# NativeCAD 0.11.1 "Järvi" — a rod unioned straight through a rod is analytic

**125 tools, nothing added, removed or renamed — every 0.11.0 call keeps working.** A patch release for one kernel defect a user hit on the first thing they tried.

## The defect (CADSB-1005, reported by Chris Wilson, 2026-09-18)
Two `cad_cylinder`s with perpendicular, intersecting axes — a thin rod straight through a thicker one — followed by `cad_boolean_union` came back as dense striations: the thin rod's wall and the junction were **554 PLANE faces**. Watertight, −0.14 % on volume, and no cylindrical face left on either rod, so `cad_fillet_edges` had nothing to pick.

`ops/cylCylEdge.js` (the cylinder-on-cylinder analytic path, CADSF-984) built a union only as a single **boss** — one end of the tool outside the wall, the other embedded — and refused a tool whose two ends are both outside on opposite sides (`cylcyl_boss_root_not_embedded`, "a union of a through rod is not the boss this path builds"). `ops/boolean.js` then fell through to the general classify-and-stitch engine, exactly as designed, and that engine's answer is triangles.

## The fix
The through rod is now **built on the analytic path** as two bosses back to back: one Steinmetz quartic per side of the outer wall — the same (Ro, ∓1) crossings the subtract branch already takes for a radial through hole — each bounding the tool's wall out to its own cap. On a **tube** the tool wall bridging the bore between the two bore quartics is kept as material boundary and each bore face gains its quartic as a hole.

Measured (`tests/test_cadsb-1005.js`, 22 assertions, red on the base code at A1):
- Ø10 rod through a Ø20 × 60 rod: **554 → 10 faces** (6 CYLINDRICAL + 4 PLANE), `checkFull` clean, volume within **0.014 %** of πR²H + πr²L − V_bicyl(R, r) at chord 0.001 (the general engine's answer was −0.14 %), every authored edge with a recorded tolerance (worst 1.8e-6 against a 1e-5 target).
- Ø10 rod through a Ø60 × 3 tube: **14 faces**, four crossings, volume within 0.007 %.
- The tool on the primitive's own seam (+X, +Y, −X) — CADSF-1018's re-seam takes it; analytic, 10 faces, clean.
- The executor route (`cad_cylinder` + `rotate` → `cad_boolean_union`) returns the same 10-face body.
- Unchanged: the single boss (root embedded) still builds as one crossing; a skew pair and a rod that ends *inside* the far wall are not taken by this path.
- `tests/test_cadsf-1064.js` §H: a bleed-pad root through the barrel is a through-rod union and now builds (+8 faces) where it used to refuse.

What a caller might key off: `regime` / `engineTrail` for this pair now reads `cyl-cyl-analytic`; the result's `cylCyl.crossings` has two entries for a rod, four for a tube.

## Known — filed, not hidden
- **Filleting the resulting saddle edges refuses BY NAME** (`blend-sel-non-planar-support`): the convex, unequal-radius cylinder/cylinder canal band does not exist yet. **CADSB-1006** — the spine is the same closed-form Steinmetz family (offset cylinders R+ρ and r+ρ), so it needs no marching. `test_cadsb-1005.js` §F pins today's refusal and flips when it lands.
- **CADSB-1007**: every post-commit site mirror since 5d7b5596 (2026-09-17) had been refused by the CADSF-413 parity gate (`parity-web-matrix.json` one line stale). Regenerated in cb5245c1; the mirror is unblocked with this release.
- `tool-list-budget.test.js` is **red on master before and after** this release: `tools/list` is 413,175 B against the 409,600 B ceiling. No tool description changed here; filed separately.

## Gates
schema-sync 481/481 · mcp-smoke `dist/server.min.js` = `bin/nativecad-mcp.js` = 125 tools · bundle-smoke on the shipped `.mcpb` (unlicensed host: boot, tools/list, licence gate) · `dist/server.min.js` byte-identical across the tree build, the tgz and the `.mcpb` (sha256 `d0ba5645…`).

**Downloads are served from featureboard.ai** (see `latest.json` for bytes + sha256):
https://featureboard.ai/nativecad/releases/nativecad-mcp-0.11.1.mcpb
Staged kernel: git cb5245c1, tree 1d637eabca41 (347 files). Built with `SOURCE_DATE_EPOCH` pinned to cb5245c1 from a clean `git archive` export, esbuild 0.28.1.
