Skip to content

Release 0.3.0b3 - #6

Merged
ebt55 merged 34 commits into
mainfrom
claude/exactdoc-pdf-docx-tool-d4bf20
Oct 13, 2026
Merged

ebt55 merged 34 commits into
mainfrom
claude/exactdoc-pdf-docx-tool-d4bf20

Conversation

@ebt55

@ebt55 ebt55 commented Oct 13, 2026

Copy link
Copy Markdown
Owner

Release commit for 0.3.0b3, the first announced beta. Under amendment 7's stop rule, b3 is announced whatever its sealed exam shows, with the numbers printed as recorded.

Converter changes:

  • Stray shapes (WP68): they no longer grow into page-sized pictures. Changes cover the image budget, margin strips, box bars and photo shadows.
  • Layout readings (WP71):
    • memo margin labels and bullets;
    • blank résumé templates;
    • signature grids;
    • URLs broken at the line edge.

Sealed holdout-4 exam: 36 never-seen PDFs, 32 promised. Results: docs/evidence/holdout4-2026-10-13.txt.

Criterion Result
R1 Pass. 0 crashes; Word opened 36/36.
R2 Pass. LibreOffice 24/27 page-exact; Word 22/27.
R3 (v2) Fail. 2 short LaTeX papers came out unusable.

Release measurement: scorecard READY (beta-readiness-2026-10-13-b3.json). The strict gate passes in both lanes. Google Docs output is byte-identical to 0.3.0b1's.

Release files: README and CHANGELOG are refreshed to b3's evidence, and the version is 0.3.0b3.

After merge, v0.3.0b3 is tagged per docs/releasing.md.

🤖 Generated with Claude Code

ebt55 and others added 30 commits October 13, 2026 15:39
Synthetic pages, one per mechanism (a page's full-page background picture
under a drawn logo; a cover band's stripe; a full-height thumb tab under a
header banner; a photograph's drop shadow) and the look-alikes that must keep
their reading (a cover photograph with its headline under a small mark, a
tinted strip carrying text, a chart in a card, two photographs side by side,
a photograph without a shadow).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build_figure grew a picture over lines under a budget (max_area) and over
images with none: a drawn logo touching a full-page background grew to the
sheet and took every line on it (h3_15's At a Glance page); a thumb tab at
the paper's edge took each page of a report with its banner (h3_28, 50 pages
to 109); a cover band's stripe stood 372pt tall in the flow (h3_22's blank
first page). Four readings, standard profile only, a switch each in
infer.WP68_RULES:

- image_budget: an image grows a picture under the line budget, except cover
  art a small mark stands on with live text over it (_cover_art: y06's cover
  keeps its reading). A refused image takes the writer's full-page rule or
  _float_backgrounds, as an untouched image does.
- margin_strip: a text-free full-height fill, half or more in a side margin
  (_margin_strip; in_side_margin wanted it wholly outside), alone or a
  cluster, is margin furniture and dropped.
- box_bar: a tall narrow bar inside a built box whose picture would take no
  text is the box's decoration and dropped (never floated).
- image_shadow: a one-colour raster under a photograph it holds is the
  photograph's drop shadow, dropped (freed from those pictures, each stood in
  the flow as a grey box).

Nothing is floated by these rules. The gdocs profile is untouched
(tab_layouts=False).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rsion

24 public PDFs, 20 promised under promised_narrowed (15 short, 5 long),
selected mechanically by a sampling recipe written before any candidate
was seen (v1 SHA-256 recorded; the full recipe and the manifest are
published after the single run). The recipe's sources ran out before 16
of the 40 targeted places were filled; no source was added afterwards.
Nobody ran the converter on the set; the collector is independent of the
0.3.0b3 fixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The holdout-3 triage's mechanism B (a 1-3-line spill costing a whole page at
the source's hard page breaks) reaches none of its six target cases: a3
widow control moves no page, a1 seam join never joins under the loop on 202
documents and once open-loop (y09 raw, within2pt 0.7207 -> 0.6994, pages
unchanged), b the Word reserve fixes h3_32 in Word but fails the gate on
01_whitepaper_market (within2pt 0.8128 -> 0.749), a2 was not built and the
c3 Word fixture does not reproduce. Shelved; the code stays on branch wp69.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…romised)

A supplementary tranche of 12 short documents was added on the
coordinator's decision before anything was run, by a second recipe
(RECIPE-2) written before any of its candidates was seen; three Chrome web
prints were printed for the set from a page list fixed in that recipe.
One combined manifest, new SHA-256; both recipes' SHA-256s recorded; 27
short promised, 5 long promised. Nobody ran the converter on the set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ifest hash before any run

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The image budget freed every image over it. Where a freed image had nothing
to anchor it -- not the whole sheet, no text on it -- it stood in the flow at
its own height: a DHS OIG back cover's 497pt and 320pt photographs, part of
the picture before, cost h2_20 and h2_21 two pages each. `_image_leaves`
replaces `_cover_art`: refused only when the whole sheet (the writer's
full-page rule) or with text on it (`_float_backgrounds`), and not cover art
a small mark stands on (y06). Control fixture: back_cover.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sting

Gate strict on ff70576 (2174 OK, both lanes 16/16); criterion 8 against
b1's final sweep: 0 worse in either lane; gdocs byte-identical over 202
documents; 16 raw-profile movers with LibreOffice (product, raw) and Word
before/after. Three unpromised InDesign reports regress (h33, h34, h3_40).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decision (a), 2026-10-13: h34, h33, h3_40 and h3_41 are accepted as
unpromised movers -- InDesign designed reports outside the narrowed promise;
criterion 8 clean; the growth comes from text that was rasterised as a page
picture now being live, editable text. Follow-ups: (c) keep the full-sheet
raster when live text would overflow it; h3_15's in-flow 618pt cover picture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- _image_shadow: not the whole sheet, no line centre on it, at most
  SHADOW_MAX_GROWTH (2x) the photograph it holds. A one-colour card holding
  a photograph and white text is that text's background (_float_backgrounds)
  and stays; dropped, the text was white on white.
- _flat_raster: with an alpha channel, one colour AND translucent throughout
  (no pixel above SHADOW_MAX_ALPHA, half opaque): a shadow's soft mask, not
  an opaque alpha-shaped mask or overlay. h3_28's shadows are black with
  alpha at most 102.
- _margin_strip: the text test reads the page's rotated lines too, so a tab
  labelled up its edge is kept with its label.

Controls: dark_card, mask_overlay, thumb_tab(label=...); each fails at
ff70576.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f70576

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…budget, margin strips, box bars, photo shadows)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	CHANGELOG.md
A blank resume template sets the same placeholder field ("City, ST",
"Semester Year") flush right beside each entry; the fields cannot start
ragged, so _right_tab_fields refused them and the block-cluster reader set
the page as two columns. Also excluded from the right-hand lines: a banner
centred across the page's middle and the right item of a list set two-up;
and one long field beside the page's white is still a field. WP71_RULES,
standard profile only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A letter's signature pages set a signature picture over each signer's
name and title, two to a row: the two names of a row became one paragraph,
the pictures stacked between the rows in the flow, and the pages ran long.
Read before the float passes (_stash_picture_grid): two or more columns of
pictures of a size (within 25% of their median width), three or more rows,
each cell a picture with at most three caption lines overlapping it,
narrower than the column pitch, nothing else in the band but the rules the
pictures sit on. The pictures are anchored at their positions; each row is
a borderless layout row of caption cells, each caption kept line by line.
WP71_RULES["picture_grid"], standard profile (anchored) only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…right-aligned

A memo sets DATE, TO and SUBJECT in 6pt in the margin, each beside its
12pt line: the baselines differ by 2.2pt, outside every row test, so each
label became a paragraph of its own after its value (_margin_labels: within
0.45 of the smaller line's pitch, the label's box at least half inside the
line's, set smaller, a word or two, heading its line; read as a hanging
label by the list-marker machinery). And a list item's first line, cut by
the block builder from the rest of its item, was one full line flush with
the column's right edge and read as right-aligned, which kept it from
rejoining its item; wider than 0.8 of the column it is left-aligned unless
a paragraph beside it is flush right too (_settle_wide_right).
WP71_RULES, standard profile only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chrome breaks a long URL anywhere at the margin; the line join put a space
inside it (`8c cFofX`), which splits the token for the recall metrics and
hands the renderer two tokens to break. Joined with nothing when the broken
line reached its edge (the dehyphenation test's), the joined token is a URL
or path (a scheme or www., or a path separator in both halves) or the line
was one token from margin to edge, and the document's vocabulary attests
neither half as a word; the hyphen branch keeps precedence. URL_OVERFLOW
(None by default) offers the measured alternatives for the overlong token:
zero-width spaces after / ? & = inside it, or a line break where the source
broke it. WP71_RULES["url_join"], standard profile only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured on holdout-3 in the canonical container, product lane: the
Chrome-printed greensheet is 14 pages for 12 with the join alone, 13 with
zero-width spaces after / ? & = inside the joined token (word recall 0.53
-> 0.96) and 15 with the source's break kept as a line break, which also
put a blank resume template a page late. Never inside "//".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s of cells

Measured on holdout-3: a one-token line read as a token wider than the
measure joined the figures stacked in a financial statement's cells
(695,200 + 7,176,500) and a template's empty bullets; it now needs a line
that spans its measure, 20 characters or more, and a path separator. And a
resume's skills set three bullets to a row was read as a list item's first
line and merged with the row below; a line whose spans stand more than two
ems apart is a row of cells, not a full line (_row_of_cells).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A table of symbols (lshort's primes and quotes) set a glyph in a smaller
size beside its neighbour cell, and it was read as that cell's label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A reference ended '2023.' at the edge and its URL began the next line; the
joined token named a scheme, so the year and the URL ran together (y60).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ature grid

Approved by the coordinator: a letter's signatures run from a short scrawl to
a long one (71-162pt on the signature pages measured), and at 0.25 the grid
reading left a page of them out and regressed its own target. A brochure's
feature grid -- icons of varied size over one to three caption lines, the
captions of a row on one line -- is refused by two new cell tests: the
caption starts at the picture's left edge, and the picture is at least half
as wide as the caption (GRID_PIC_CAPTION_SHARE).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a grid before the column tests

(a) _merge_list_markers: a margin label whose nearest line is a marker glyph
of its own was put on that line, which is consumed into its item line, and
the label's text was lost. A marker line is never a label's host.
(b) _url_continues: where only separators made the join (no scheme, not a
one-token line), a half that is a figure (1/2) or a short formula (x=1), or
two halves whose every word the document uses (and/or + input/output), keep
their space; the vocabulary is letters only, so whole halves never matched.
(c) _assemble_chunks: the stashed picture grid is read before any column
test; a producer that draws each column's captions together had the
column readers set them as two columns under the anchored pictures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reading, acceptances

Gate wp71-g4 at 7926519 (2219 OK, FAILED_STEPS=0, 16/16 both lanes);
criterion 8 PASS in both lanes against 0.3.0b1's final sweep; gdocs
byte-identical on 202; holdout-3 development reading (not an exam): R2
LibreOffice 23/26, Word 21/26, R3 v1 pass, R3 v2 would fail on h3_13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e grids, URLs broken at the line edge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The holdout-4 dry run on a2a181b refused at step (a), before anything was
converted or recorded: holdout_dryset.py named its synthetic promise
promised_b_narrowed, and the holdout4 row reads promised_narrowed (from its
registration). The sealed exam never reads the synthetic set; only the dry
run was affected.

resolve now prints EXAM_PROMISE_FIELD (the exam's first promise field), and
holdout_exam.sh builds the dry-run set with it (holdout_dryset.py
--promise-field). Tooling only; the converter is untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ence

Release measurement, integration a2a181b, final_set.sh steps b,c,d,f on a
clean detached worktree (rc3) in the canonical image (bab1cfc0), overnight,
with no foreign container at any point:
- strict gate PASS (2,219 tests; both lanes 16/16); product and raw sweeps
  90/90 with no error rows; Word 90/90 on both flavours with no error, hang
  or repair prompt; every quiet serial timing within criterion 2 (worst:
  y06 product 156.2 s of 189).
- Docs lane reused, not re-flown: this head's gdocs DOCX parts are
  byte-identical to b1's uploads on all 90 convertible documents.
- beta-readiness-2026-10-13-b3.json: READY (10 pass, 0 fail, 3 reported),
  read for 0.3.0b3 by passing --release 0.3.0b3 (the RELEASE constants
  still say 0.3.0b2; nothing changed tonight), accepted sweep b1's final
  product sweep, waiver file empty, --allow-mixed-commits/--allow-stale for
  the reused Docs rows. Criterion 12 passed (no stale README evidence).
- release-measurement-2026-10-13-b3.json: inputs by SHA-256, timings, the
  Docs identity, the release-string note, the exam's commit.

Holdout-4, run once on a2a181b (the same commit), R3 under amendment 7
(v2): holdout4-2026-10-13.json/.txt, announce: no. R1 PASS (0 crashes,
0 refusals, Word 36/36 clean); R2 PASS (short promised page-exact 24/27
LibreOffice, 22/27 Word; word recall >= 0.9 25/27 and 24/27); R3 FAIL
(2 short catastrophic: h4_34, 38/19 pages; h4_35, doc_recall 0.85;
0 long). The sealed manifest and the two sampling recipes are published
byte-identical to their registered SHA-256s, marked -text; they name local
scratch paths (C:/lotmp/rv_hold*) and, in RECIPE-2, the headless Chrome
command used to print three documents for the set; no personal data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ebt55 and others added 4 commits October 13, 2026 23:47
…omise field

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed holdout-4 exam (R1 pass, R2 pass, R3 fail)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The release commit for the first announced beta. Version 0.3.0b3 in
pyproject.toml and uv.lock; beta_readiness.py's RELEASE and final_set.sh's
default read 0.3.0b3, so the tools agree with the recorded scorecard
(docs/evidence/beta-readiness-2026-10-13-b3.json, READY).

CHANGELOG: `## 0.3.0b3 -- 2026-10-14`, with holdout-4's known issues (the two
arXiv LaTeX papers R3 counts unusable, and the R2 misses), WP68's four
InDesign reports (not three), WP71's accepted costs, and a note that a URL
copied from the DOCX may carry zero-width spaces (also in
docs/deep-dive/limitations.md).

README: the status callout, the "What works" evidence links and never-seen
rows (holdout-4: letters and memos, resumes, short LaTeX papers, reports over
20 pages, long LaTeX, web pages), the release-measurement links, and the
never-seen section rewritten for holdout-4 (R1-R5 as recorded; verdict: met
the page and word bar on short documents in both lanes, two LaTeX papers
unusable; the end of the fixed-exam loop; b2 -> b3 on never-seen short
documents; the re-scored R3 as history).

Stale docs: releasing.md (b2 and b3 published / announced; command examples
use 0.3.0b3); scripts/dev/README.md documents that the exam default stays
holdout3 and that every exam is spent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… holdout-4's numbers)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 13, 2026 18:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ebt55
ebt55 merged commit 5e680d6 into main Oct 13, 2026
17 checks passed
@ebt55
ebt55 deleted the claude/exactdoc-pdf-docx-tool-d4bf20 branch October 13, 2026 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants