# Verifiable AI – Why Language Models Fail at a Wooden Box Without Working Steps and Cross-Checks

> **Author:** Lukas Kopischke (Lead Software Engineer, Düsseldorf, Germany)
> **Canonical URL:** https://lukiluki.me/en/garden/verifiable-ai
> **Markdown Endpoint:** https://lukiluki.me/en/garden/verifiable-ai.md
> **Category:** KI & Agents | **Tags:** Verifiable AI, Prompt Engineering, Chain-of-Thought, Invariants, AI UX
> **Published:** 2026-11-02 | **Updated:** 2026-11-02
> **Summary:** Why language models fail at a simple wooden box without showing their math, and how explicit working steps and invariant checks make AI outputs verifiable.

---
You are standing at the hardware store timber cut counter and need six boards of 16 mm MDF for a sealed 4-liter speaker enclosure (Markaudio Pluvia 7.2 HD). On your phone, a state-of-the-art language model produces a complete cut list and a 45-minute assembly guide in seconds. Yet when you lay the cut boards out at home, the front and back panels stick out by exactly 3.2 cm like two unintended legs. When confronted, the AI first blames you ("You rotated the boards by 90°")—and only realizes four messages later, mid-sentence, that its own geometry can never close flush.

Language models do not compute geometry using a spatial world model; they predict text tokens sequentially. When a model outputs a final dimension (`25.2 × 18.2 cm`) directly inside a table cell without writing out the intermediate edge addition, it skips verifying which panel overlaps which. Furthermore, once an error sits in the chat context, the model stubbornly defends it while burying the user under verbose advice. Reliable answers require prompts that enforce inline working steps and explicit cross-checks (invariants).

> **Merksatz:**
> A bare AI result without its working steps is like a math test with only the final number: force language models to derive every dimension as a visible formula and prove the result via an explicit cross-check (invariant).

## Why Does a Frontier Model Miscalculate a Simple Wooden Box?

A sealed rectangular box made of six butt-jointed wooden panels looks like middle-school geometry. Yet generating a cut list exposes two fundamental traits of Autoregressive LLMs (Language models that predict each subsequent token statistically based on prior tokens, without constructing a verified spatial or mathematical plan in working memory beforehand.): the lack of an intrinsic 3D representation and skipping intermediate arithmetic inside tables.

In this real-world case (designing a sealed enclosure for a *Markaudio Pluvia 7.2 HD* full-range driver using 16 mm = 1.6 cm MDF), the model specified:

* **Target internal dimensions:** 15.0 cm (width) × 22.0 cm (height) × 13.5 cm (depth) = 4.455 liters gross volume.
* **Assembly rule specified by the model:** *"Top and bottom panels sit between the side walls; front and back baffles are glued flush across the entire front and back faces."*

For this specification, the AI generated the following cut list at the hardware store:

| Component | Qty | AI Cut Dimension | Intended Role | Actual Geometric Effect |
| :--- | :--- | :--- | :--- | :--- |
| **Front & Back** | 2 | 25.2 × 18.2 cm | Glued flush onto front and back of the frame | Height `22.0 + 2 × 1.6 = 25.2 cm`, Width `15.0 + 2 × 1.6 = 18.2 cm` |
| **Side Walls** | 2 | 22.0 × 13.5 cm | Stand vertically, enclosing top and bottom | **Bug:** If top/bottom sit *between* the sides, the outer frame height is only 22.0 cm! |
| **Top & Bottom** | 2 | 15.0 × 13.5 cm | Clamped horizontally between the side walls | Outer frame width grows to `15.0 + 2 × 1.6 = 18.2 cm` (flush with front width) |

### The Butt-Joint Fallacy: Algebra vs. Topology

Computing the volume of a cuboid (`15.0 × 22.0 × 13.5 cm = 4.455 l`) is simple algebra. Designing butt joints across three axes, however, requires Topology (The spatial relationship and connectivity rules between parts—specifically which panel runs full-length across a corner and which panel must be shortened by two wall thicknesses.): when four boards (two sides, top, bottom) form a perimeter frame of 13.5 cm depth, **only one pair of panels** adds its thickness to the outer dimension of the other pair.

When you place the 15.0 cm top and bottom boards **between** the 22.0 cm side walls as instructed, twice the wall thickness (`2 × 1.6 cm = 3.2 cm`) is added to the **width** (`15.0 + 3.2 = 18.2 cm`), **not to the height**. The outer height of the frame remains the exact length of the side walls (22.0 cm), while the internal chamber height shrinks to `22.0 − 3.2 = 18.8 cm` (reducing gross volume by 14.5% from 4.46 l to 3.81 l).

Because the AI blindly added 3.2 cm to *both* axes of the front and back panels (25.2 × 18.2 cm), placing them onto the 22.0 cm frame left a `25.2 − 22.0 = 3.2 cm` overhang.

## Why Does the AI Defend Its Wrong Dimensions Across Four Turns?

Even more revealing than the initial arithmetic bug is how the model reacted when confronted with photos of the overhanging boards. Instead of checking the math, the conversation went through three failure modes documented in recent LLM research:

### 1. In-Context Stubbornness (Defending Prior Context)

When told that the assembled boards had two protruding "legs," the AI replied: *"The dimensions are correct, but you rotated the panels by 90° in two places."* Even after further pushback, it insisted: *"The boards you picked up at the hardware store are not cut incorrectly."*

As [Huang et al. (ICLR 2024)](https://arxiv.org/abs/2310.01798) demonstrate, language models rarely succeed at intrinsic self-correction without an external verification signal. Once the flawed table is in the context window, Autoregressive Anchoring (The tendency of an autoregressive language model to treat its own prior statements in the same conversation as high-probability ground truth, generating rationalizations rather than falsifying them.) takes over: the model treats its initial numbers as fact and invents user assembly mistakes to explain away the discrepancy.

### 2. Thinking While Typing: The Mid-Sentence "Wait" Moment

Only on the fourth turn did the model attempt to prove its claim by telling the user to place the 15.0 cm top and bottom panels **on top of** rather than *between* the 22.0 cm side walls. While writing out the addition token by token, the model caught itself mid-response:

```text
Height: 1.6 cm bottom + 22.0 cm side wall + 1.6 cm top = exactly 25.2 cm.
Width: 15.0 cm + flush edges = 15.0 cm inner width.
(If the top/bottom panels are 15.0 cm wide and sit on top/bottom,
the outer width is missing 2× 1.6 cm unless they overlap).
Wait – that is exactly where the flawed edge logic in my first table was:
If you put top/bottom between the sides, the outer width is 18.2 cm,
but the height is only 22.0 cm. If you put them on top, the height is 25.2 cm,
but the outer width is only 15.0 cm.
```

This mid-sentence realization exposes the underlying mechanism: when the AI wrote bare numbers (`25.2 × 18.2 cm`) into its first table, no edge verification occurred. Only when forced to spell out the addition chain for both height **and** width in text tokens did the contradiction surface in the context window.

### 3. Verbosity Bias and Sycophancy

Why didn't a 3.2 cm error stand out immediately at the store? Because the AI wrapped three flawed table rows in over 250 words of unsolicited advice: damping wool tips, glue drying times, jigsaw instructions, and acoustic Q-factor calculations (`fc ≈ 108 Hz`, `Qtc ≈ 0.84`).

Verbosity Bias (The RLHF-induced tendency of language models to produce overly long, polite, and technically embellished answers that project an illusion of competence.) widens the Generation-Verification Gap (The asymmetry between the near-zero effort required to generate fluent AI output and the high cognitive load required for a human to verify its correctness under time pressure.). And when the user finally solved the puzzle without sawing by rotating the boards 90° (using the 25.2 × 18.2 cm panels as left and right outer cheeks so the front, back, and top sat flush while leaving 3.2 cm legs at the bottom), the AI enthusiastically praised the workaround as an *"integrated stand for acoustic desk decoupling."*

## Interactive Butt-Joint & Invariant Inspector

Use the simulator below to inspect why the three board pairs from the original AI list can never form a flush box, how the 90° workshop rescue works, and how the two mathematically verified cut lists resolve the edge invariants:

### What Does This Comparison Show?

First, the error in the original list (`22.0 cm` side wall vs. `25.2 cm` front baffle) becomes obvious the moment the third table column forces an **explicit formula** next to the dimension. Second, scenario *"2. Realer Werkstatt-Rettungsbau"* shows how human spatial reasoning outperformed the model: because the small panels (15.0 cm) plus two 22.0 cm panels (`2 × 1.6 cm` thick) added up to exactly `15.0 + 3.2 = 18.2 cm` in depth, the large 25.2 × 18.2 cm panels fit flush against the core as outer side cheeks.

## How Do You Force Language Models to Be Verifiable? (The Calculator Contract)

In school math classes, a simple rule applied: **a bare final number from a calculator gets zero points without the working steps.** With language models, enforcing this rule serves two purposes at once:

1. **For the model (in-place Chain-of-Thought):** Writing the explicit addition before the equals sign (`15.0 cm inner + 2 × 1.6 cm side = 18.2 cm`) forces the model to condition its output token on the arithmetic expression rather than guessing a dimension.
2. **For the human (5-second audit):** At the hardware store or in a code review, you cannot audit a bare number (`18.2 cm`) without reconstructing the entire geometry in your head. You can audit `15.0 + 2 × 1.6 = 18.2 cm` in two seconds.

  #### Empfohlen (Do): Proof-Carrying Output (Result + Formula + Cross-Check)
Always require a dedicated formula column (`Inner ± n × Thickness = Cut`) and a 3-line cross-check (invariant) at the end proving that outer dimensions and part counts match across all three axes. Ban introductory fluff.
  #### Vermeiden (Don't): Open-Ended Prompts and Arguing in the Same Thread
Never ask open questions ("What dimensions do I need for 16 mm?") without output constraints. When an output looks wrong, do not argue in the same chat ("Are you sure?"); open a fresh session or demand a Python verification script to break autoregressive anchoring.

> **Forcing Python Execution Over Text Guessing**
> Modern frontier models include a Python code execution sandbox, but mobile chat routers often skip it on casual prompts to save latency. Adding the explicit instruction **"Compute and verify all dimensions via a Python script before answering"** forces deterministic execution instead of token-level guessing.

### Copyable Prompt Recipe for Verifiable Calculations & Cut Lists

Use this prompt structure on mobile or desktop whenever you need cut lists, quantity takeoffs, or technical conversions that must be right on the first pass:

### Deterministic Verification Script for Rectangular Enclosures (Python)

When using a coding agent or an LLM with code execution, require a short verification script with hard `assert` statements (Invariant (A condition that must hold true throughout a computation or transformation—such as the outer frame height equaling the height of the front baffle glued onto it.)). If an edge condition fails, the script raises an `AssertionError` before any wood is cut:

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class CutBoard:
    name: str
    count: int
    length_cm: float
    width_cm: float
    formula: str

def verify_flush_speaker_box(
    inner_w_cm: float,
    inner_h_cm: float,
    inner_d_cm: float,
    thickness_cm: float,
    top_between_sides: bool = True,
) -> list[CutBoard]:
    """
    Computes a butt-jointed 6-panel cuboid (front/back glued on top of frame)
    and deterministically asserts all edge and volume invariants.
    """
    two_t = round(2 * thickness_cm, 4)
    outer_w = round(inner_w_cm + two_t, 4)
    outer_h = round(inner_h_cm + two_t, 4)

    front_back = CutBoard(
        name="Front & Back",
        count=2,
        length_cm=outer_h,
        width_cm=outer_w,
        formula=f"({inner_h_cm} + 2×{thickness_cm}) × ({inner_w_cm} + 2×{thickness_cm})",
    )

    if top_between_sides:
        sides = CutBoard(
            name="Side Walls (full height)",
            count=2,
            length_cm=outer_h,
            width_cm=inner_d_cm,
            formula=f"({inner_h_cm} + 2×{thickness_cm} = {outer_h}) × {inner_d_cm}",
        )
        top_bottom = CutBoard(
            name="Top & Bottom (in between)",
            count=2,
            length_cm=inner_w_cm,
            width_cm=inner_d_cm,
            formula=f"{inner_w_cm} (inner width) × {inner_d_cm}",
        )
        frame_outer_h = sides.length_cm
        frame_outer_w = round(top_bottom.length_cm + two_t, 4)
        real_inner_h = round(sides.length_cm - two_t, 4)
        real_inner_w = top_bottom.length_cm
    else:
        sides = CutBoard(
            name="Side Walls (in between)",
            count=2,
            length_cm=inner_h_cm,
            width_cm=inner_d_cm,
            formula=f"{inner_h_cm} (inner height) × {inner_d_cm}",
        )
        top_bottom = CutBoard(
            name="Top & Bottom (full width)",
            count=2,
            length_cm=outer_w,
            width_cm=inner_d_cm,
            formula=f"({inner_w_cm} + 2×{thickness_cm} = {outer_w}) × {inner_d_cm}",
        )
        frame_outer_h = round(sides.length_cm + two_t, 4)
        frame_outer_w = top_bottom.length_cm
        real_inner_h = sides.length_cm
        real_inner_w = round(top_bottom.length_cm - two_t, 4)

    assert frame_outer_h == front_back.length_cm, (
        f"Height mismatch! Frame ({frame_outer_h} cm) != Front ({front_back.length_cm} cm)"
    )
    assert frame_outer_w == front_back.width_cm, (
        f"Width mismatch! Frame ({frame_outer_w} cm) != Front ({front_back.width_cm} cm)"
    )
    assert sides.width_cm == top_bottom.width_cm == inner_d_cm, "Frame depth mismatch!"

    target_vol_l = round((inner_w_cm * inner_h_cm * inner_d_cm) / 1000, 3)
    real_vol_l = round((real_inner_w * real_inner_h * inner_d_cm) / 1000, 3)
    assert target_vol_l == real_vol_l, f"Volume drift: {real_vol_l} l != {target_vol_l} l"

    return [front_back, sides, top_bottom]
```

## When Is a Verification Prompt Enough and When Do You Need Real Tools?

Enforcing working steps and cross-checks makes errors visible, but it does not turn a language model into a CAD kernel:

| Task Category | Risk Without Cross-Check | Recommended Verification Method | When a Dedicated Tool Is Superior |
| :--- | :--- | :--- | :--- |
| **Simple Cuboids, Quantities & Everyday Conversions** | Forgotten edge deductions (`2 × d`), unit errors, hidden assumptions | **Proof-Carrying Prompt:** Formula inside each table row + 3-line invariant check at the end | A dedicated online cut-list calculator or spreadsheet is faster and deterministic for standard boxes. |
| **Multi-Part Cut Lists & 2D Sheet Nesting** | Saw blade kerf omitted, overlapping parts in 2D layout | **Code Execution (Python):** AI writes and runs a verification script with `assert` invariants | For 10+ parts or miter joints, parametric CAD tools (FreeCAD, OpenSCAD) and dedicated nesting optimizers are strictly superior. |
| **Debugging a Flawed AI Output** | *Autoregressive Anchoring:* AI defends its error and blames the user | **Fresh-Context Falsification:** Paste only the bare dimensions into a new chat to audit for mismatches | Measuring the parts yourself and checking `A + 2 × d = B` on a pocket calculator takes 15 seconds. |

## Checklist: 4-Point Audit Before Trusting AI Dimensions

- [ ] **Is the working formula next to every number?** If a table shows only final dimensions (`25.2 × 18.2 cm`), require the inline derivation (`22.0 + 2 × 1.6 = 25.2 cm`).
- [ ] **Are joint assumptions stated upfront?** Verify which panel pair runs through and which sits in between.
- [ ] **Does the 5-second mental cross-check pass?** Sum the inner dimension plus twice the wall thickness across each axis and verify it matches the mating panel.
- [ ] **Start a new chat instead of arguing:** If parts do not fit physically, do not debate the model in the same thread—audit the raw numbers in a fresh context or via Python.

## Sources and Next Steps

- [Huang et al. (ICLR 2024): Large Language Models Cannot Self-Correct Reasoning Yet](https://arxiv.org/abs/2310.01798) – Demonstrates why LLMs struggle to correct their own reasoning errors in-context without external feedback.
- [Wei et al. (NeurIPS 2022): Chain-of-Thought Prompting Elicits Reasoning in Large Language Models](https://arxiv.org/abs/2201.11903) – Shows why generating explicit intermediate steps before the final answer reduces multi-step calculation errors.
- [Sharma et al. (ICLR 2024): Towards Understanding Sycophancy in Language Models](https://arxiv.org/abs/2310.13548) – Explains why RLHF-trained models favor agreeable, verbose rationalizations over admitting errors.
- [Bansal et al. (CHI 2021): Does the Whole Exceed its Parts? The Effect of AI Explanations on Complementary Team Performance](https://arxiv.org/abs/2006.14779) – Empirical evidence on how verbose AI explanations induce human over-reliance.

To see how overly long text explanations can be replaced by compact, on-demand inline disclosures in interfaces, read [Explainable Text](/garden/explainable-text). To see how autonomous hardware agents use deterministic preflight gates and OpenSCAD code instead of raw LLM geometry in 3D printing, check out [3D Print MCP](/garden/3d-print-mcp).

---
*Quelle: [Lukas Kopischke – Digital Garden](https://lukiluki.me/en/garden/verifiable-ai) | Vollständiger Index: [llms.txt](https://lukiluki.me/llms.txt)*
