Repository navigation
v1.10.0 — Closure (table alignment 3-layer rework + measurement/gate family)
Release 1.10.0 notes
Tag: v1.10.0
Date: 2026-09-30
Train: Closure batch — table cell alignment rework + measurement / gate family
Cut: docs-only, on top of a179f09 (the code tree is byte-identical to b4e4a55)
Summary
v1.10.0 closes the P-002 / P-020…P-027 track. The only backend behaviour change is P-002 (table cell
alignment): the single "uniform grid geometric containment" path in table_backfill becomes three layers —
T1 value match (row-band + column-window anchored) → T2 geometric (unchanged) → T3 text cluster — with a
backfill sanity gate in front of the amber (value-replacement) branch. Everything else is measurement tooling,
documentation gates, promotion of R&D conclusions, and Lite-era clean-up. Cloud validation ran three gates
(G4/G5/G6) with real before/after numbers.
Added
- P-002 — three-layer table cell alignment (value match → geometric → cluster) (2026-09-29): see Summary.
New host modulebackend/app/services/table_alignment.py(zero migration: the three existing functions stay put,
one-way importbackfill → alignment). Contract additions are purely additive:cell_align_reason(per-cell
8-value reason grid;nullfor non-candidate cells),quality.table_backfill.align_reason_counts(8 keys always
present,sum == candidates),reasononmismatch_details[]and on debug records, a 6th review-table column,
andsibling_bboxessibling-table neighbourhood exclusion.
Geometry constants calibrated on real layouts:EXP_X_MIN_RATIO0.15 → 0.05; the other three unchanged.
Golden pins: bank 12×value_match(was 6 green / 6 red), symbol 4×value_match(was 4 red), and a new
non-uniform gold sample at 5 green / 2 honest red.
Correctness evidence: the old funnel silently mis-filled 4 cells on mamba p12 (e.g. a numeric cell backfilled
with a column-header label); the new sanity gate blocks all four as reviewable red. - P-020 — OCR quality measurement harness M1+M2 (2026-09-22): a machine-local bypass instrument under
scripts/measure/(deliberately not versioned). It never imports the app — it consumes the pipeline's result
JSON — so historical results stay re-measurable on the same scale. Degraded-specimen synthesis from one forward
affine matrix, weak GT from a born-digital text layer, line-level CER (micro/corpus/macro), LCS reading order,
table / non-table / digit slices, cell accuracy, a pinned 15-column CSV and an HTML report. Pinned design points
D2 (char-only edit-distance DP with a fixed equal-cost tie-break), D7 (GT quad-ised through the same forward
affine, exact clipping) and D8 (char-level provenance declared structurally unmeasurable). - P-022 — retired-reference (tombstone) gate (2026-09-24): an outward-facing doc that references a path / port /
command / module deleted by a past retirement fails, unless the same line states that it was retired — a notice
is documentation, a stale instruction is a defect. Literal substring tokens only: no regex, nosubprocess, no
writes. Scope is an allow-list; archived material is exempt with a printed reason. Wired by import into
audit_agent_ops.py, so the existing requiredagent-ops-auditcheck runs it — no CI configuration change. - P-023 — test stub scope is now both a rule and a gate (2026-09-25): born from a P-021 CI run that reddened
Phase A in a file the branch never touched, because a module-levelsys.modules["paddle"]stub is installed at
collection time and outlived the test that needed it.scripts/test_registry_audit.pygains check 5
(check_stub_scope, stdlib AST, fail-closed on unparsable files), wired into the required audit check, and the
kernel testing doc states the criterion plus both failure modes. - P-026 — public quality case study (2026-09-26):
docs/demo/QUALITY_CASE_STUDY.mdtells the P-021 story end to
end — a silent OCR coordinate defect (scale drift 1.1084–1.2257, non-rigid, rotations flattened) found by the
local measurement harness, traced to one engine preprocessing default, fixed by one init parameter, and locked by
contract tests. Before/after: 12/15 fixture×spec combos improved, 0 regressions, text volume recovered up to 2.1×,
and 26/26 responses byte-identical across two independent cloud runs. - P-027 — table-structure GT reconciliation on WTW (P-018 P2) (2026-09-28): the local harness gains a
structure-side scale for tables on the public WTW dataset (ICCV 2021; 14,581 photographed / scanned / web table
images) — an XML→GT adapter, a self-implemented structure-only TEDS (APTED-style ordered-tree distance with pinned
insert/delete/update costs), and anevaluate-tableCLI scoring detection recall/IoU, row/column/merge occupancy
agreement, and S-TEDS. Predictions are captured once into a content-addressed cache, so metric revisions cost no
GPU time. Baseline (2026-09-28, 300-image stratified subset, seed=42):grid_exact145/300,grid_f1mean 0.8989,
mean_s_teds0.8399,table_recall0.8300. WTW's ground truth carries no cell text, so the content dimension is
out of scope here; scores are reported as our own protocol, not an official leaderboard.
Removed
- Lite track references stripped from all outward-facing material (documentation catching up with the v1.8 code
deletion, not a capability change), and dead Lite instructions removed from the living docs. - Lite-era files deleted (explicitly authorized, second pass): the 2.9 MB
DocVision_Lite.gif, the dead
lite-preview.e2e.jsspec, the brokenbootstrap_lite_models.{py,sh}, the orphan
packages/docuvision-core/models/tree, and two stale test-support files. Verified after deletion: core
pytest -qstill reports 13 passed, matching the v1.8 baseline. .zcode/retired by user decision (expected unused for the next six months), together with its.gitignorerule
and PENDING P-006.- ZCode retired from the agent roster; review duty becomes "whoever takes the round", not a named agent.
Changed
- Acceptance material explicitly archived: the v1.3.0/1.3.1/1.4/1.5/1.6 cloud checklists each got an
Archived / frozen (2026-09-24)header. Bodies are deliberately untouched — frozen is not the same as rewritten. - P-022 promoted out of PENDING into a living doc (
docs/architecture/doc-governance.md), registered as
DOC-1 / DOC-2. The token list deliberately stays inscripts/docs_refs_audit.pyas the single source. - P-024 — the "propose a new chat" rule gains forced trigger points instead of pure introspection; every
commit / PR and every CHANGELOG / PENDING write carries oneSession-check:line, zero counts included. - P-025 — R&D promotion becomes a gate (DOC-3: every PENDING entry carries one
> status:line, and a
landedentry older than 90 days warns) plus a checkpoint (onePromotion-check:line per PENDING / CHANGELOG
write). Deliberately not machine-checked, with the reason written down. - E2 — the unit suite can no longer shrink silently (
scripts/unit_suite_pin.py; first pin 7 files / 67 case
declarations / 0 skips), wired into the required audit check. - OCR quality-measurement harness promoted into a living doc (
docs/architecture/ocr-quality-harness.md); the
two transitional local-only drafts were deleted anddocs/R&D/README.mdwas corrected in the same pass. - CI core install line de-Lite'd and then dropped (it was installing nothing); stale CI workflow-comment figures
replaced by pointers at their pins.
Fixed
- P-021 —
POST /api/v1/ocrreturned polygons outside the uploaded pixel frame (fix landed 2026-09-24):
ocr_service._init_enginebuilt the engine withoutuse_doc_unwarping, so PaddleOCR's doc preprocessor ran
UVDoc unwarping (default on) and the returned polygons described a warped canvas rather than the input image
(measured as a non-rigid frame: scale 1.11–1.23 per probe, rotations flattened). One-line fix, net-zero on lines;
locked bybackend/tests/test_ocr_service_engine_params.py(stubspaddle, no GPU / Paddle) with a negative
control. Post-fix cloud readings: scale 0.9992–1.0001, residual 0.6–1.1 px, rotation amplitude preserved; text
usability 12 improved / 0 regressions / 3 unchanged. Accepted side effect:book.jpg(a genuinely curved spread)
loses 27% of its text. - Two
kind: fulltest files no longer leak theirpaddle/cv2stubs (P-023; found by the new check 5 on its
first real run) — the local suite had been red for that reason alone. - P-019 — module-map §6 A3 row single-sourced: the row's own copies of five §3 infra numbers are gone (one had
already drifted); §3 is now the single numeric source.
Verification
| Gate | Result |
|---|---|
| G4 (cloud) | judge 1-6/9 PASS; judge 7 (golden-diff whitelist) closed with the approved whitelist; judges 8/9 covered by G1 unit tests + golden pins |
| G5 (cloud) | INV-A1 / A2 / A3 zero violations; candidate-cell set identical before/after; red rate p12 58.2% → 0.8%, p29 97% → 25.4% |
| G6 (cloud) | WTW sentinel PASS — re-scoring the same cache is byte-identical and wtw_metrics.csv sha256 matches the P-027 baseline |
| Local | pytest 442 passed; audit / lint / docs_refs 0 error / 0 warning |
Full detail — including the honest boundaries and the execution-time rulings X1–X5 — is in the CHANGELOG
[1.10.0] section and docs/architecture/provenance-review.md §4/§5.
Upgrade / migration
- No schema, API or configuration migration.
- Contract additions are purely additive (new reason grid + counts +
reasonfields + a 6th review-table column),
so existing consumers keep working. Consumers that assert an exactreview_listshape or a fixed review-table
column count must add the new column. - Known discrepancy:
APP_VERSIONinbackend/app/core/config.pyis still1.9.0— this cut was docs-only and
did not bump it, so/healthreports1.9.0for thev1.10.0tag. Logged for a follow-up code change (a code
change would break the "code tree byte-identical" property of this tag, so it was deliberately not bundled here).