v0.3.0
Native charts across all three formats, a deterministic-cover subtitle fill, a
single source of truth for component-survival, and a round of correctness +
quality fixes from a multi-agent code review. Brand Profiles from 0.1.x/0.2.0 keep
working unchanged.
Added
- A
chartblock is now authored as a native chart on both Word and PowerPoint
(a real DrawingMLc:chart: an inlinew:drawingon docx, agraphicFrameon
pptx), no longer flattened to body text.bar/column/barh/line/area/pie/
doughnutmap to the matching chart type (unknown -> clustered column, surfaced as
INFO); series/categories/title come from the block, and the chart inherits the
document/deck theme's accent colors so it is on-brand by construction. A
multi-series pie/doughnut surfaces a truncation WARNING; an empty/all-non-numeric
chart degrades loudly. A sharedooxml.chartbuilds the docx chart with INLINE
cached data (no embedded workbook) and is the single data gate both formats use;
the pptx data workbook's wall-clock timestamps are normalized by
repack_fixed_timestamps(now recursive over nested OOXML packages), so generation
stays byte-idempotent on both. - Excel charts complete the set: a
GridDocument.chartsentry ({sheet?, type, title?, anchor, data, categories?, data_titles?}) is authored as a NATIVE
openpyxl chart that REFERENCES the workbook's own cell ranges (the grid model is
range-based, so the data lives in the sheet). Same type map / unknown-type INFO
fallback / loud degrade contract; the chart inherits the workbook theme, and
generation stays byte-idempotent. All three formats now author native charts. - Word: the deterministic cover fill (comprehension absent) now also places
the authored subtitle into the cover slot identified by its resolved
cover.subtitlestyle - correct-by-style, never guessed from the template's
placeholder text - so the output no longer shows the template's stale demo
subtitle. Role inference resolvescover.subtitlefrom a custom
subtitle-named style (preferred) or the builtinSubtitle; a multilingual
subtitlename-token family backs it. Templates whose subtitle is a databound
SDT keep working via core-property sync; extra cover fields (date/id/author)
remain the comprehension path's job and are still surfaced as unplaced.
Fixed
- General correctness + quality review (multi-agent, adversarially verified):
- Word/PPTX tables no longer drop multi-run column headers. A header cell
authored with rich runs (e.g. plain text + a bold unit) kept only its first
run throughTable.from_dict; every run is now preserved (and the loose
{"runs": [...]}/{"text": "..."}/ run-list / string shapes a body cell
accepts are accepted for columns too). - PowerPoint body text on a placeholderless layout degrades loudly instead
of vanishing silently (ablock_degradedWARNING is now recorded). - Word hyperlink runs with empty text no longer emit an empty
w:hyperlink. comprehend's skeleton demo/required annotation matched the wrong key
(always None); it now keys on the region id, so the annotation actually applies.extractwraps its work in error handling (cleanERROR extract: ...+ exit 1,
matchinggenerate) and defaults--scopetoautolike the other commands.- Idempotency: a non-UTF-8
core.xmlno longer crashes the timestamp pin; the
nested-package dcterms regex uses[^<]*+count=1so it cannot cross a tag
boundary on malformed XML.
- Word/PPTX tables no longer drop multi-run column headers. A header cell
- Quality cleanups: consolidated the duplicate docx
_apply_*_stylehelpers,
removed the unusedsafe_filenameutility, dropped a redundantset()in
has_part, removed a duplicatevisual.no_pagesfinding, and stopped running
check_profiletwice in the QA gate.
Changed
component_survivalnow has a single source of truth. The pptx generator's
own pre-reconcile, drop-to-zero variant was removed; the QA gate's
check_component_survival(which re-reads the shell and output independently,
for all three formats, on any count decrease) is the sole emitter. This ends the
duplicate, differently-wordedcomponent_survivalfindings a pptx run produced.