splatthis 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. splatthis-0.2.0/CHANGELOG.md +264 -0
  2. splatthis-0.2.0/CONTRIBUTING.md +532 -0
  3. splatthis-0.2.0/LICENSE +21 -0
  4. splatthis-0.2.0/MANIFEST.in +4 -0
  5. splatthis-0.2.0/PKG-INFO +455 -0
  6. splatthis-0.2.0/README.md +408 -0
  7. splatthis-0.2.0/pyproject.toml +136 -0
  8. splatthis-0.2.0/setup.cfg +4 -0
  9. splatthis-0.2.0/src/splatthis/__init__.py +50 -0
  10. splatthis-0.2.0/src/splatthis/_version.py +3 -0
  11. splatthis-0.2.0/src/splatthis/adaptive_compute.py +520 -0
  12. splatthis-0.2.0/src/splatthis/artifact_backends.py +556 -0
  13. splatthis-0.2.0/src/splatthis/artifact_evaluation.py +126 -0
  14. splatthis-0.2.0/src/splatthis/artifact_gates.py +368 -0
  15. splatthis-0.2.0/src/splatthis/artifact_io.py +45 -0
  16. splatthis-0.2.0/src/splatthis/browser_capture.py +815 -0
  17. splatthis-0.2.0/src/splatthis/browser_export.py +426 -0
  18. splatthis-0.2.0/src/splatthis/budgets.py +338 -0
  19. splatthis-0.2.0/src/splatthis/canvas_parity.py +107 -0
  20. splatthis-0.2.0/src/splatthis/cli.py +721 -0
  21. splatthis-0.2.0/src/splatthis/color.py +50 -0
  22. splatthis-0.2.0/src/splatthis/config.py +214 -0
  23. splatthis-0.2.0/src/splatthis/conversion_engine.py +125 -0
  24. splatthis-0.2.0/src/splatthis/converter.py +12 -0
  25. splatthis-0.2.0/src/splatthis/distillation.py +608 -0
  26. splatthis-0.2.0/src/splatthis/domain.py +82 -0
  27. splatthis-0.2.0/src/splatthis/engine_artifacts.py +379 -0
  28. splatthis-0.2.0/src/splatthis/engine_configuration.py +891 -0
  29. splatthis-0.2.0/src/splatthis/engine_densification.py +769 -0
  30. splatthis-0.2.0/src/splatthis/engine_guidance.py +702 -0
  31. splatthis-0.2.0/src/splatthis/engine_initialization.py +511 -0
  32. splatthis-0.2.0/src/splatthis/engine_optimization.py +857 -0
  33. splatthis-0.2.0/src/splatthis/engine_postfit.py +887 -0
  34. splatthis-0.2.0/src/splatthis/engine_state.py +285 -0
  35. splatthis-0.2.0/src/splatthis/export_common.py +388 -0
  36. splatthis-0.2.0/src/splatthis/features.py +492 -0
  37. splatthis-0.2.0/src/splatthis/fidelity/__init__.py +32 -0
  38. splatthis-0.2.0/src/splatthis/fidelity/analysis.py +101 -0
  39. splatthis-0.2.0/src/splatthis/fidelity/config.py +66 -0
  40. splatthis-0.2.0/src/splatthis/fidelity/evaluator.py +183 -0
  41. splatthis-0.2.0/src/splatthis/fidelity/metrics.py +244 -0
  42. splatthis-0.2.0/src/splatthis/fidelity/operators.py +97 -0
  43. splatthis-0.2.0/src/splatthis/fidelity/report.py +43 -0
  44. splatthis-0.2.0/src/splatthis/fidelity/stage.py +176 -0
  45. splatthis-0.2.0/src/splatthis/io.py +132 -0
  46. splatthis-0.2.0/src/splatthis/mixed_primitives.py +447 -0
  47. splatthis-0.2.0/src/splatthis/mlx_losses.py +252 -0
  48. splatthis-0.2.0/src/splatthis/mlx_optimizer.py +176 -0
  49. splatthis-0.2.0/src/splatthis/mlx_renderer.py +537 -0
  50. splatthis-0.2.0/src/splatthis/mlx_runtime.py +56 -0
  51. splatthis-0.2.0/src/splatthis/mlx_stage.py +504 -0
  52. splatthis-0.2.0/src/splatthis/optimizer.py +131 -0
  53. splatthis-0.2.0/src/splatthis/pipeline.py +95 -0
  54. splatthis-0.2.0/src/splatthis/pipeline_artifacts.py +335 -0
  55. splatthis-0.2.0/src/splatthis/pipeline_phases.py +442 -0
  56. splatthis-0.2.0/src/splatthis/pixel_runtime.py +987 -0
  57. splatthis-0.2.0/src/splatthis/pptx_export.py +745 -0
  58. splatthis-0.2.0/src/splatthis/profiles.py +365 -0
  59. splatthis-0.2.0/src/splatthis/proxies.py +165 -0
  60. splatthis-0.2.0/src/splatthis/py.typed +0 -0
  61. splatthis-0.2.0/src/splatthis/quality.py +76 -0
  62. splatthis-0.2.0/src/splatthis/renderer.py +1428 -0
  63. splatthis-0.2.0/src/splatthis/reporting.py +72 -0
  64. splatthis-0.2.0/src/splatthis/roundtrip.py +84 -0
  65. splatthis-0.2.0/src/splatthis/splat.py +549 -0
  66. splatthis-0.2.0/src/splatthis/storage.py +202 -0
  67. splatthis-0.2.0/src/splatthis/svg_export.py +1106 -0
  68. splatthis-0.2.0/src/splatthis/svg_recipe_gate.py +236 -0
  69. splatthis-0.2.0/src/splatthis/template_assets.py +36 -0
  70. splatthis-0.2.0/src/splatthis/templates/__init__.py +1 -0
  71. splatthis-0.2.0/src/splatthis/templates/drawingml/background_shape.xml +31 -0
  72. splatthis-0.2.0/src/splatthis/templates/drawingml/blur.xml +1 -0
  73. splatthis-0.2.0/src/splatthis/templates/drawingml/close_group.xml +1 -0
  74. splatthis-0.2.0/src/splatthis/templates/drawingml/edge_segment.xml +21 -0
  75. splatthis-0.2.0/src/splatthis/templates/drawingml/effect_list.xml +3 -0
  76. splatthis-0.2.0/src/splatthis/templates/drawingml/gradient_fill.xml +7 -0
  77. splatthis-0.2.0/src/splatthis/templates/drawingml/gradient_stop.xml +3 -0
  78. splatthis-0.2.0/src/splatthis/templates/drawingml/group.xml +14 -0
  79. splatthis-0.2.0/src/splatthis/templates/drawingml/shape.xml +30 -0
  80. splatthis-0.2.0/src/splatthis/templates/drawingml/shape_no_effect.xml +29 -0
  81. splatthis-0.2.0/src/splatthis/templates/drawingml/slide.xml +24 -0
  82. splatthis-0.2.0/src/splatthis/templates/drawingml/soft_edge.xml +1 -0
  83. splatthis-0.2.0/src/splatthis/templates/drawingml/solid_fill.xml +3 -0
  84. splatthis-0.2.0/src/splatthis/templates/pptx/app_props.xml +7 -0
  85. splatthis-0.2.0/src/splatthis/templates/pptx/content_types.xml +15 -0
  86. splatthis-0.2.0/src/splatthis/templates/pptx/core_props.xml +12 -0
  87. splatthis-0.2.0/src/splatthis/templates/pptx/pres_props.xml +4 -0
  88. splatthis-0.2.0/src/splatthis/templates/pptx/presentation.xml +14 -0
  89. splatthis-0.2.0/src/splatthis/templates/pptx/presentation_rels.xml +8 -0
  90. splatthis-0.2.0/src/splatthis/templates/pptx/raster_slide.xml +49 -0
  91. splatthis-0.2.0/src/splatthis/templates/pptx/raster_slide_rels.xml +5 -0
  92. splatthis-0.2.0/src/splatthis/templates/pptx/root_rels.xml +6 -0
  93. splatthis-0.2.0/src/splatthis/templates/pptx/slide_layout.xml +26 -0
  94. splatthis-0.2.0/src/splatthis/templates/pptx/slide_layout_rels.xml +4 -0
  95. splatthis-0.2.0/src/splatthis/templates/pptx/slide_master.xml +39 -0
  96. splatthis-0.2.0/src/splatthis/templates/pptx/slide_master_rels.xml +5 -0
  97. splatthis-0.2.0/src/splatthis/templates/pptx/theme.xml +55 -0
  98. splatthis-0.2.0/src/splatthis/templates/pptx/vector_slide_rels.xml +4 -0
  99. splatthis-0.2.0/src/splatthis/templates/pptx/view_props.xml +4 -0
  100. splatthis-0.2.0/src/splatthis/templates/reporting/side_by_side.html +45 -0
  101. splatthis-0.2.0/src/splatthis/templates/svg/background.svg +1 -0
  102. splatthis-0.2.0/src/splatthis/templates/svg/blur_document.svg +7 -0
  103. splatthis-0.2.0/src/splatthis/templates/svg/blur_ellipse.svg +1 -0
  104. splatthis-0.2.0/src/splatthis/templates/svg/blur_filter.svg +3 -0
  105. splatthis-0.2.0/src/splatthis/templates/svg/close.svg +1 -0
  106. splatthis-0.2.0/src/splatthis/templates/svg/edge_group.svg +2 -0
  107. splatthis-0.2.0/src/splatthis/templates/svg/edge_line.svg +1 -0
  108. splatthis-0.2.0/src/splatthis/templates/svg/edge_path.svg +1 -0
  109. splatthis-0.2.0/src/splatthis/templates/svg/ellipse.svg +1 -0
  110. splatthis-0.2.0/src/splatthis/templates/svg/empty_document.svg +3 -0
  111. splatthis-0.2.0/src/splatthis/templates/svg/palette_background.svg +1 -0
  112. splatthis-0.2.0/src/splatthis/templates/svg/palette_document.svg +9 -0
  113. splatthis-0.2.0/src/splatthis/templates/svg/palette_ellipse.svg +1 -0
  114. splatthis-0.2.0/src/splatthis/templates/svg/palette_gradient.svg +3 -0
  115. splatthis-0.2.0/src/splatthis/templates/svg/palette_stop.svg +1 -0
  116. splatthis-0.2.0/src/splatthis/templates/svg/scripted_document.svg +9 -0
  117. splatthis-0.2.0/src/splatthis/templates/svg/scripted_runtime.js +52 -0
  118. splatthis-0.2.0/src/splatthis/templates/svg/standard_document.svg +12 -0
  119. splatthis-0.2.0/src/splatthis/templates/svg/standard_gradient.svg +3 -0
  120. splatthis-0.2.0/src/splatthis/templates/svg/standard_stop.svg +1 -0
  121. splatthis-0.2.0/src/splatthis.egg-info/PKG-INFO +455 -0
  122. splatthis-0.2.0/src/splatthis.egg-info/SOURCES.txt +124 -0
  123. splatthis-0.2.0/src/splatthis.egg-info/dependency_links.txt +1 -0
  124. splatthis-0.2.0/src/splatthis.egg-info/entry_points.txt +2 -0
  125. splatthis-0.2.0/src/splatthis.egg-info/requires.txt +28 -0
  126. splatthis-0.2.0/src/splatthis.egg-info/top_level.txt +1 -0
@@ -0,0 +1,264 @@
1
+ # Changelog
2
+
3
+ All notable changes to SplatThis are documented here.
4
+
5
+ ## Unreleased
6
+
7
+ ### Added
8
+
9
+ - A static pixel-runtime selection chain: RGBA32F WebGL2, quality-gated
10
+ RGBA16F WebGL2, exact Worker/OffscreenCanvas CPU, then exact main-thread CPU.
11
+ It records the selected backend plus compute/end-to-end timing, and supports
12
+ diagnostic backend forcing through the URL query string.
13
+ - Governing Chromium capture of the selected pixel-runtime canvas buffer, so
14
+ acceptance and manifests use the deployed path rather than an internal
15
+ proxy. On a 1,788-splat 476 x 502 Chameleon checkpoint, 32F completed in
16
+ roughly 16-19 ms and differed from exact CPU on six pixels by one byte.
17
+ - A 21-image Chrome backend gate: 32F was selected on every image with at most
18
+ one byte error and -0.0000014 worst source SSIM_sRGB delta; 16F passed its
19
+ runtime sample on 20 images and correctly fell back to exact Worker CPU on
20
+ checkerboard.
21
+ - A browser-native Canvas compositor that submits one transformed Canvas 2D
22
+ radial gradient per splat, with optional three-plane mouse parallax and
23
+ governing Chromium capture.
24
+ - A reproducible scriptless CSS linear-compositor MVP. Reversing Chameleon's
25
+ DOM draw order and using linear-sRGB fills with exact Gaussian alpha masks
26
+ improved the unchanged 1,615-splat population from 0.7017 to 0.8748
27
+ SSIM_sRGB and from 0.3182 to 0.1456 LPIPS.
28
+ - A `css` export target that emits one scriptless DOM/CSS gradient
29
+ ellipse per Gaussian, with exact-size Chromium grading and optional CSS-only
30
+ 10x10 hover-grid parallax over saliency-derived depth planes.
31
+ - Versioned, target-specific repeat-render noise floors for the Chrome pixel runtime,
32
+ Playwright Chromium SVG, and Microsoft PowerPoint slideshow captures.
33
+ - A resumable full-corpus calibration tool that retains repeated captures and
34
+ records renderer, artifact, capture, timing, and metric provenance.
35
+ - An offline adaptive pixel-runtime simulator for replaying stage checkpoints and
36
+ comparing existing 2k/4k artifacts under guarded SSIM and LPIPS policies.
37
+ - A default-off online pixel-runtime controller that can stop before densification,
38
+ later stages, and residual detail after the current run reaches an explicit
39
+ margin-adjusted Chrome quality target.
40
+ - Content-addressed adaptive-policy options in the full-corpus benchmark.
41
+ - A resumable full-frame pixel-runtime checkpoint parity calibrator and versioned
42
+ 48-checkpoint model-to-Chrome evidence.
43
+ - Versioned exact replay of all 84 raw pixel-runtime stage checkpoints across the
44
+ 21-image corpus, including a predeclared compute go/no-go comparison for
45
+ SSIM targets 0.98 and 0.979.
46
+ - A `capture` installation extra for exact Chrome pixel-runtime, native Canvas,
47
+ CSS, and SVG capture from SplatThis's own virtual environment.
48
+ - A reusable native-dimension Playwright SVG capture CLI with explicit
49
+ viewport, DPR, resource-wait, warm-up, timing, and repeat-hash provenance.
50
+ - A deterministic SVG recipe gate and full-corpus comparison overview for
51
+ standard, palette-quantized, and native-blur artifacts.
52
+ - Versioned evidence for 63 native-dimension Chromium SVG captures:
53
+ palette-quantized safely won seven images, blur won none, and the result
54
+ cleared the predeclared five-image gate for a default-off integration slice.
55
+ - A max-fidelity SVG compositor gate that browser-grades historical order,
56
+ corrected standard gradients, and corrected adaptive high gradients before
57
+ accepting or reverting the complete artifact. Its fixed ROIs, full metric
58
+ vector, compressed size, latency, and selection are retained in the manifest.
59
+ - A 33-population, 21-image SVG compositor corpus pass. Correct painter order
60
+ improved median SSIM by 0.08513 and LPIPS by 0.09097 at unchanged gzip size;
61
+ adaptive high stops added 0.01019 median SSIM with 56.8% gzip growth.
62
+ - A 21-image native-PPTX painter-order corpus pass using 42 real Microsoft
63
+ PowerPoint slideshow captures. Corrected order improved median SSIM by
64
+ 0.02662 and LPIPS by 0.03346; the guarded per-image policy selected it for
65
+ 14 images and retained legacy order for seven.
66
+ - Explicit `--pptx-painter-order legacy|back-to-front` production emission,
67
+ manifest provenance, and a resumable external real-PowerPoint selector that
68
+ atomically materializes the accepted native deck as `selected.pptx`.
69
+
70
+ ### Added
71
+
72
+ - A PEP 561 `py.typed` marker, declared in both `package-data` and
73
+ `MANIFEST.in`. The package exports 26 names as a library API and is annotated
74
+ throughout, but without the marker every consumer type-checking against the
75
+ installed distribution saw `Any`. Verified by installing the built wheel into
76
+ a clean environment and resolving `save_svg` and `GaussianSplat` to their real
77
+ signatures.
78
+
79
+ ### Changed
80
+
81
+ - Reworked the release workflow onto PyPI Trusted Publishing, matching the
82
+ sibling `openxml-audit` repository, which has shipped five releases through
83
+ the same shape. No API token is stored in the repository: PyPI mints a
84
+ short-lived credential per workflow run via OIDC. The trigger also moves from
85
+ `release: published` to `push: tags: v*` — the old trigger required a GitHub
86
+ Release to exist before the workflow would run, so pushing a tag alone did
87
+ nothing; the workflow now creates the release itself. Build, PyPI publish, and
88
+ GitHub release are separate jobs sharing one built artifact, and the wheel
89
+ smoke test runs in a throwaway venv so it cannot be satisfied by build
90
+ dependencies present in the job environment.
91
+ - Declared the conversion engine's shared mixin surface in `engine_state.py`:
92
+ 35 state attributes and 32 cross-mixin method signatures, inherited by all
93
+ seven mixins. Only 4 of those attributes previously carried any annotation.
94
+ The declaration is inert — no runtime members, last in the MRO — so state
95
+ ownership and method implementations are unchanged, and a seeded Torch
96
+ conversion emits a byte-identical SVG before and after. Corrected the
97
+ dependency inversion where artifact backends and pipeline phases annotated
98
+ the public `PNG2SVGConverter` facade rather than the `ConversionEngine` base
99
+ they actually receive. Together: mypy 778 → 462 errors, `attr-defined`
100
+ 340 → 1.
101
+ - Documented what a fixed `--seed` actually guarantees per optimizer backend.
102
+ Torch reproduces the emitted artifact byte for byte; MLX does not. Metal
103
+ orders float32 reductions nondeterministically, so repeated single-process
104
+ seeded MLX runs differ by roughly one float32 ULP (~3e-8) in splat
105
+ parameters, which is enough to tip a rounded SVG attribute across a
106
+ formatting boundary. Reported metrics still agree to nine significant
107
+ figures, so the quoted four-decimal corpus medians are unaffected. The
108
+ previous note attributed MLX nondeterminism solely to concurrent processes
109
+ sharing one Metal device; it also occurs in a single process. "Reproducible
110
+ manifests" in the project status is now "provenance-complete manifests".
111
+ - Corrected package metadata that would have been immutable after the first
112
+ release: the author contact was a placeholder for a nonexistent domain, and
113
+ the summary and keywords claimed SVG-only conversion.
114
+ - Collapsed four project names onto one. The distribution is now `splatthis`
115
+ (was `splat-this`), the import path is `splatthis` (was `png2svg_gs`), and the
116
+ console entry point is `splatthis` (was `splatlify`). The repository, the
117
+ GitHub Pages site, and the project name in prose are unchanged. `png2svg_gs`
118
+ had also become inaccurate: the package emits SVG, PPTX, native Canvas, CSS,
119
+ and pixel-runtime artifacts, not only SVG. No compatibility shim or alias
120
+ entry point is provided — the package has never been published to PyPI, so
121
+ there is no installed base to migrate.
122
+ - Removed the unreferenced root-level `png2svg` launcher. It exposed an older,
123
+ divergent flag surface (`--max-splats`, `--output-format {svg,drawingml,pptx}`,
124
+ `--backend {auto,torch,gsplat}`) that no longer matched the packaged CLI, and
125
+ its `gsplat` backend has been retired and is now explicitly rejected. The
126
+ packaged `splatthis` entry point is the only supported command-line surface.
127
+ - Replaced the state-restoring monolithic conversion run with an immutable
128
+ `ConverterConfig`, per-call `ConversionRequest`/`RunContext`, and explicit
129
+ prepare, fit, and deployment phases. The public converter no longer mutates
130
+ and restores its own budget state, and its coordinator is now a thin facade.
131
+ - Reduced `converter.py` to a stable public facade and `conversion_engine.py`
132
+ to a 123-line composition root. Configuration, initialization, optimization,
133
+ densification, post-fit, artifact strategy, and regional guidance now have
134
+ separate internal modules; constructor branches are isolated behind focused
135
+ setup helpers.
136
+ - Added one artifact-backend registry for SVG, DrawingML, PPTX, native Canvas,
137
+ CSS, and pixel-runtime emission, persistence, governing evaluation, and
138
+ evidence provenance. PPTX persistence reuses its already-emitted DrawingML
139
+ payload instead of generating the full shape tree twice.
140
+ - Split atomic storage, pure quality metrics, browser artifact evaluation,
141
+ reporting, and round-trip validation into one-way dependency layers.
142
+ `artifact_io` is now also a compatibility facade, and the side-by-side HTML
143
+ document moved to a packaged template.
144
+ - Replaced the 3,541-line I/O monolith with focused artifact-I/O, shared export,
145
+ browser, SVG, PPTX, pixel-runtime, and color modules. `splatthis.io` remains
146
+ a 132-line compatibility facade, while production code imports the focused
147
+ implementations directly. SVG, DrawingML, and PPTX package markup now lives
148
+ in packaged templates rather than Python source; representative emitted
149
+ artifacts remain byte-identical. NumPy color transforms now have one shared
150
+ implementation.
151
+ - Torch/CPU corpus runs accept opt-in `--jobs N` subprocess parallelism while
152
+ keeping JSONL writes and artifact scoring coordinated in one thread. Parallel
153
+ MLX runs are rejected because shared-Metal processes caused seeded parameter
154
+ drift. Resumability now reuses only successful records whose primary artifact
155
+ still matches its recorded size and SHA-256, so failed, corrupted, and
156
+ partially deleted runs are retried instead of becoming false cache hits.
157
+ - The explicit `fast` MLX profile now renders 32 tiles per batch. A 21-image,
158
+ full-frame 512-splat sweep reduced median optimizer time by 42% and median
159
+ wall time by 23%; balanced and max-fidelity retain the conservative 8-tile
160
+ behavior because low-budget per-image fidelity moved in both directions.
161
+ - Conversion reuses its already-computed linear proxy framebuffer when writing
162
+ the optional proxy PNG, eliminating a second full CPU splat render. Internal
163
+ Python pixel-runtime helpers now use explicit names; the ambiguous historical
164
+ `generate_canvas_html` aliases were removed.
165
+ - Internal `*_splat_proxy.png` files are now emitted only when explicitly
166
+ requested or required by a side-by-side report, instead of appearing beside
167
+ every normal conversion and being mistaken for the deployed artifact.
168
+ - Removed the unshipped gsplat adapter, which depended on private legacy 2D
169
+ APIs and was neither packaged nor used by release benchmarks. Renderer
170
+ `auto` now resolves deterministically to the Torch reference backend.
171
+ - The former `canvas` output is now named `pixel-runtime`, because it
172
+ software-rasterizes the splat equations into an `ImageData` framebuffer.
173
+ `canvas` now means the genuine Canvas 2D primitive compositor. Historical
174
+ corpus and noise results are labelled as pixel-runtime evidence.
175
+ - Same-population Chameleon documentation now distinguishes the actual
176
+ browser SVG (0.7076 SSIM), browser-gated palette recipe (0.7274), internal
177
+ software preview (0.8803), and pixel runtime (0.9045).
178
+ - Pixel-runtime capture can retain every repeated browser rendering for calibration
179
+ instead of keeping only the final PNG.
180
+ - Adaptive pixel-runtime targets now denote desired Chrome quality and are evaluated
181
+ with a deployed scorer that mirrors JavaScript double math, Float32Array
182
+ accumulation, and 8-bit sRGB ImageData packing. All 48 calibrated
183
+ checkpoints matched Chrome pixel-for-pixel, so the default model-to-browser
184
+ safety margin is zero; optional cross-version overrides remain available.
185
+ - ADR-003 now distinguishes the implemented artifact-gate foundation,
186
+ retrospective simulation, and bounded online hard-target controller from
187
+ still-proposed predictive allocation, selective 8k scaling, broader
188
+ operators, and hybrid residuals.
189
+ - The adaptive simulator now rescores canonical raw stages at the exact ImageData
190
+ byte boundary instead of depending on historical continuous manifest scores,
191
+ and models only the online hard-target stop rather than offline plateau or
192
+ regression rules. Both tested targets saved 1.3% of aggregate stage time,
193
+ below the 5% gate, so further hard-target A/B expansion is not recommended.
194
+ - Pixel-runtime calibration now defaults to the active SplatThis interpreter instead
195
+ of a Playwright environment in the sibling `svg2pptx` repository.
196
+ - The SVG recipe gate now evaluates browser-delivered SVG with a reused
197
+ Chromium process instead of librsvg. One unmeasured filter warm-up precedes
198
+ three required byte-identical captures, avoiding a first-draw one-level
199
+ pixel wobble without charging browser startup to every recipe.
200
+ - Browser-delivered SVG is now governed by one shared Playwright Chromium
201
+ renderer across core export grading, ADR-003 fidelity, corpus benchmarking,
202
+ artifact calibration, and experimental runners. CairoSVG and librsvg are no
203
+ longer implicit deployed-artifact fallbacks. If Chromium is unavailable, SVG
204
+ acceptance now fails closed while retaining proxy metrics as diagnostics only.
205
+ - Repeated SVG evaluation now reuses one Chromium page and decodes governing
206
+ frames in memory; per-artifact geometry is validated once before measured
207
+ repeat captures.
208
+ - SVG gradient fidelity is now a policy (`standard` or adaptive `high`) rather
209
+ than another primitive recipe. High uses a 0.005 opacity-curve error bound,
210
+ up to nine stops, and four-decimal opacity.
211
+
212
+ ### Fixed
213
+
214
+ - Score pixel-runtime checkpoints at the emitted 8-bit framebuffer boundary instead
215
+ of comparing a continuous float proxy with Chrome. This removes up to
216
+ 0.001102 SSIM of systematic score overstatement in the calibration set.
217
+ - Preserve the virtual-environment Python symlink when launching Playwright
218
+ capture, rather than resolving it to a system interpreter without the venv's
219
+ packages; checkpoint calibration now also fails dependency checks once,
220
+ before entering the corpus loop.
221
+ - Emit standard, browser-compatible, scripted-matrix, palette-quantized, and
222
+ blur SVG splats in back-to-front painter order while leaving the exact
223
+ front-to-back pixel runtime unchanged.
224
+
225
+ ## 0.2.0 - 2026-07-30
226
+
227
+ ### Added
228
+
229
+ - Target-aware pixel-runtime, SVG, and native DrawingML/PPTX export pipelines.
230
+ - MLX optimization with periodic tile-plan rebuilds and full geometry training.
231
+ - Actual-artifact SVG evaluation and real-PowerPoint corpus capture tooling.
232
+ - Monotonic pixel-runtime checkpoint and post-processing gates.
233
+ - Browser-pixel-buffer corpus metrics, per-picture comparisons, and budget history.
234
+ - Optional layered pixel-runtime parallax.
235
+ - Experimental Top-K distillation and mixed-primitive MVP tooling.
236
+
237
+ ### Changed
238
+
239
+ - MLX now defaults to eight tiles per batch. Three real corpus checkpoints
240
+ measured 12-34% lower median forward-and-backward latency than a 16-tile
241
+ batch without changing render math; on the Chameleon converter-default
242
+ comparison it was 23% lower than 128 tiles.
243
+ - The corpus overview renders canvases lazily near the viewport.
244
+ - Canvas splats are sorted once during export instead of at every page load.
245
+ - Internal PNGs are named and described as splat proxies, not screenshots of
246
+ the emitted SVG or PPTX.
247
+ - Package metadata and documentation now report full-corpus, deployed-artifact
248
+ results instead of extrapolating from a favorable single image.
249
+
250
+ ### Fixed
251
+
252
+ - Correct rotated anisotropic footprint bounds in Canvas and NumPy rendering.
253
+ - Fall back to Torch when MLX imports but no Metal device is available.
254
+ - Publish SVG, PPTX, Canvas, JSON, manifest, and proxy-PNG outputs atomically.
255
+ - Escape Canvas document titles and reject invalid canvas dimensions.
256
+ - Report the real number of parallax layers instead of JSON-string length.
257
+ - Return concise CLI errors for invalid or unreadable input.
258
+
259
+ ### Compatibility
260
+
261
+ - Python 3.13 or newer is required.
262
+ - MLX remains optional and requires an Apple-Silicon Metal session.
263
+ - PPTX quality claims refer to Microsoft PowerPoint slideshow captures;
264
+ internal proxies and LibreOffice renders are labeled separately.