Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
2642 commits
Select commit Hold shift + click to select a range
ec1a5a4
merge(charts): a BIFF chart's plot area is stated, not computed, and …
claude Sep 11, 2026
b2c2b07
sheets(rows): a trailing empty paragraph is a line, and the wrap was …
claude Sep 11, 2026
ea7b3a3
merge(sheets): a trailing empty paragraph is a line, and the 534 miss…
claude Sep 11, 2026
18f9da9
probes: the TK-Syllabus line-count gap is withdrawn, it was a get_tex…
claude Sep 11, 2026
9e9815d
slides(bullet, break): a hard line break does not size its line, and …
claude Sep 11, 2026
c1981c2
merge(slides): the overflow was never the defect, and a hard break si…
claude Sep 11, 2026
83d75ef
skills(corpus-batches): contention also fabricates failures, not just…
claude Sep 11, 2026
328e793
probes(charts): a chart-type audit of all four streams, and the censu…
claude Sep 11, 2026
50adaf6
merge(probes): a chart-type coverage audit across the three streams
claude Sep 11, 2026
99bfbc7
sheets(merge,shape): a merged fill stops one column past the block, a…
claude Sep 11, 2026
e58567a
merge(sheets): a merged fill stops one column past the block, and the…
claude Sep 11, 2026
868f430
charts(smooth): flatten a smoothed series as 26.2.4.2 does, and settl…
claude Sep 11, 2026
7d5b130
merge(charts): the reference's spline is a 20-per-interval flattening…
claude Sep 11, 2026
c8db26f
sheets(iconSet): the corpus reaches seven glyphs, not twenty-two icon…
claude Sep 11, 2026
a88fcb3
merge(sheets): iconSet, and a census that turned the artwork question…
claude Sep 11, 2026
d5d77a4
sheets(biff): a grouped shape has no client anchor, a TXO eats the dr…
claude Sep 11, 2026
3c25da5
merge(sheets): a grouped BIFF shape has never been drawn, and a TXO w…
claude Sep 11, 2026
c4e56c7
slides(ppt,autofit): a .ppt hyperlink is a field only while the trunc…
claude Sep 11, 2026
dfe6b2d
merge(slides): a truncated OLE property buffer drops hyperlinks, and …
claude Sep 11, 2026
c68c984
skills(corpus-batches): a killed test run reports neither a pass nor …
claude Sep 11, 2026
f81b104
charts(rest): a chartex chart is two polylines, and the block clip is…
claude Sep 11, 2026
872a8d1
charts(rest): reconcile the EMF share against its own table
claude Sep 11, 2026
7b79a5d
merge(charts): a chartex chart is two polylines, and the escaping uni…
claude Sep 11, 2026
b843c9b
probe(chart): the axis hyphenator, confirmed by switching the diction…
claude Sep 11, 2026
d07a9ce
probe(charts): the hyphenation seat sized, and the licence establishe…
claude Sep 11, 2026
3e769da
fix(charts): the category-axis hyphenator, shipped with one dictionar…
claude Sep 12, 2026
fbdb0bc
merge(charts): a hyphenator, with en_US vendored and other dictionari…
claude Sep 12, 2026
0054705
wip(pivotgen): salvaged from a container restart, unvalidated
claude Sep 12, 2026
2277709
wip(sheetdraw): salvaged from a container restart, unvalidated
claude Sep 12, 2026
95629cb
wip(slidefw2): salvaged from a container restart, unvalidated
claude Sep 12, 2026
10d739e
pivotgen: the generated grid checked both ways, and three rules the o…
claude Sep 12, 2026
ef67126
sheets(r107): the pattern fill and the hidden value validated, and O4…
claude Sep 12, 2026
39edc2d
merge(sheets): an Escher pattern fill is an 8x8 tile, and the row-gri…
claude Sep 12, 2026
6b6325b
pivotgen: the pivot grid measured — alle einzeln 225.44 -> 0.07, 36 M…
claude Sep 12, 2026
e2f366a
merge(sheets): the pivot's generated grid, and 225.44 of ink becomes …
claude Sep 12, 2026
493a666
skills(corpus-batches): a killed round leaves a cli-base that may con…
claude Sep 12, 2026
7e4c77e
slides(fontwork): an Escher WordArt drawn as Fontwork, and a subscrip…
claude Sep 12, 2026
3a926f6
merge(slides): Escher WordArt reaches Fontwork, and an escaped portio…
claude Sep 12, 2026
a408e4b
slides(ppt): a percentage paragraph space is measured against the par…
claude Sep 12, 2026
e1907b4
slides(r108): correct the leg-split counts in the write-up
claude Sep 12, 2026
ccca101
merge(slides): a percentage paragraph spacing resolves against the la…
claude Sep 12, 2026
187f782
sheets(pivot): the hidden header and the packed row column, and the o…
claude Sep 12, 2026
05bd3ef
merge(sheets): the hidden pivot header, and a bug in the oracle that …
claude Sep 12, 2026
47f7b07
charts(r108): a BIFF axis' tick record and line colours, and the of-p…
claude Sep 12, 2026
a311b00
merge(charts): BIFF axis ticks and line colour, and the plot rectangl…
claude Sep 12, 2026
d6dd940
probe(charts): close O31 — no live 3-D chart scene is ever drawn as v…
claude Sep 12, 2026
f8812f1
skill(render-comparison): an OLE preview is not the renderer's drawing
claude Sep 12, 2026
857f8cb
sheets(r110): the pivot's dxf records are not nil, and only the colou…
claude Sep 12, 2026
2cb731a
charts(r110): two labels collide when they reach the wrap's own 95%, …
claude Sep 12, 2026
b55ff75
merge(charts): two adjacent labels keep the wrap's own five per cent …
claude Sep 12, 2026
3309599
charts(r110): a sheet chart is laid out on its own page, and the pie'…
claude Sep 12, 2026
d957808
merge(charts): a sheet chart is laid out on its own page, and the pie…
claude Sep 12, 2026
2741149
slides(r110): an empty paragraph's line is floored at its bullet's box
claude Sep 12, 2026
01a27d3
merge(slides): an empty paragraph's line is floored at its bullet's box
claude Sep 12, 2026
74f5b5f
probe(slides): seat the .ppt picture bullet as O46
claude Sep 12, 2026
a4ec380
sheets(r110): the pivot's dxf records are read, and 033's black band …
claude Sep 12, 2026
84aeb34
merge(sheets): the pivot's dxf records, and the clearing measured by …
claude Sep 12, 2026
dce2b3c
sheets: the dxf solid paints the bgColor, not the pattern colour
claude Sep 12, 2026
3923c95
probe(gate): full corpus at the merged head, and the reference's own …
claude Sep 12, 2026
a362d41
probe(gate): bank r109's rows beside r111's so the diff is reproducible
claude Sep 12, 2026
80fc17a
probe: seat the reference's own reproducibility as C11
claude Sep 12, 2026
3ea5cde
sheets: the sheet default is the Normal cellStyleXf, not cellXfs[0]
claude Sep 12, 2026
c1f0dc9
merge(sheets): the sheet default is the Normal cellStyleXf, not cellX…
claude Sep 12, 2026
c8c66d4
charts: the wrap room is 0.95, and a value axis keeps chart2's defaults
claude Sep 12, 2026
c6fda68
merge(charts): the wrap room is 0.95, and a value axis keeps chart2's…
claude Sep 12, 2026
589707c
slides: a .ppt states its picture bullet on the master, not on the pa…
claude Sep 12, 2026
a7f3138
docs: a reach figure equal to the whole set is a missing pin
claude Sep 12, 2026
4f4d0dd
merge(slides): a .ppt states its picture bullet on the master, not on…
claude Sep 12, 2026
1496f03
probe(gate): r112 is clean, and the reference's instability is worse …
claude Sep 12, 2026
53d4f47
charts: a value axis is capped on its first three labels, and turns t…
claude Sep 12, 2026
32c0a44
merge(charts): a value axis is capped on its first three labels, and …
claude Sep 12, 2026
5e8f110
slides: a .ppt table's cells never autofit, and a shape keeps its ruler
claude Sep 12, 2026
ee5dbde
merge(slides): a .ppt table's cells never autofit, and a shape keeps …
claude Sep 12, 2026
f160c8a
probe(vision): the blind reading found a defect three rounds had missed
claude Sep 12, 2026
c7d39b8
probe(strokes): the heavy rule is a spreadsheet class, and the first …
claude Sep 13, 2026
dc17fef
slides: a .ppt table's rows are laid out twice, and its rules are cel…
claude Sep 13, 2026
ee1be8c
merge(slides): a .ppt table's rows are laid out twice, and its rules …
claude Sep 13, 2026
deff88e
probe(vision): O57 is an advance width, not a wrap rule
claude Sep 13, 2026
36546b7
charts: the interval cap is taken against the maximum-label rectangle…
claude Sep 13, 2026
c6ed238
merge(charts): the interval cap is taken against the maximum-label re…
claude Sep 13, 2026
6ea6d80
probe(gate): 915 match, and the verdict that moved is the volatile-da…
claude Sep 13, 2026
b297819
probe: seat the date-boundary verdict flip as C13
claude Sep 13, 2026
f9fe56d
probe: order the confound table numerically
claude Sep 13, 2026
e4fe231
probe(slides): O57's extra width is invented — the .ppt confound is L…
claude Sep 13, 2026
d1358bd
sheets: a cell border takes the sheet's print scale
claude Sep 13, 2026
a26b1fb
probe(slides): escape the O57 row's pipes so the register renders
claude Sep 13, 2026
3dff52d
merge(sheets): a cell border takes the sheet's print scale
claude Sep 13, 2026
5897dbb
merge(slides): O57 is invented width, and it is the seventh confound …
claude Sep 13, 2026
88209aa
tools: provenance-index.py must not destroy the index it maintains
claude Sep 13, 2026
9e9dc43
probe(gate): 120 renderings changed and no gate row did
claude Sep 13, 2026
0ad9ea1
chart(slides): O43 has no witness, O58 is half a turned label's height
claude Sep 13, 2026
6227381
merge(charts): the turned-label reserve is h.sin/2, O43 has no witnes…
claude Sep 13, 2026
c00998d
fix(sheets,slides,words): a border's dashes are absolute, and a chart…
claude Sep 13, 2026
97c73b1
merge(sheets/charts): the theme matrix never reached two chart reader…
claude Sep 13, 2026
79ee2f7
probe(vision): O62 stands, and a thin rule cannot be read from a full…
claude Sep 13, 2026
755c295
fix(sheets): a hyperlink's underline comes out of the same call as it…
claude Sep 14, 2026
c966892
merge(sheets): a Calc hyperlink's underline and colour are one path, …
claude Sep 14, 2026
5c85934
probe: order the confound table after C15 and C16
claude Sep 14, 2026
90b5b22
skill(render-comparison): the flat-ODF leg can lose what the PDF draws
claude Sep 14, 2026
50d0d89
probe: gate r119 moves no comparable column, and every mover is a C13…
claude Sep 14, 2026
c98ddaa
probe: bank the round-80 ODF gate's rows, which were only ever on disk
claude Sep 14, 2026
9901174
docs(probes): close O1, O2, O4 and O5, the four seats with no registe…
claude Sep 14, 2026
b88969d
merge(o2audit): the four seats with no register row, and O2's real re…
claude Sep 14, 2026
fccb041
probe: the NAS deck does hold three tables, and O67 survives on a wid…
claude Sep 14, 2026
2e8bb3f
fix(text): a rule's thickness is a whole device pixel rounded to a wh…
claude Sep 14, 2026
ba8346a
fix(sheets): a hyperlink cell keeps a HARD colour, and which are hard…
claude Sep 14, 2026
400aaba
probe(quantise-r120): the write-up, the sweep and the register's two …
claude Sep 14, 2026
0fa883d
merge(quantise): the rule thickness is a whole reference-device pixel…
claude Sep 14, 2026
d98c8be
probe: gate r122, and C11's instability is wider than a character cou…
claude Sep 14, 2026
fef09a1
A double underline is two thinner lines, and none of the three rules …
claude Sep 14, 2026
935ad19
And the bold underline, the corpus reach, and O70
claude Sep 14, 2026
d86ed0f
merge(dblunder): the double underline, the rule offsets, and a bold r…
claude Sep 14, 2026
3208d58
probe(ink-hunt-r124): the passing set's head hides two underlines, an…
claude Sep 14, 2026
e484d5d
merge(inkhunt): five seats out of the passing set, found by blind rea…
claude Sep 14, 2026
bdfa0c9
probe: gate r125 -- 368 renderings moved their rules and no gate colu…
claude Sep 14, 2026
c82a3b0
fix(pptgeom): the trapezoid is the only mirrored Escher preset, and t…
claude Sep 14, 2026
2447b7a
probe(pptgeom-r127): the trapezoids' own fFlipV flags, and what each …
claude Sep 14, 2026
d3e7b60
probe(pptgeom-r127): note that the fidelity project's two .ppt fixtur…
claude Sep 14, 2026
b4ca0c6
probe(pptgeom-r127): the fidelity run -- 552 discovered, 542 passed, …
claude Sep 14, 2026
6114a4c
merge(pptgeom): the trapezoid is the only mirrored preset, and a blan…
claude Sep 14, 2026
d68add3
fix(words): clip a picture to its own preset geometry, and refute two…
claude Sep 14, 2026
f6d192d
words(r126): a decoration crosses a tab, and a TOC entry loses its st…
claude Sep 14, 2026
1376daf
merge(wordsgroup): the 8.85x was the instrument, and the real defect …
claude Sep 14, 2026
fe97cc0
merge(wordsdec): a tab carries its decoration at full width, and the …
claude Sep 14, 2026
e1b05c8
probe: round 128's test total was a truncated run, corrected in place
claude Sep 14, 2026
e284358
skill: the box a tool reports, and what a ten-reader run taught
claude Sep 14, 2026
ec0a11e
probe: gate r129, and alle einzeln is not a two-state oscillator
claude Sep 14, 2026
fb9bf3b
probe: a refuted seat was still sitting in "Open - seated", stating i…
claude Sep 14, 2026
5569fad
words(r131): a shared cell edge is one border, and the FAA orientatio…
claude Sep 14, 2026
01f30fb
merge(wordstable): a shared cell edge is one border, and O78's 1.5 pt…
claude Sep 14, 2026
0ca1c65
probe: how this file goes wrong at a merge, and the audit that would …
claude Sep 14, 2026
23c241f
fix(sheets): a scaled page quantises its rule before the transform, n…
claude Sep 14, 2026
e74e3ca
merge(rulescale): the zoom belongs inside the llround, and there is n…
claude Sep 14, 2026
d468507
words(r130): a .doc contents list keeps a style the reference refuses…
claude Sep 14, 2026
cce4b5f
probe(r130): the converted .odt and .rtf columns were swept too, and …
claude Sep 14, 2026
a185ec7
merge(ww8toc): the suppression is one sti, and the walk was dropping …
claude Sep 14, 2026
9a90bd6
probe: gate r133 reads 916, and the extra match is not ours
claude Sep 15, 2026
f6b6116
probe(r136): a third of the corpus has never been looked at, and rank…
claude Sep 15, 2026
71241fc
merge(r136): coverage census and six seats from non-ink ranking
claude Sep 15, 2026
1575671
words(r135): a .doc toggle is relative to one style, and an attribute…
claude Sep 15, 2026
d29cd41
merge(r135): WW8 toggle sprm base and the index-field CHPX boundary
claude Sep 15, 2026
8fb3b1a
probe: the frozen footer page number is a dropped field, and it takes…
claude Sep 15, 2026
bf3b7dc
merge(r137): the DOCX import drops a page field in a grouped text box…
claude Sep 15, 2026
5b4ada1
env: the reference binary does not survive a container rebuild, and i…
claude Sep 16, 2026
61ad51c
sheets(r138): a shape's own picture fill is the shape's interior, and…
claude Sep 17, 2026
dd9c2ba
sheets(r139): a number format's colour belongs to the subformat the v…
claude Sep 17, 2026
ad12def
words(r140): a w:object's replacement picture was drawn twice, by a f…
claude Sep 17, 2026
96dbdbb
sheets(r141): an ODF number style's subformats are several elements, …
claude Sep 17, 2026
d8f49e7
sheets(r141): O98 is refuted the day it was seated, and it named a pr…
claude Sep 17, 2026
41ee517
sheets(r142): an ODF number format spells `_x` nowhere, and `*x` as a…
claude Sep 17, 2026
72db85d
words(r143): a character width stated by a style reaches the layout a…
claude Sep 17, 2026
86dbae9
sheets(r144): a Gantt drawn out of conditional formats, and the hatch…
claude Sep 17, 2026
f24ecc3
sheets(r145): the BIFF half of the hatch mix, and two seats re-censused
claude Sep 17, 2026
f6c19c8
words(r146): a v:line states its extent in from/to, and the table-row…
claude Sep 17, 2026
3a2ec41
words(r147): a horizontal table border hangs below the boundary, not …
claude Sep 17, 2026
cc5cc02
Read style:text-scale in the ODT reader (O101, ODF third)
claude Sep 17, 2026
f2207fd
The row below a table boundary pays the whole band (O84)
claude Sep 17, 2026
c11a4b4
Read style:table-centering, not style:table-centring (O100)
claude Sep 18, 2026
820d61f
Read charscalex and sprmCCharScale (O101, WW8 and RTF thirds; seat cl…
claude Sep 18, 2026
b5d4634
A break-only line takes the break run's face, not the neighbour's (O91)
claude Sep 18, 2026
a3159ce
A split table row is ruled once at the cut, by its bottom rule (O83)
claude Sep 18, 2026
1ea79b8
An escaped size is truncated to a twip, not rounded (O78 seat A)
claude Sep 18, 2026
170d609
Bank round 153's base-leg fixture scores
claude Sep 18, 2026
a42f819
Bank round 153's confinement sweep, its scoring and O78 seat A's close
claude Sep 18, 2026
4396f28
Compare a font size at the resolution LibreOffice's PDF writer prints…
claude Sep 18, 2026
791c5d8
Record round 153's suite totals
claude Sep 18, 2026
ffbdb45
A cell a vertical merge covers is charged to the row's height (O78 se…
claude Sep 18, 2026
d56538f
Bank round 154's four fixtures, their measurements and the write-up
claude Sep 18, 2026
6135306
Finish a sweep leg a container restart killed, and validate what it left
claude Sep 18, 2026
1787626
Ignore round 154's base-leg renderings
claude Sep 18, 2026
d74dd3a
Bank round 154's sweep and close O78; seat O103, O104 and O105
claude Sep 19, 2026
77304c2
Record round 154's suite totals
claude Sep 19, 2026
35b6adb
An .odt's tables read their row-height setting, covered cells and pag…
claude Sep 19, 2026
6f3b50d
Bank round 155's measurements and write-up
claude Sep 19, 2026
ef40133
Ignore round 155's base-leg rendering
claude Sep 19, 2026
96e2626
Bank round 155's sweep: the ODF column gains four gate verdicts and l…
claude Sep 19, 2026
b322e47
Record round 155's suite totals
claude Sep 19, 2026
41f5394
A .doc's covered cell carries the merge master's borders, not its own…
claude Sep 19, 2026
b1e3c4f
Bank round 156's measurements and write-up
claude Sep 19, 2026
e064e29
Ignore round 156's converted flat-ODF view
claude Sep 19, 2026
e08469d
Ignore round 156's base-leg rendering
claude Sep 19, 2026
919bf46
Bank round 156's sweep, and seat the deep-merge residual it uncovered…
claude Sep 19, 2026
36cfe08
Record round 156's suite totals
claude Sep 19, 2026
ee78558
Narrow O107: the heights are right when computed and wrong when placed
claude Sep 19, 2026
b98b02b
Withdraw O107's synthetic witness: the deep fixtures agree after all
claude Sep 19, 2026
c7e8ff9
Refute O107's second candidate: a merge across a page boundary is exact
claude Sep 19, 2026
ae76ff4
Merge pull request #15 from theolivenbaum/claude/renderer-comparison-…
theolivenbaum Sep 19, 2026
d636a10
Expand a DOCX REF field from its bookmark, as the reference does
claude Sep 19, 2026
8af1cbb
Count a list by its abstract definition, not by its w:numId
claude Sep 19, 2026
acfa0e9
Void the direct formatting of a heading a TOC template switch names
claude Sep 20, 2026
e35a69b
Follow Word: ship the TOC template-style rule switched off
claude Sep 20, 2026
bccfeb6
Follow Word on REF fields too, behind one Word-parity switch
claude Sep 20, 2026
70af0b4
Merge pull request #16 from theolivenbaum/claude/renderer-comparison-…
theolivenbaum Sep 20, 2026
c9afbd9
Bank r163 evidence: OMML is unimplemented, and it costs pages
claude Sep 24, 2026
81d1eee
Bank the split-row finding, and audit every measurement for build sta…
claude Sep 24, 2026
1117ccf
A split row's first part drops its trailing spacing rather than move …
claude Sep 24, 2026
674bb64
Split a table row a vertical merge reaches into, and clamp the coveri…
claude Sep 25, 2026
70f4c4e
Do not bank the OM-template probe's whole-document text dumps
claude Sep 25, 2026
ac7050f
Draw the marks a formula generates, not only the text it states
claude Sep 25, 2026
a41f5d7
Ignore the render output of the two live r164 probe directories
claude Sep 25, 2026
3749675
Clip a fixed-height shape's text to its text area, as the reference does
claude Sep 25, 2026
54a4919
Bank the diagram-r164 probe: the eight "draws more text" templates
claude Sep 25, 2026
bb0d711
Reserve a formula's own height on the line it sits on
claude Sep 25, 2026
29a8125
Bank the pages-r164 probe: four page-count residuals, four mechanisms
claude Sep 25, 2026
acdd517
Bank tabright-r166: the right-tab fit rule, and why its candidate fix…
claude Sep 25, 2026
56cd4c9
Bank emptysect-r167: the empty-section page, refuted at its proposed …
claude Sep 26, 2026
c05023e
Draw a recomputed field's value in the field's formatting, not its ca…
claude Sep 26, 2026
96d61a7
Draw a page field that states no separator at all
claude Sep 26, 2026
ef3595d
Bank indexwrap-r169: a positioned table is never an obstacle here
claude Sep 26, 2026
fb1dd5a
indexwrap-r169: a table of contents IS wrapped beside a fly
claude Sep 26, 2026
acd80be
indexwrap-r169: two more arms, and the heading's x measured rather th…
claude Sep 27, 2026
9e8d97e
tabright-r166: measure the right-tab boundary at a point, not at sixteen
claude Sep 27, 2026
730ba3c
floattable-r170: a positioned table's wrap is worth one document, so …
claude Sep 27, 2026
53817d1
A VML text box insets its text, and keeps the height it declares
claude Sep 27, 2026
9389678
A VML shape inside a v:group loses its paragraph formatting, and that…
claude Sep 27, 2026
717aefb
Read a VML outline's arrowheads
claude Sep 27, 2026
5f50e3d
wordsink-r174: the words track ranked by ink at HEAD
claude Sep 27, 2026
67baf08
A right stop past the line's end gives the paragraph's end indent back
claude Sep 27, 2026
608e635
A `w:u` stating no `w:val` is not an underline
claude Sep 27, 2026
d437423
vmlpreset-r174: which VML shapes get any ink at all
claude Sep 27, 2026
3b671fa
holdover-r177: both FAA Holdover Tables are the word-parity page and …
claude Sep 27, 2026
c4fb775
inkmetric-r178: the ink ranking was measuring colour quantisation, an…
claude Sep 27, 2026
9086c1e
The right-tab give-back is the trailing stretch's alone
claude Sep 27, 2026
22cca57
tooling-r180: fine-tune the comparison tools
claude Sep 27, 2026
be050e5
Re-run the track-ink ranking under fixed tools; record which tool ans…
claude Sep 27, 2026
661fba6
An inline picture is ink a floating table has to move out of the way of
claude Sep 27, 2026
bb69832
An autofitting shape takes its height from its text, not from the a:e…
claude Sep 27, 2026
574605f
Rank the ink sweep on the worst page, and refute the document the sum…
claude Sep 27, 2026
5729298
A continuous DOC section that hangs its descriptor on a hard break ke…
claude Sep 27, 2026
4eed3a8
A VML shape names its geometry, so draw that geometry and paint it
claude Sep 27, 2026
c11e6a4
Read the two chart types that are a field rather than a record
claude Sep 28, 2026
1f1fb17
Rank a chart on diff%, not on |ink|% -- the first sweep's conclusion …
claude Sep 28, 2026
d86f41e
Draw a 3-D pie as an extruded solid, and stop squaring its diagram
claude Sep 28, 2026
387fc98
Shape a chart's bold text in the bold face on the words track
claude Sep 28, 2026
bf7dddf
Place bars on a date axis by their date
claude Sep 28, 2026
6e3b04b
Give an of-pie its composite wedge, its bar order and its opening angle
claude Sep 28, 2026
55c3f04
Put an inEnd pie label at the rim instead of at half the radius
claude Sep 28, 2026
c1207a8
Record that a slide line break charges its trailing blank
claude Sep 28, 2026
91bcda2
Refute "a slide line break charges its trailing blank"
claude Sep 28, 2026
850adad
Give a chart label's width its trailing blank
claude Sep 28, 2026
9e45e49
Bank a chart's pattern-fill backdrop, withdrawn on its hatch phase
claude Sep 28, 2026
f68bf80
Pin where an autofitted slide bullet's first line starts
claude Sep 28, 2026
7c18b7e
Clear a character bullet's unscaled width on an autofitted first line
claude Sep 28, 2026
743acb3
Count a page-relative anchor from the body for an embedded object
claude Sep 28, 2026
41bbd74
Keep the bottom correction for a following object, and measure the reach
claude Sep 28, 2026
c212741
Merge pull request #17 from theolivenbaum/claude/renderer-comparison-…
theolivenbaum Sep 28, 2026
1c55ab7
Rename the Paperless port to XRay.Office
claude Oct 16, 2026
d634cd5
Call the product X-Ray.Office in prose
claude Oct 16, 2026
6fc0dd8
Package X-Ray.Office for NuGet and add its publishing pipeline
claude Oct 16, 2026
984214d
Cancel, time-limit and size-limit every long operation; write richer …
claude Oct 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
68 changes: 68 additions & 0 deletions .claude/skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Skills for developing X-Ray.Office

Six skills covering development of the [X-Ray.Office](../../dotnet/) C# libraries against
headless LibreOffice as the reference implementation.

| Skill | Use it when |
|---|---|
| [`libreoffice-reference`](libreoffice-reference/) | You need ground truth: reference PDFs, per-page PNGs, or reference text from a document. Also when `soffice --convert-to` misbehaves. |
| [`render-comparison`](render-comparison/) | Comparing an X-Ray.Office rendering against the reference, and working out *why* it differs. |
| [`page-vision`](page-vision/) | Actually *looking* at a page: getting it in front of a reader at a resolution where the defect survives, delegating the reading to an uncontaminated reviewer, and knowing what a visual reading can and cannot establish. |
| [`extraction-comparison`](extraction-comparison/) | Comparing extracted text. Also the right first step for a visual bug — parsing bugs are far cheaper to find in text than in pixels. |
| [`office-corpus`](office-corpus/) | Building or curating test documents. |
| [`corpus-batches`](corpus-batches/) | Driving the 541-document sample corpus to parity, batch by batch — the ordering, the regression rule, and how to dispatch parallel agents across the three tracks. |

## Start here

```bash
.claude/skills/libreoffice-reference/scripts/check-env.sh
```

Nothing else is trustworthy until this passes. It catches the two failures that waste the
most time:

- **Application modules missing.** `libreoffice-core` alone installs a `soffice` that runs
but cannot load *any* document, failing with a maximally unhelpful
`Error: source file could not be loaded`.
- **Wrong font substitution.** If Calibri resolves to DejaVu Sans rather than Carlito,
advance widths change, so line breaks change, so pagination changes — and every page after
the first differs for a reason that has nothing to do with X-Ray.Office.

## Scripts

All are dependency-free (bash, or Python using only the standard library) and all were
verified against LibreOffice 24.2.7.2 on real files.

| Script | Does |
|---|---|
| `libreoffice-reference/scripts/check-env.sh` | Verifies soffice, modules, fonts, rasteriser |
| `libreoffice-reference/scripts/lo-convert.sh` | Documents → reference PDFs and page PNGs |
| `libreoffice-reference/scripts/lo-extract.sh` | Documents → reference text (right filter per family) |
| `render-comparison/scripts/compare-images.py` | Page images → metrics, diagnosis, diff images |
| `render-comparison/scripts/pdf-image-diff.py` | Two PDFs → page PNGs, diff PNGs, and where each page differs |
| `extraction-comparison/scripts/compare-text.py` | Text → similarity, first divergence, codepoint diagnostics |
| `office-corpus/scripts/make-corpus.sh` | Generates a test corpus across all 17 formats |
| `corpus-batches/scripts/render-corpus.sh` | Renders a whole corpus with LibreOffice — parallel, resumable |
| `corpus-batches/scripts/pdf-complexity.py` | Scores what each rendered PDF demands of a renderer |
| `corpus-batches/scripts/make-batches.py` | Orders a corpus by that score and cuts it into per-family batches |
| `corpus-batches/scripts/batch-check.sh` | Renders a batch range both ways and gates on whether they agree |

## Two facts worth knowing before you start

**`soffice` exits 0 even when it converts nothing.** Never trust its exit code — always check
that the output file exists. The scripts here all do.

**Rasterised LibreOffice output is byte-deterministic — on the documents this was verified on,
and not universally.** The original check stands: the same input converted twice and rasterised
gave identical PNGs. But `fse_identification_form.xlsx` converted five times by one `soffice`
26.2.4.2 gives 430, 430, 430, 430 and **443** words, the difference being one cell's sentence
that LibreOffice draws in about one run in five. See the last section of
`dotnet/TODO.raster-ceiling.md`. **Render a reference more than once before trusting a
single-document figure**, and treat a golden image's checksum as a claim about that document
rather than about the renderer.

Within that limit the practice still holds: golden reference images can be committed and
checksummed, and a changed checksum is a real signal — but it is now a signal to re-render and
check whether the document is one of the unstable ones, not automatically evidence that
something in the tree changed. The PDFs themselves are *not* byte-identical either way, since
they embed a timestamp, so checksum the PNGs and never the PDFs.
Loading
Loading