# Automatic translation — no human review gate — decision record

> **Deliverable for ADO PBI #1455** — "Make translation fully automatic; remove the human review
> gate." This is the durable record of the product pivot the implementation executed against.
>
> **Scope of this doc:** the decision + the trade-offs behind it, and a precise account of what changed
> in the code and what was deliberately preserved. The code change shipped with this PBI; this record
> is its rationale and its boundary (what is out of scope / future).
>
> **Date:** 2026-06-25.
>
> **It supersedes a prior product invariant.** It retires the "*apprenticeship, not a batch job*" /
> per-batch human approval gate that [`spec.md`](https://docs.getkenly.com/spec) and
> [`user-stories.md`](https://docs.getkenly.com/user-stories) used to describe, and subsumes the auto-advance work. It also
> retires the premise of Feature **#1365** that "the human-in-the-loop quality gate is the product's
> reason to exist."

---

## 0. TL;DR — the decisions

| # | Question | Decision | Consequence |
|---|----------|----------|-------------|
| D1 | **Is there a human review/approval gate?** | **No.** Kenly is a **fully automatic** translation service. Upload → upfront cost estimate → commit/pay → the whole book translates itself → read/export. | The per-page approve / reject / edit and the source-language confirm/correct steps are gone. Processed pages are **auto-approved by the system**. |
| D2 | **How does the batch ladder escalate?** | **Automatically.** Still calibrate on one page first, but each completed batch **auto-confirms** (increments `ApprovalCount`, widening the next batch) and the next batch is enqueued by `IBatchAutoAdvancer` (on the JobProcessor) with a **Worker backstop**. | `Calibrating → Processing → Complete` with auto-confirm; no human action between batches. `BatchPolicy` (1 → 5 → 25 → 100 → rest) is unchanged. |
| D3 | **What can stop an in-flight book?** | **Only affordability.** When the next batch would exceed the wallet balance, processing **pauses cleanly** (no error) and shows the "Add credit" CTA (#1396). A top-up resumes it. Failed pages are recovered by explicit **retry**. | The pre-commit cost estimate (#1375) + the wallet are the sole gate. Retry is the one remaining explicit control. |
| D4 | **What does the reading screen do?** | **Read-only.** Page through the translation (original scan beside the English), see per-page status, export. No decision buttons. | The completion notification fires **once when the whole book finishes** ("Translation ready"), not per batch. |

---

## 1. The decision

**Remove the human review gate. Kenly is a fully automatic translation service with no
human-in-the-loop review.** A user uploads a book, sees an upfront cost estimate, commits/pays, and the
**entire book translates automatically** with zero per-page interaction; they then read and export the
finished translation. Like it or leave.

This is a product call by the product owner, not an engineering convenience:

- **The decision burden was too high.** Asking a reader to approve/reject/correct every page — for a
  book that can run to hundreds or a thousand pages — is a worse experience than a finished translation
  delivered for a known upfront price. The gate that was framed as "the product's reason to exist"
  turned out to be the product's biggest friction.
- **The tech for *meaningful* per-page human intervention isn't the product.** A reader correcting raw
  machine-translation output, block by block, is neither what most users want nor where the quality
  leverage is (that is in the OCR/translation models and an optional LLM polish pass — see
  [`spec.md §8`](https://docs.getkenly.com/spec), M3). Surfacing a correct/incorrect decision the user is poorly placed to
  make added burden without commensurate quality.
- **An automatic service is a cleaner promise.** "Upload, pay a known price, get the whole book" is a
  product anyone can understand; "apprentice the machine page by page" is not.

---

## 2. D1 — No human review/approval gate

**Recommendation. Removed.** The page lifecycle is now `Pending → Processing → Approved`, where
**`Approved` is reached by the system auto-approving a cleanly-processed page** — there is no human
approve / reject / edit-before-approve, and no confirm/correct of the detected source language.

**Options considered.**

| Option | Verdict |
|---|---|
| **(a) Remove the gate entirely — fully automatic** | ✅ **Chosen.** Matches the PO's product call; lowest friction; a clear upfront-price promise. |
| (b) Keep the gate but default it to auto-approve, opt-in to review | ❌ Carries the entire review UI + endpoints as dead weight for a path nobody is meant to take; invites drift and confusion about the "real" product. |
| (c) Keep per-page review, soften it (batch-approve) | ❌ Still asks the user to make per-book decisions; does not solve the decision-burden problem the PO raised. |

**Trade-offs.** We give up the (theoretical) per-page human quality safety net. We accept this: the
quality lever is the models + an optional polish pass, not a reader's block-by-block edits. The
`AwaitingReview` / `AwaitingApproval` enum members were originally **retained for back-compat** with
any project persisted under the old model — the automatic flow never entered them.

> **Update (2026-06-27).** Those vestigial states were **removed entirely** (along with `PageStatus.Rejected`):
> `ProjectStatus` is now `Created · Calibrating · Processing · Complete · Failed`, `PageStatus` is
> `Pending · Processing · Approved · Failed`, and the `AwaitingReview` queue kind / lifecycle bucket /
> status filter are gone. The product owner directed the full removal once the DB held no pre-pivot
> records. Cancellation (`Cancelling`/`Cancelled`) and a possible explicit `Paused` state are tracked
> separately (see §7).

**What changed in code.** The approve / reject / edit-translation / confirm-source-language endpoints
and their state-machine transitions were removed; `ProcessNextBatchAsync` now **auto-confirms** a
completed batch instead of parking pages for review.

---

## 3. D2 — Automatic batch escalation (calibrate first, then auto-advance)

**Recommendation. The batch ladder survives; only its trigger changed.** The flow still starts narrow
— a single **calibration page** — and widens 1 → 5 → 25 → 100 → rest. What changed: each completed
batch **auto-confirms** (increments `ApprovalCount`, which `BatchPolicy.NextBatchSize` reads to widen
the next batch) and the next batch is enqueued **automatically** by `IBatchAutoAdvancer`
(`BookTranslation.Core/Abstractions/IBatchAutoAdvancer.cs`, implemented in
`BookTranslation.Infrastructure/Jobs/BatchAutoAdvancer.cs`) driven from the `JobProcessor`, with the
**Worker as a backstop** so an in-flight book reaches completion even if the API process churns.

The project state machine becomes:

```
Created ──Normalize──► Calibrating ──ProcessNextBatch (1 page, auto-confirm)──► Processing
   Processing ──auto-advanced ProcessNextBatch (5 → 25 → 100 → rest, each auto-confirms)──► Processing …
   Processing ──(no Pending pages left)──► Complete
```

**Options considered.**

| Option | Verdict |
|---|---|
| **(a) Keep the calibrate-narrow ladder, advance it automatically** | ✅ **Chosen.** Keeps the proven "don't bulk-process before the first page looks sane" instinct and the resumable per-batch transitions, while removing the human pause. |
| (b) Drop the ladder, process the whole book in one batch | ❌ Loses the cheap early signal (a totally broken OCR config is caught after 1 page, not after 1000) and the granular resumability; no upside once the human gate is gone. |

**Trade-offs.** The "calibration page" no longer gives a human a look before scale — it is now purely a
system warm-up / early-failure signal. We keep it because it is nearly free and preserves the
batch-granular resumable transitions; removing it bought nothing.

---

## 4. D3 — Affordability is the only gate (+ retry)

**Recommendation. The only thing that pauses an in-flight book is money.** The pre-commit cost estimate
(#1375) plus the wallet are the sole brake. When the next batch would exceed the balance, the
auto-advance **pauses cleanly** at `Processing` — **not an error** — and the UI shows the "Add credit"
CTA (#1396); topping up resumes the chain exactly where it stopped. The one remaining **explicit**
recovery control is **retry** of a `Failed` page (`Failed → Processing`), owning the affordance #1340
referenced and #1367 stories.

**Options considered.**

| Option | Verdict |
|---|---|
| **(a) Pause cleanly + "Add credit" + auto-resume on top-up** | ✅ **Chosen.** Treats running out of credit as an expected state, not a failure; resumable by construction. |
| (b) Hard-fail the project when over balance | ❌ Punishes a normal, recoverable situation; loses work / confuses the user. |
| (c) Let it overdraw and bill later | ❌ Unacceptable for a prepaid wallet model; invites abuse and disputes. |

**Trade-offs.** A long book can stop midway if the wallet runs dry — but that is the *desired*
behaviour for a prepaid service, and the clean pause + one-click top-up makes it a non-event. The
upfront estimate (#1375) is what keeps this rare: the user commits knowing the projected cost.

---

## 5. D4 — Read-only reading experience + single completion notification

**Recommendation. The review screen is now a read-only reading view.** The user pages through the
translation (each page's original scan beside its English), sees per-page status, and exports — there
are **no approve / reject / edit decision buttons**. The completion notification fires **once, when the
whole book finishes** ("Translation ready"), replacing the old per-batch "a batch is ready for your
review" notification (#1352, reframed).

**Trade-offs.** Fewer touch-points means the user gets one clear "it's done" signal instead of a stream
of per-batch prompts — consistent with the hands-off product. Resume-where-you-left-off (#1353) stays,
but now it resumes *reading*, not *reviewing*.

---

## 6. Explicitly preserved (NOT removed by this pivot)

The pivot is surgical — it removes the human gate, not the engine. These all **survive unchanged in
intent**:

- **The resumable state machine.** Every operation is still one discrete, guarded, **persisted**
  transition; `project.json` is still the authoritative resumable state; a fresh process still
  continues from disk. Auto-advance chains transitions; it does not make them implicit.
- **The calibrate-first batch ladder.** 1 → 5 → 25 → 100 → rest, capped to remaining `Pending` pages.
  `BatchPolicy` is untouched.
- **The spend / affordability gate.** The estimate-vs-balance cost gate and the credit wallet are now
  the *primary* (and only) gate, not a secondary one.
- **Failed-page retry.** The one explicit recovery control (`Failed → Processing`).
- **The per-page pipeline.** normalize → layout → OCR → language detect → block-by-block translate →
  assemble → export, all as in [`spec.md §4`](https://docs.getkenly.com/spec).

---

## 7. Out of scope / future

- **Per-page-range selection** — "upload a PDF and translate only pages X–Y / specific pages" (#1386,
  #1376). The automatic flow currently translates the whole uploaded book; selecting a sub-range to
  pay for is a separate, future enhancement, not part of this pivot.
- **An additional cost-estimate requirement** — any tightening of the upfront estimate (e.g. a hard
  confirm step, per-file actual-vs-estimate reconciliation beyond #1397–#1399) is tracked as a
  **separate PBI**, not folded in here.
- **Translation-quality controls** — the optional LLM polish pass and per-book OCR-engine choice
  (Kraken vs Surya for historical type) remain M3 work in [`spec.md §8`](https://docs.getkenly.com/spec); they are the real
  quality lever now that per-page human correction is gone.

---

## 8. Impact on existing docs + tickets

- **[`spec.md`](https://docs.getkenly.com/spec)** — §1 goal, §2 principles, §3 state machine (project + page diagrams), §4
  pipeline step 6, the batch-ladder note, §7 API table (approve/reject removed, retry surfaced), §8 M1
  description, and §9 testing table were rewritten to the automatic model.
- **[`user-stories.md`](https://docs.getkenly.com/user-stories)** — product-intent header, the Reader/Translator persona,
  Feature **#1365** (renamed *Core Translation & Reading Experience*; #1366 edit-before-approve and
  #1368 confirm-source-language retired; #1367 retry survives), the retro-documented flows in §6
  (approve/reject removed; read-only reading + auto-advance documented), #1340/#1352 queue + notification
  wording, and the onboarding gap.
- **`CLAUDE.md` / `README.md`** — the top-line one-liners that described a "human approval gate between
  every batch escalation" were corrected to the automatic-service model; the Worker description changed
  from "continues approved projects, never approves" to "auto-advances in-flight projects to completion."
- **Feature #1365** premise ("the human-in-the-loop quality gate is the product's reason to exist") is
  **retired**; this PBI subsumes the auto-advance work.
