# Office intake: the three decisions, and what measured them Decision record for the intake work planned 2026-09-01. The plan itself is local-only; these three choices are not, because each of them changes something a consumer can observe. ## 1. The converter binary is vendored, not resolved from PATH **Decision: operator, 2026-09-01, after research.** `pandoc` converts `docx`, `xlsx`, `pptx`, `odt` and `rtf` to text, and it enters as a **pinned wheel inside the existing `[extract]` extra** rather than as a system binary the library shells out to. The first design considered was the opposite — spawn a system `pandoc` from one allowlisted module — and three independent measurements retired it: - The `xlsx` and `pptx` readers exist only from pandoc **3.8.3**. Debian 12 ships 2.17.1.1 and Ubuntu 24.04 ships 3.1.3, so a `PATH` binary cannot deliver two of the five formats on current stable distributions. Those table rows would fail by environment rather than by design. - The `docx` reader changed its emitted output in **at least 22 of the 3.x releases**, including one change shipped in 3.6.2 and reverted in 3.6.4. A byte-exact golden over an unpinned binary is a promise about someone else's machine. - The ecosystem already made this decision: Quarto bundles pandoc to eliminate version-mismatch risk, and `pypandoc-binary` ships it as a platform wheel. Two consequences follow, and both are load-bearing: **The single-runtime-dependency rule is unchanged.** The wheel lives in the `[extract]` extra, which `pyproject.toml` already places outside that rule by construction. The default install still declares exactly one runtime dependency. **The model-free gate keeps `subprocess` in its alternation.** Because the conversion goes through an imported package rather than a process this library spawns, `src/llm_ingestion_okf/` needs no `subprocess` of its own and the gate stays exactly as it was. What the gate proves has narrowed and should be stated honestly: it proves no model vendor is reachable from `src/`, not that no process is spawned anywhere in the dependency tree. **One measured trap, recorded because it is invisible when it fires.** `pypandoc` searches `PATH` **before** its own bundled binary and selects the highest version it finds. On a machine with a newer system pandoc, the vendored wheel is silently bypassed and every determinism guarantee with it. The binary must therefore be resolved explicitly and its version asserted against a frozen literal — a check that costs nothing and is the only thing standing between the pin and a bundle built by a converter nobody chose. ## 2. Judgement lives outside the run path, as versioned data **Decision: operator, 2026-09-01.** Segment boundaries are proposed by a stdlib, model-free tool; a `tools/`-side command raises those proposals into reasoned candidates; a human ratifies or corrects; the ratification is written to a versioned plan file, and the run path only ever reads that file. `src/` remains model-free. The measured shape of the loop matters more than the shape of the diagram: - **The verdict carries its dwell time.** A ratified flag with no per-item time is unfalsifiable. The published case is 300 000+ insurance decisions averaging 1.2 seconds each, ~80 % of the appealed ones later overturned. Recording the time is what makes "adjudicated" a fact rather than a claim, and it is the same field that measures what adjudication costs. - **Rejecting is one keystroke; correcting is optional.** Measured over 2 784 annotations: people flagged *fewer* errors when flagging required typing the correction. An interface that charges for disagreement manufactures the rubber-stamping its output then claims to have avoided. - **The model leg is off by default,** so its value can be measured rather than assumed. Pre-annotation has been measured lowering a good annotator's accuracy from 98.1 % to 95.8 %. ## 3. A new profile, never a change to an existing one **Decision: operator, 2026-09-01.** A segmented bundle could not declare which upstream spec it targets: `SEGMENTED_V1` names `bundle_id`, `OKF_V0_2` names `okf_version`, and the two never intersect. Rather than add the key to `SEGMENTED_V1`, a sixth profile — `SEGMENTED_OKF_V0_2` — carries both. This follows the standing rule that upstream support is additive, expressed as a new profile and never as a migration. It also avoids resting on an unverified premise: extending `SEGMENTED_V1` would have been safe only if nobody had adopted it, and "nobody has adopted it yet" is a claim about other repositories that this one cannot check. ## What these three do not settle The acceptance rubric these decisions are measured against (K1–K7) is owned at programme level, spans this library and its consumers, and is not closed here. This work produces numbers on K1–K5 with their denominators; the thresholds that turn a number into a verdict belong to whoever owns the rubric.