hyperweave 0.3.8__tar.gz → 0.3.10__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 (464) hide show
  1. {hyperweave-0.3.8 → hyperweave-0.3.10}/.gitignore +4 -0
  2. {hyperweave-0.3.8 → hyperweave-0.3.10}/CHANGELOG.md +61 -1
  3. {hyperweave-0.3.8 → hyperweave-0.3.10}/PKG-INFO +6 -2
  4. {hyperweave-0.3.8 → hyperweave-0.3.10}/README.md +5 -1
  5. {hyperweave-0.3.8 → hyperweave-0.3.10}/justfile +7 -3
  6. hyperweave-0.3.10/scripts/extract_font_metrics.py +327 -0
  7. hyperweave-0.3.10/scripts/generate_proofset.py +4579 -0
  8. hyperweave-0.3.10/scripts/proofset_harness.py +287 -0
  9. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/_version.py +2 -2
  10. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/cli.py +2 -2
  11. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/assembler.py +13 -2
  12. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/bar_chart.py +16 -0
  13. hyperweave-0.3.10/src/hyperweave/compose/chart_layout.py +264 -0
  14. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/context.py +68 -45
  15. hyperweave-0.3.10/src/hyperweave/compose/layout.py +1401 -0
  16. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/resolver.py +1144 -304
  17. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/resolvers/chart.py +72 -12
  18. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/resolvers/stats.py +62 -90
  19. hyperweave-0.3.10/src/hyperweave/compose/spatial_records.py +36 -0
  20. hyperweave-0.3.10/src/hyperweave/compose/stats_layout.py +698 -0
  21. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/treemap.py +12 -0
  22. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/connectors/base.py +6 -0
  23. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/connectors/rest.py +5 -1
  24. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/enums.py +0 -1
  25. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/font_metrics.py +22 -0
  26. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/models.py +1 -2
  27. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/paradigm.py +291 -7
  28. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/schema.py +8 -0
  29. hyperweave-0.3.10/src/hyperweave/core/text.py +268 -0
  30. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/font-embedding.yaml +0 -3
  31. hyperweave-0.3.10/src/hyperweave/data/font-metrics/barlow-condensed-900.json +3464 -0
  32. hyperweave-0.3.10/src/hyperweave/data/font-metrics/chakra-petch.json +3463 -0
  33. hyperweave-0.3.10/src/hyperweave/data/font-metrics/inter.json +4328 -0
  34. hyperweave-0.3.10/src/hyperweave/data/font-metrics/jetbrains-mono.json +877 -0
  35. hyperweave-0.3.10/src/hyperweave/data/font-metrics/orbitron.json +4278 -0
  36. hyperweave-0.3.10/src/hyperweave/data/fonts/inter.b64 +1 -0
  37. hyperweave-0.3.10/src/hyperweave/data/fonts/inter.meta.json +1 -0
  38. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/genomes/chrome.json +2 -10
  39. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/genomes/telemetry-voltage.json +1 -2
  40. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/paradigms/brutalist.yaml +68 -9
  41. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/paradigms/cellular.yaml +88 -5
  42. hyperweave-0.3.10/src/hyperweave/data/paradigms/chrome.yaml +192 -0
  43. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/mcp/server.py +6 -4
  44. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/render/chart_engine.py +342 -79
  45. hyperweave-0.3.10/src/hyperweave/render/glyph_metrics.py +150 -0
  46. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/render/motion.py +38 -1
  47. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/serve/app.py +70 -1
  48. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-markers/diamond.svg.j2 +1 -1
  49. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-markers/endpoint-diamond.svg.j2 +4 -4
  50. hyperweave-0.3.10/src/hyperweave/templates/components/chart-markers/endpoint-rect.svg.j2 +12 -0
  51. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-markers/rect.svg.j2 +3 -3
  52. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-milestone-brutalist.svg.j2 +4 -4
  53. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-milestone.svg.j2 +1 -1
  54. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/filter.svg.j2 +1 -1
  55. hyperweave-0.3.10/src/hyperweave/templates/components/glyph-inline.svg.j2 +11 -0
  56. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/glyph.svg.j2 +2 -3
  57. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/metadata.svg.j2 +1 -1
  58. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/metric.svg.j2 +3 -3
  59. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/phase-segment.svg.j2 +3 -3
  60. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/rule.svg.j2 +2 -2
  61. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/status.svg.j2 +6 -4
  62. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/error-badge.svg.j2 +49 -44
  63. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/brutalist-dark-content.j2 +16 -17
  64. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/brutalist-light-content.j2 +12 -14
  65. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/cellular-content.j2 +22 -46
  66. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/cellular-defs.j2 +1 -1
  67. hyperweave-0.3.10/src/hyperweave/templates/frames/badge/chrome-content.j2 +66 -0
  68. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/chrome-defs.j2 +5 -5
  69. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge.svg.j2 +0 -4
  70. hyperweave-0.3.10/src/hyperweave/templates/frames/catalog.svg.j2 +75 -0
  71. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/chart/brutalist-dark-content.j2 +35 -35
  72. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/chart/brutalist-defs.j2 +21 -27
  73. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/chart/brutalist-light-content.j2 +47 -41
  74. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/chart/cellular-content.j2 +34 -34
  75. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/chart/cellular-defs.j2 +6 -3
  76. hyperweave-0.3.10/src/hyperweave/templates/frames/chart/chrome-content.j2 +150 -0
  77. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/chart/chrome-defs.j2 +36 -14
  78. hyperweave-0.3.10/src/hyperweave/templates/frames/divider/brutalist-seam.svg.j2 +41 -0
  79. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/divider/chrome-band.svg.j2 +1 -1
  80. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/divider.svg.j2 +71 -132
  81. hyperweave-0.3.10/src/hyperweave/templates/frames/icon/brutalist-content.j2 +33 -0
  82. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/icon/cellular-content.j2 +4 -40
  83. hyperweave-0.3.10/src/hyperweave/templates/frames/icon/chrome-content.j2 +59 -0
  84. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/icon/chrome-defs.j2 +7 -7
  85. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/icon.svg.j2 +0 -1
  86. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-content.j2 +1 -1
  87. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-overlay.j2 +2 -2
  88. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/cellular-content.j2 +1 -1
  89. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/cellular-defs.j2 +1 -1
  90. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/cellular-overlay.j2 +2 -2
  91. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/chrome-content.j2 +2 -2
  92. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/chrome-defs.j2 +6 -7
  93. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/chrome-overlay.j2 +6 -6
  94. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal.svg.j2 +3 -3
  95. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/receipt.svg.j2 +53 -54
  96. hyperweave-0.3.10/src/hyperweave/templates/frames/rhythm-strip.svg.j2 +138 -0
  97. hyperweave-0.3.10/src/hyperweave/templates/frames/stats/brutalist-dark-content.j2 +160 -0
  98. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/stats/brutalist-defs.j2 +2 -2
  99. hyperweave-0.3.10/src/hyperweave/templates/frames/stats/brutalist-light-content.j2 +167 -0
  100. hyperweave-0.3.10/src/hyperweave/templates/frames/stats/cellular-content.j2 +121 -0
  101. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/stats/cellular-defs.j2 +5 -2
  102. hyperweave-0.3.10/src/hyperweave/templates/frames/stats/chrome-content.j2 +124 -0
  103. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/stats/chrome-defs.j2 +11 -8
  104. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/brutalist-dark-content.j2 +35 -27
  105. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/brutalist-light-content.j2 +31 -27
  106. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/brutalist-status.j2 +3 -3
  107. hyperweave-0.3.10/src/hyperweave/templates/frames/strip/cellular-content.j2 +39 -0
  108. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/cellular-status.j2 +3 -4
  109. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/chrome-content.j2 +12 -8
  110. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/chrome-defs.j2 +11 -11
  111. hyperweave-0.3.10/src/hyperweave/templates/frames/strip/chrome-status.j2 +19 -0
  112. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip.svg.j2 +43 -72
  113. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/motions/border/chromatic-pulse.svg.j2 +1 -1
  114. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/motions/border/corner-trace.svg.j2 +1 -1
  115. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/motions/border/dual-orbit.svg.j2 +3 -3
  116. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/motions/border/entanglement.svg.j2 +6 -6
  117. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/motions/border/rimrun.svg.j2 +4 -24
  118. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/partials/provider-glyphs.svg.j2 +1 -6
  119. hyperweave-0.3.10/tests/fixtures/proofset_data.json +811 -0
  120. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/snapshots/url_stability/divider_band_chrome_static.svg +0 -19
  121. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/snapshots/url_stability/icon_github_chrome_static.svg +0 -19
  122. hyperweave-0.3.10/tests/test_algorithmic_geometry.py +458 -0
  123. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_assembler.py +42 -0
  124. hyperweave-0.3.10/tests/test_badge_cellular.py +385 -0
  125. hyperweave-0.3.10/tests/test_badge_layout.py +389 -0
  126. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_chart_engine.py +71 -11
  127. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_font_gating.py +3 -4
  128. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_font_metrics_chakra.py +30 -7
  129. hyperweave-0.3.10/tests/test_font_metrics_inter.py +29 -0
  130. hyperweave-0.3.10/tests/test_glyph_metrics.py +151 -0
  131. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_marquee_v0_2_16.py +10 -8
  132. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_mcp.py +9 -0
  133. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_paradigm_cellular.py +2 -1
  134. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_proofset.py +47 -30
  135. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_receipt_token_compliance.py +14 -5
  136. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_render.py +1 -0
  137. hyperweave-0.3.10/tests/test_spatial_stencils.py +225 -0
  138. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_strip_brutalist_grammar.py +59 -19
  139. hyperweave-0.3.10/tests/test_strip_invariance.py +280 -0
  140. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_telemetry_contract_per_stage.py +1 -1
  141. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_telemetry_skin_dispatch.py +0 -7
  142. {hyperweave-0.3.8 → hyperweave-0.3.10}/uv.lock +4 -0
  143. hyperweave-0.3.8/hooks/session_end.sh +0 -6
  144. hyperweave-0.3.8/scripts/extract_font_metrics.py +0 -200
  145. hyperweave-0.3.8/scripts/generate_proofset.py +0 -1722
  146. hyperweave-0.3.8/src/hyperweave/compose/layout.py +0 -353
  147. hyperweave-0.3.8/src/hyperweave/core/text.py +0 -65
  148. hyperweave-0.3.8/src/hyperweave/data/font-metrics/chakra-petch.json +0 -110
  149. hyperweave-0.3.8/src/hyperweave/data/font-metrics/inter.json +0 -107
  150. hyperweave-0.3.8/src/hyperweave/data/font-metrics/jetbrains-mono.json +0 -113
  151. hyperweave-0.3.8/src/hyperweave/data/font-metrics/orbitron.json +0 -108
  152. hyperweave-0.3.8/src/hyperweave/data/paradigms/chrome.yaml +0 -100
  153. hyperweave-0.3.8/src/hyperweave/templates/components/chart-markers/endpoint-rect.svg.j2 +0 -12
  154. hyperweave-0.3.8/src/hyperweave/templates/components/glyph-inline.svg.j2 +0 -10
  155. hyperweave-0.3.8/src/hyperweave/templates/frames/badge/chrome-content.j2 +0 -57
  156. hyperweave-0.3.8/src/hyperweave/templates/frames/catalog.svg.j2 +0 -92
  157. hyperweave-0.3.8/src/hyperweave/templates/frames/chart/chrome-content.j2 +0 -129
  158. hyperweave-0.3.8/src/hyperweave/templates/frames/divider/brutalist-seam.svg.j2 +0 -49
  159. hyperweave-0.3.8/src/hyperweave/templates/frames/icon/brutalist-content.j2 +0 -33
  160. hyperweave-0.3.8/src/hyperweave/templates/frames/icon/chrome-content.j2 +0 -62
  161. hyperweave-0.3.8/src/hyperweave/templates/frames/master-card.svg.j2 +0 -144
  162. hyperweave-0.3.8/src/hyperweave/templates/frames/rhythm-strip.svg.j2 +0 -138
  163. hyperweave-0.3.8/src/hyperweave/templates/frames/stats/brutalist-dark-content.j2 +0 -169
  164. hyperweave-0.3.8/src/hyperweave/templates/frames/stats/brutalist-light-content.j2 +0 -176
  165. hyperweave-0.3.8/src/hyperweave/templates/frames/stats/cellular-content.j2 +0 -146
  166. hyperweave-0.3.8/src/hyperweave/templates/frames/stats/chrome-content.j2 +0 -134
  167. hyperweave-0.3.8/src/hyperweave/templates/frames/strip/cellular-content.j2 +0 -55
  168. hyperweave-0.3.8/src/hyperweave/templates/frames/strip/chrome-status.j2 +0 -13
  169. hyperweave-0.3.8/tests/test_badge_cellular.py +0 -148
  170. hyperweave-0.3.8/tests/test_badge_layout.py +0 -301
  171. {hyperweave-0.3.8 → hyperweave-0.3.10}/.dockerignore +0 -0
  172. {hyperweave-0.3.8 → hyperweave-0.3.10}/.github/workflows/ci.yml +0 -0
  173. {hyperweave-0.3.8 → hyperweave-0.3.10}/.github/workflows/deploy.yml +0 -0
  174. {hyperweave-0.3.8 → hyperweave-0.3.10}/.github/workflows/publish.yml +0 -0
  175. {hyperweave-0.3.8 → hyperweave-0.3.10}/.pre-commit-config.yaml +0 -0
  176. {hyperweave-0.3.8 → hyperweave-0.3.10}/Dockerfile +0 -0
  177. {hyperweave-0.3.8 → hyperweave-0.3.10}/LICENSE +0 -0
  178. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/buttons/button-liquid.svg +0 -0
  179. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/cards/card-butterfly.svg +0 -0
  180. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/cards/card-python.svg +0 -0
  181. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/cards/card-sunflower.svg +0 -0
  182. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/cards/card-waves.svg +0 -0
  183. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/badge_critical.svg +0 -0
  184. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/badge_passing.svg +0 -0
  185. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/badge_warning.svg +0 -0
  186. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/banner.svg +0 -0
  187. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/icons/discord.svg +0 -0
  188. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/icons/notion.svg +0 -0
  189. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/icons/reddit.svg +0 -0
  190. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/icons/spotify.svg +0 -0
  191. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/icons/youtube.svg +0 -0
  192. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/marquee_counter.svg +0 -0
  193. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/marquee_horizontal.svg +0 -0
  194. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/marquee_vertical.svg +0 -0
  195. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/profile-cards/chart_stars_full.svg +0 -0
  196. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/profile-cards/stats.svg +0 -0
  197. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/brutalist-emerald/strip.svg +0 -0
  198. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/badge_critical.svg +0 -0
  199. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/badge_passing.svg +0 -0
  200. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/badge_warning.svg +0 -0
  201. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/banner.svg +0 -0
  202. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/icons/bluesky.svg +0 -0
  203. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/icons/github.svg +0 -0
  204. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/icons/instagram.svg +0 -0
  205. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/icons/mastodon.svg +0 -0
  206. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/icons/x.svg +0 -0
  207. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/marquee_counter.svg +0 -0
  208. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/marquee_horizontal.svg +0 -0
  209. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/marquee_vertical.svg +0 -0
  210. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/profile-cards/chart_stars_full.svg +0 -0
  211. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/profile-cards/stats.svg +0 -0
  212. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/chrome-horizon/strip.svg +0 -0
  213. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/telemetry/master_card.svg +0 -0
  214. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/telemetry/receipt.svg +0 -0
  215. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/telemetry/receipt_claude-code_medium.svg +0 -0
  216. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/telemetry/receipt_codex_large.svg +0 -0
  217. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/telemetry/receipt_voltage_xlarge.svg +0 -0
  218. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/telemetry/rhythm_strip.svg +0 -0
  219. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/examples/telemetry/rhythm_strip_voltage_xlarge.svg +0 -0
  220. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/footers/inneraura-footer-liquid.svg +0 -0
  221. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/footers/inneraura-footer-purple.svg +0 -0
  222. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/footers/inneraura-footer.svg +0 -0
  223. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/hyperweave-banner.svg +0 -0
  224. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/icons/cobalt-sapphire-discord.svg +0 -0
  225. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/icons/cobalt-sapphire-docs.svg +0 -0
  226. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/icons/cobalt-sapphire-github.svg +0 -0
  227. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/icons/cobalt-sapphire-instagram.svg +0 -0
  228. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/icons/cobalt-sapphire-linkedin.svg +0 -0
  229. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/icons/cobalt-sapphire-tiktok.svg +0 -0
  230. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/icons/cobalt-sapphire-x.svg +0 -0
  231. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/icons/cobalt-sapphire-youtube.svg +0 -0
  232. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/marquees/badge-showcase-triple.svg +0 -0
  233. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/marquees/genome-marquee-triple.svg +0 -0
  234. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/marquees/sample-badges.svg +0 -0
  235. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/404.svg +0 -0
  236. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/callout-icons.svg +0 -0
  237. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/divider.svg +0 -0
  238. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/favicon.svg +0 -0
  239. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/hero-banner.svg +0 -0
  240. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/hyperweave-banner-v2.svg +0 -0
  241. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/hyperweave-navbar-logo.svg +0 -0
  242. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/loader.svg +0 -0
  243. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/mintlify-assets/og-image.svg +0 -0
  244. {hyperweave-0.3.8 → hyperweave-0.3.10}/assets/timelines/hyperweave-roadmap.svg +0 -0
  245. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/assets/favicon.svg +0 -0
  246. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/assets/hyperweave-banner.svg +0 -0
  247. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/assets/hyperweave-navbar-logo.svg +0 -0
  248. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/assets/og-image.svg +0 -0
  249. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/explanation/architecture.mdx +0 -0
  250. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/explanation/camo-compatibility.mdx +0 -0
  251. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/explanation/cim-compliance.mdx +0 -0
  252. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/explanation/genome-profile-system.mdx +0 -0
  253. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/explanation/metadata-tiers.mdx +0 -0
  254. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/how-to/add-motion-to-badges.mdx +0 -0
  255. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/how-to/create-session-receipts.mdx +0 -0
  256. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/how-to/set-up-claude-code-hooks.mdx +0 -0
  257. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/how-to/use-live-data-badges.mdx +0 -0
  258. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/introduction.mdx +0 -0
  259. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/mint.json +0 -0
  260. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/quickstart.mdx +0 -0
  261. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/reference/cli.mdx +0 -0
  262. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/reference/compose-spec.mdx +0 -0
  263. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/reference/genomes.mdx +0 -0
  264. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/reference/http-api.mdx +0 -0
  265. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/reference/mcp-tools.mdx +0 -0
  266. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/reference/motions.mdx +0 -0
  267. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/reference/telemetry-contract.mdx +0 -0
  268. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/spec/hyperweave-protocol.mdx +0 -0
  269. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/tutorials/build-an-artifact-kit.mdx +0 -0
  270. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/tutorials/compose-your-first-badge.mdx +0 -0
  271. {hyperweave-0.3.8 → hyperweave-0.3.10}/docs/tutorials/install-session-telemetry.mdx +0 -0
  272. {hyperweave-0.3.8 → hyperweave-0.3.10}/fly.toml +0 -0
  273. {hyperweave-0.3.8 → hyperweave-0.3.10}/hooks/install.py +0 -0
  274. {hyperweave-0.3.8 → hyperweave-0.3.10}/pyproject.toml +0 -0
  275. {hyperweave-0.3.8 → hyperweave-0.3.10}/scripts/extract_glyphs.py +0 -0
  276. {hyperweave-0.3.8 → hyperweave-0.3.10}/scripts/probe_live_stats.py +0 -0
  277. {hyperweave-0.3.8 → hyperweave-0.3.10}/scripts/probe_star_history.py +0 -0
  278. {hyperweave-0.3.8 → hyperweave-0.3.10}/scripts/stress_test.py +0 -0
  279. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/__init__.py +0 -0
  280. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/__main__.py +0 -0
  281. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/__init__.py +0 -0
  282. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/engine.py +0 -0
  283. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/lanes.py +0 -0
  284. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/palette.py +0 -0
  285. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/reasoning.py +0 -0
  286. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/resolvers/__init__.py +0 -0
  287. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/rhythm.py +0 -0
  288. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/rhythm_strip.py +0 -0
  289. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/compose/validate_paradigms.py +0 -0
  290. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/config/__init__.py +0 -0
  291. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/config/genome_validator.py +0 -0
  292. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/config/loader.py +0 -0
  293. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/config/registry.py +0 -0
  294. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/config/settings.py +0 -0
  295. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/connectors/__init__.py +0 -0
  296. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/connectors/arxiv.py +0 -0
  297. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/connectors/cache.py +0 -0
  298. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/connectors/github.py +0 -0
  299. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/__init__.py +0 -0
  300. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/cell_layout.py +0 -0
  301. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/color.py +0 -0
  302. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/contracts.py +0 -0
  303. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/state.py +0 -0
  304. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/core/thresholds.py +0 -0
  305. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/badge_modes.yaml +0 -0
  306. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/css/accessibility.css +0 -0
  307. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/css/bridge.css +0 -0
  308. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/css/expression.css +0 -0
  309. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/css/status.css +0 -0
  310. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/barlow-condensed-700.b64 +0 -0
  311. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/barlow-condensed-700.meta.json +0 -0
  312. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/barlow-condensed-900.b64 +0 -0
  313. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/barlow-condensed-900.meta.json +0 -0
  314. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/chakra-petch.b64 +0 -0
  315. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/chakra-petch.meta.json +0 -0
  316. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/jetbrains-mono.b64 +0 -0
  317. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/jetbrains-mono.meta.json +0 -0
  318. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/orbitron.b64 +0 -0
  319. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/fonts/orbitron.meta.json +0 -0
  320. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/genomes/automata.json +0 -0
  321. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/genomes/brutalist.json +0 -0
  322. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/genomes/telemetry-claude-code.json +0 -0
  323. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/genomes/telemetry-codex.json +0 -0
  324. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/genomes/telemetry-cream.json +0 -0
  325. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/glyphs.json +0 -0
  326. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/motions/border/chromatic-pulse.yaml +0 -0
  327. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/motions/border/corner-trace.yaml +0 -0
  328. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/motions/border/dual-orbit.yaml +0 -0
  329. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/motions/border/entanglement.yaml +0 -0
  330. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/motions/border/rimrun.yaml +0 -0
  331. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/motions/static.yaml +0 -0
  332. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/paradigms/default.yaml +0 -0
  333. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/policies/normal.json +0 -0
  334. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/policies/permissive.json +0 -0
  335. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/policies/ungoverned.json +0 -0
  336. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/profiles/brutalist.contract.json +0 -0
  337. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/profiles/brutalist.yaml +0 -0
  338. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/profiles/chrome.contract.json +0 -0
  339. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/profiles/chrome.yaml +0 -0
  340. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/reasoning/__init__.py +0 -0
  341. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/reasoning/brutalist.yaml +0 -0
  342. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/specimens.yaml +0 -0
  343. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/telemetry/model-pricing.yaml +0 -0
  344. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/telemetry/runtimes/claude-code.yaml +0 -0
  345. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/telemetry/runtimes/codex.yaml +0 -0
  346. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/telemetry/stage-config.yaml +0 -0
  347. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/telemetry/stage-labels.yaml +0 -0
  348. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/telemetry/tool-colors.yaml +0 -0
  349. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/arrow.json +0 -0
  350. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/aurora.json +0 -0
  351. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/beacon.json +0 -0
  352. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/bracket3d.json +0 -0
  353. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/chevron.json +0 -0
  354. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/crosshair.json +0 -0
  355. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/diamond.json +0 -0
  356. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/rocket.json +0 -0
  357. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/rules/bar.json +0 -0
  358. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/rules/dashed.json +0 -0
  359. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/rules/five-wave.json +0 -0
  360. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/rules/spectral.json +0 -0
  361. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/rules/straight.json +0 -0
  362. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/rules/wave.json +0 -0
  363. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/data/terminals/stijl.json +0 -0
  364. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/kit.py +0 -0
  365. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/mcp/__init__.py +0 -0
  366. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/mcp/__main__.py +0 -0
  367. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/py.typed +0 -0
  368. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/render/__init__.py +0 -0
  369. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/render/fonts.py +0 -0
  370. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/render/glyphs.py +0 -0
  371. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/render/templates.py +0 -0
  372. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/serve/__init__.py +0 -0
  373. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/serve/data_tokens.py +0 -0
  374. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/__init__.py +0 -0
  375. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/capture.py +0 -0
  376. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/codex_parser.py +0 -0
  377. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/contract.py +0 -0
  378. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/corrections.py +0 -0
  379. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/cost.py +0 -0
  380. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/models.py +0 -0
  381. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/parser.py +0 -0
  382. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/receipt_paths.py +0 -0
  383. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/runtimes.py +0 -0
  384. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/telemetry/stages.py +0 -0
  385. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-area.svg.j2 +0 -0
  386. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-axes.svg.j2 +0 -0
  387. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-empty-state.svg.j2 +0 -0
  388. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-gridlines.svg.j2 +0 -0
  389. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-markers/circle.svg.j2 +0 -0
  390. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/chart-polyline.svg.j2 +0 -0
  391. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/gradient.svg.j2 +0 -0
  392. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/components/terminal.svg.j2 +0 -0
  393. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/document.svg.j2 +0 -0
  394. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/brutalist-content.j2 +0 -0
  395. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/brutalist-defs.j2 +0 -0
  396. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/default-content.j2 +0 -0
  397. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/badge/default-defs.j2 +0 -0
  398. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/chart/brutalist-content.j2 +0 -0
  399. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/chart.svg.j2 +0 -0
  400. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/icon/brutalist-defs.j2 +0 -0
  401. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/icon/cellular-defs.j2 +0 -0
  402. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/icon/default-content.j2 +0 -0
  403. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/icon/default-defs.j2 +0 -0
  404. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-defs.j2 +0 -0
  405. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/default-content.j2 +0 -0
  406. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/marquee-horizontal/default-defs.j2 +0 -0
  407. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/stats/brutalist-content.j2 +0 -0
  408. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/stats.svg.j2 +0 -0
  409. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/brutalist-content.j2 +0 -0
  410. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/brutalist-defs.j2 +0 -0
  411. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/cellular-defs.j2 +0 -0
  412. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/default-content.j2 +0 -0
  413. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/default-defs.j2 +0 -0
  414. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/frames/strip/default-status.j2 +0 -0
  415. {hyperweave-0.3.8 → hyperweave-0.3.10}/src/hyperweave/templates/partials/state-signal-cascade.j2 +0 -0
  416. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/__init__.py +0 -0
  417. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/conftest.py +0 -0
  418. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/fixtures/codex_session.jsonl +0 -0
  419. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/fixtures/codex_session_patches.jsonl +0 -0
  420. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/fixtures/github_contributions/synthetic.html +0 -0
  421. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/fixtures/session.json +0 -0
  422. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/fixtures/session.jsonl +0 -0
  423. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/fixtures/synthetic_session.jsonl +0 -0
  424. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/helpers.py +0 -0
  425. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_badge_brutalist_dark.py +0 -0
  426. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_badge_mode.py +0 -0
  427. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_chart_frame.py +0 -0
  428. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_chromatic_coverage_validator.py +0 -0
  429. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_chrome_variants.py +0 -0
  430. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_codex_parser.py +0 -0
  431. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_compose_bar_chart.py +0 -0
  432. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_compose_rhythm_strip.py +0 -0
  433. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_compose_treemap.py +0 -0
  434. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_compose_variant_field.py +0 -0
  435. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_connectors.py +0 -0
  436. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_core.py +0 -0
  437. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_data_tokens.py +0 -0
  438. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_divider_cellular.py +0 -0
  439. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_divider_genome_specific.py +0 -0
  440. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_doctor.py +0 -0
  441. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_font_subsetting.py +0 -0
  442. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_genome_automata.py +0 -0
  443. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_github_scrape.py +0 -0
  444. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_install_hook.py +0 -0
  445. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_kit.py +0 -0
  446. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_paradigm_dispatch.py +0 -0
  447. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_paradigm_extensibility.py +0 -0
  448. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_parse_transcript_auto.py +0 -0
  449. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_receipt_paths.py +0 -0
  450. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_resolver_rhythm.py +0 -0
  451. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_runtime_registries.py +0 -0
  452. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_serve.py +0 -0
  453. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_serve_live_state.py +0 -0
  454. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_slot_metric_state.py +0 -0
  455. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_state_inference.py +0 -0
  456. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_stats_brutalist.py +0 -0
  457. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_stats_card.py +0 -0
  458. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_strip_cellular.py +0 -0
  459. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_strip_status_toggle.py +0 -0
  460. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_telemetry.py +0 -0
  461. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_telemetry_integration.py +0 -0
  462. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_tool_class_completeness.py +0 -0
  463. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_url_stability.py +0 -0
  464. {hyperweave-0.3.8 → hyperweave-0.3.10}/tests/test_variant_default_resolution.py +0 -0
@@ -36,3 +36,7 @@ assets/cards/cards-2x2-v2.svg
36
36
  assets/cards/cards-2x2-v3.svg
37
37
  assets/cards/cards-2x2.svg
38
38
  assets/cards/halftone-card-triangle.svg
39
+ assets/demos/
40
+ scripts/analyze_audio.py
41
+ scripts/generate_demo_charts.py
42
+ scripts/render_demo_video.py
@@ -5,6 +5,66 @@ All notable changes to HyperWeave are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.3.10] - 2026-05-22
9
+
10
+ v0.3.10 finishes the layout hardening started in v0.3.9. Badges, strips, stats cards, charts, and older frame templates now place their content from measured layout values instead of template-side math. The visible result is tighter automata badges, cleaner headers, and more consistent glyph alignment.
11
+
12
+ ### Added
13
+
14
+ - **Stats and chart layout modules** — Stats cards and star charts now compute their frame, header, axis, metric, and footer positions before rendering.
15
+ - **Glyph measurement** — Provider glyphs are measured from their SVG paths and scaled by visible ink, so sparse marks like Docker no longer look smaller than dense marks like GitHub.
16
+ - **Inter font metrics** — Inter now includes generated width, bearing, and vertical-bound data for more accurate text measurement.
17
+ - **Template safeguards** — Automated checks now prevent coordinate math, hardcoded geometry, and literal colors from returning to templates.
18
+
19
+ ### Changed
20
+
21
+ - **Badges** — Automata bookends, glyphs, labels, separators, values, and trailing edges now use balanced visible spacing.
22
+ - **Glyph alignment** — Badge glyphs align to measured text centers where text uses a normal baseline, while chrome keeps its centered-baseline alignment.
23
+ - **Stats cards** — Identity text, bio text, metric slots, activity bars, language bars, and footer positions now share the same measured layout path.
24
+ - **Star charts** — Header labels, project/provider titles, axes, milestones, and chart labels now come from chart layout data instead of template constants.
25
+ - **Strips** — Strip layout is split into named groups for core content, chrome details, cellular details, status marks, and bookends.
26
+ - **Other frames** — Receipt, rhythm-strip, icon, marquee, divider, catalog, and motion-border templates now consume precomputed geometry.
27
+ - **Gradients** — Standard SVG gradient endpoints are literal SVG values again; only material-specific chrome offsets remain configurable.
28
+
29
+ ### Fixed
30
+
31
+ - **Automata stat headers** — Usernames and bio summaries keep visible breathing room.
32
+ - **Automata badges** — Compact badges no longer leave extra empty space between the cellular bookend, glyph, label, value, and right edge.
33
+ - **Badge text spacing** — Text bearings and visible ink widths now drive separator and edge spacing.
34
+ - **Chart headers** — Header labels are generated from the project and provider instead of a hardcoded `HYPERWEAVE · GITHUB` string.
35
+ - **Brutalist charts** — Prototype number labels no longer render in star charts.
36
+ - **Template colors** — Specimen colors now flow through named context values or CSS roles instead of literal template hex values.
37
+
38
+ ### Removed
39
+
40
+ - **Master-card** — The unused master-card render path was removed instead of migrated.
41
+
42
+ ## [0.3.9] - 2026-05-22
43
+
44
+ Badge, strip, stat card, and star chart frames now measure rendered content before placing text, glyphs, seams, and markers. Chrome, brutalist, and automata outputs share more consistent typography, spacing, and variant colors across frame types.
45
+
46
+ ### Fixed
47
+
48
+ - **Badges** — Missing glyph/status zones collapse, provider glyphs align to text, and long chrome status labels keep even padding.
49
+ - **Chrome frames** — Badge, strip, stat card, and chart identity slots share Orbitron typography and variant glyph color.
50
+ - **Font metrics** — Chakra Petch and Barlow Condensed now use real per-weight advance widths instead of scalar bold expansion.
51
+ - **Stats cards** — Header identity, bio text, metric slots, and language footer placement measure content before positioning.
52
+ - **Star charts** — Date labels use even calendar spacing, milestone labels avoid collisions, and chrome markers use variant color instead of fixed green.
53
+ - **Strips** — Metric cells and identity zones adapt to measured labels, values, subtitles, and glyph presence.
54
+ - **Connectors** — npm download metrics use the public stats endpoint.
55
+
56
+ ### Added
57
+
58
+ - **Font metrics** — Per-weight measurements and visible text bounds for Orbitron, JetBrains Mono, Chakra Petch, and Barlow Condensed.
59
+ - **Render checks** — Direct, HTTP, and MCP outputs are compared across the release matrix.
60
+
61
+ ### Changed
62
+
63
+ - **Automata help text** — MCP help now lists all 16 automata tones.
64
+ - **Automata badges** — Default badge output now uses the compact 20px form; explicit larger requests still use the 32px form.
65
+ - **Strip rendering** — Identity glyph, icon box, divider, and status coordinates now flow from resolver context.
66
+ - **Release tooling** — `just tag` accepts versions with or without the leading `v` and refreshes package version metadata after tagging.
67
+
8
68
  ## [0.3.8] - 2026-05-19
9
69
 
10
70
  Every artifact request now emits one greppable `HW_REQUEST` access-log line to stdout, so Fly.io's log stream reveals which GitHub repos embed HyperWeave SVGs via Camo's referer header. Health and metrics probes stay silent so 30-second checks don't drown the signal.
@@ -90,7 +150,7 @@ Receipt hero reads `token volume · $cost` with a four-cell decomposition strip
90
150
 
91
151
  - 1198 tests pass.
92
152
 
93
- ## [0.3.4] - 2026-05-13
153
+ ## [0.3.4] - 2026-05-16
94
154
 
95
155
  `install-hook` now detects Claude Code and Codex automatically. A new `hyperweave doctor` command shows hook status, transcripts, and recent receipts at a glance.
96
156
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperweave
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: Headless visual output layer for AI agents. One API call → self-contained SVG.
5
5
  Project-URL: Repository, https://github.com/InnerAura/hyperweave
6
6
  Project-URL: Issues, https://github.com/InnerAura/hyperweave/issues
@@ -57,6 +57,10 @@ Description-Content-Type: text/markdown
57
57
  </p>
58
58
 
59
59
  <!--
60
+ AI agents need to explain what they did, what they found, and what changed — HyperWeave gives them a visual language that works anywhere.
61
+
62
+ ---
63
+
60
64
  A brand agent for repos.
61
65
  Generate a cohesive visual identity layer for README, profile, status, and releases — automatically.
62
66
 
@@ -730,7 +734,7 @@ Every artifact ships with:
730
734
  | Glyphs | 99 (93 Simple Icons + 6 geometric) |
731
735
  | Divider variants | 8 &mdash; 3 genome-themed (`band` chrome, `seam` brutalist, `dissolve` automata) + 5 genome-agnostic (`block`, `current`, `takeoff`, `void`, `zeropoint`) at <code>/a/inneraura/dividers/</code> |
732
736
  | Metadata tiers | 5 (Tier 0 silent &rarr; Tier 4 reasoning) |
733
- | Bundled fonts | 3 (JetBrains Mono, Orbitron, Chakra Petch — base64-embedded) |
737
+ | Bundled fonts | 4 families / 5 weights (JetBrains Mono, Orbitron, Chakra Petch, Barlow Condensed 700/900 — base64-embedded) |
734
738
 
735
739
  Stack: Pydantic, FastAPI, FastMCP v3, Jinja2, Typer.
736
740
 
@@ -23,6 +23,10 @@
23
23
  </p>
24
24
 
25
25
  <!--
26
+ AI agents need to explain what they did, what they found, and what changed — HyperWeave gives them a visual language that works anywhere.
27
+
28
+ ---
29
+
26
30
  A brand agent for repos.
27
31
  Generate a cohesive visual identity layer for README, profile, status, and releases — automatically.
28
32
 
@@ -696,7 +700,7 @@ Every artifact ships with:
696
700
  | Glyphs | 99 (93 Simple Icons + 6 geometric) |
697
701
  | Divider variants | 8 &mdash; 3 genome-themed (`band` chrome, `seam` brutalist, `dissolve` automata) + 5 genome-agnostic (`block`, `current`, `takeoff`, `void`, `zeropoint`) at <code>/a/inneraura/dividers/</code> |
698
702
  | Metadata tiers | 5 (Tier 0 silent &rarr; Tier 4 reasoning) |
699
- | Bundled fonts | 3 (JetBrains Mono, Orbitron, Chakra Petch — base64-embedded) |
703
+ | Bundled fonts | 4 families / 5 weights (JetBrains Mono, Orbitron, Chakra Petch, Barlow Condensed 700/900 — base64-embedded) |
700
704
 
701
705
  Stack: Pydantic, FastAPI, FastMCP v3, Jinja2, Typer.
702
706
 
@@ -54,7 +54,11 @@ version-refresh:
54
54
  @uv run python -c "import hyperweave; print(f'_version.py refreshed to {hyperweave.__version__}')"
55
55
 
56
56
  tag VERSION MESSAGE:
57
- git tag -a {{VERSION}} -m "{{MESSAGE}}"
57
+ #!/usr/bin/env bash
58
+ set -euo pipefail
59
+ VER="{{VERSION}}"
60
+ [[ "$VER" == v* ]] || VER="v$VER"
61
+ git tag -a "$VER" -m "{{MESSAGE}}"
58
62
  just version-refresh
59
- @echo ""
60
- @echo "Tagged {{VERSION}}. Push with: git push --follow-tags"
63
+ echo ""
64
+ echo "Tagged $VER. Push with: git push --follow-tags"
@@ -0,0 +1,327 @@
1
+ #!/usr/bin/env python3
2
+ """Extract per-codepoint advance widths from bundled WOFF2 fonts.
3
+
4
+ HyperWeave bundles fonts as base64-encoded WOFF2 in
5
+ ``src/hyperweave/data/fonts/*.b64`` (so the whole font registry ships
6
+ as plain-text files, diffable in git). This script decodes each font,
7
+ reads its ``hmtx`` table via ``fontTools``, and emits a JSON file at
8
+ ``src/hyperweave/data/font-metrics/{slug}.json`` matching the existing
9
+ ``inter.json`` schema:
10
+
11
+ {
12
+ "font_family": "Orbitron",
13
+ "baseline_size_px": 20,
14
+ "units": "tenths_of_pixels",
15
+ "bold_expansion_factor": 1.0,
16
+ "fallback_width": 110,
17
+ "widths": { " ": 78, "A": 145, ... }
18
+ }
19
+
20
+ The baseline size is chosen close to the font's dominant rendered size
21
+ in HyperWeave (20px for Orbitron in stats hero values, 11px for
22
+ Inter in badge labels). Widths are stored in tenths-of-pixels at the
23
+ baseline size, so a glyph of 145 tenths at baseline 20px renders as
24
+ 14.5px wide at 20px and ~7.25px wide at 10px (linear scaling).
25
+
26
+ Usage:
27
+ uv run python scripts/extract_font_metrics.py orbitron --baseline 20
28
+ uv run python scripts/extract_font_metrics.py jetbrains-mono --baseline 11
29
+ uv run python scripts/extract_font_metrics.py --all
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ import argparse
35
+ import base64
36
+ import json
37
+ import sys
38
+ from io import BytesIO
39
+ from pathlib import Path
40
+
41
+ from fontTools.pens.boundsPen import BoundsPen
42
+ from fontTools.ttLib import TTFont
43
+ from fontTools.varLib.instancer import instantiateVariableFont
44
+
45
+ ROOT = Path(__file__).resolve().parent.parent
46
+ FONTS_DIR = ROOT / "src" / "hyperweave" / "data" / "fonts"
47
+ METRICS_DIR = ROOT / "src" / "hyperweave" / "data" / "font-metrics"
48
+
49
+ # ASCII printable characters we shipped in inter.json (space through ~).
50
+ SUPPORTED_ASCII = [chr(c) for c in range(0x20, 0x7F)]
51
+
52
+
53
+ def load_font_from_b64(path: Path) -> TTFont:
54
+ """Decode a base64-encoded WOFF2 payload and return a TTFont."""
55
+ raw_b64 = path.read_text()
56
+ return TTFont(BytesIO(base64.b64decode(raw_b64)))
57
+
58
+
59
+ def extract_widths_and_bearings(
60
+ font: TTFont, baseline_size_px: int
61
+ ) -> tuple[dict[str, int], dict[str, list[int]], dict[str, list[int]]]:
62
+ """Return per-char (advance_widths, ink_bearings, vertical_bounds).
63
+
64
+ Advance widths follow the original schema — tenths-of-pixels at
65
+ ``baseline_size_px``. Ink bearings are returned as
66
+ ``{char: [lsb_tenths, rsb_tenths]}`` where:
67
+
68
+ * ``lsb`` is the distance from the glyph's origin to the leftmost
69
+ visible ink (left side bearing in the OpenType sense)
70
+ * ``rsb`` is the distance from the rightmost visible ink to the
71
+ advance width (right side bearing)
72
+
73
+ These let the text-measurement layer compute *visible-ink width* as
74
+ ``advance - first_char.lsb - last_char.rsb`` — the corrected width
75
+ that places downstream cursor work (badge seam placement, stat card
76
+ bio_x derivation) at the actual visible end of text, not at the
77
+ advance position which includes invisible trailing side-bearing.
78
+
79
+ Whitespace glyphs (no ink) return ``[0, advance]`` so subtracting
80
+ them produces zero visible width — correct behavior for an
81
+ all-whitespace string.
82
+ """
83
+ cmap = font.getBestCmap()
84
+ hmtx = font["hmtx"]
85
+ glyph_set = font.getGlyphSet()
86
+ units_per_em = font["head"].unitsPerEm
87
+ scale = baseline_size_px / units_per_em
88
+ widths: dict[str, int] = {}
89
+ bearings: dict[str, list[int]] = {}
90
+ vertical_bounds: dict[str, list[int]] = {}
91
+ for ch in SUPPORTED_ASCII:
92
+ codepoint = ord(ch)
93
+ if codepoint not in cmap:
94
+ continue
95
+ glyph_name = cmap[codepoint]
96
+ advance_design_units, _lsb_design = hmtx[glyph_name]
97
+ widths[ch] = round(advance_design_units * scale * 10)
98
+
99
+ # Compute visible-ink bounds via BoundsPen. Whitespace glyphs draw
100
+ # nothing; pen.bounds is None — treat as "no visible ink" so the
101
+ # entire advance is left+right bearing (rsb consumes the advance).
102
+ pen = BoundsPen(glyph_set)
103
+ try:
104
+ glyph_set[glyph_name].draw(pen)
105
+ except Exception:
106
+ # Defensive: a malformed glyph shouldn't crash the extraction.
107
+ bearings[ch] = [0, widths[ch]]
108
+ vertical_bounds[ch] = [0, 0]
109
+ continue
110
+ if pen.bounds is None:
111
+ bearings[ch] = [0, widths[ch]]
112
+ vertical_bounds[ch] = [0, 0]
113
+ continue
114
+ xmin, _ymin, xmax, _ymax = pen.bounds
115
+ lsb_px_at_baseline = xmin * scale # ink-left from glyph origin
116
+ rsb_px_at_baseline = (advance_design_units - xmax) * scale # advance - ink-right
117
+ bearings[ch] = [round(lsb_px_at_baseline * 10), round(rsb_px_at_baseline * 10)]
118
+ vertical_bounds[ch] = [round(_ymin * scale * 10), round(_ymax * scale * 10)]
119
+ return widths, bearings, vertical_bounds
120
+
121
+
122
+ def compute_fallback_width(widths: dict[str, int]) -> int:
123
+ """Median-ish fallback width for codepoints outside the supported set."""
124
+ if not widths:
125
+ return 60
126
+ sorted_widths = sorted(widths.values())
127
+ return sorted_widths[len(sorted_widths) // 2]
128
+
129
+
130
+ def emit_metrics_json(
131
+ family: str,
132
+ baseline_size_px: int,
133
+ widths: dict[str, int],
134
+ bold_expansion_factor: float,
135
+ aliases: list[str],
136
+ is_monospace: bool = False,
137
+ char_width_px: float = 0.0,
138
+ bearings: dict[str, list[int]] | None = None,
139
+ vertical_bounds: dict[str, list[int]] | None = None,
140
+ widths_by_weight: dict[str, dict[str, int]] | None = None,
141
+ bearings_by_weight: dict[str, dict[str, list[int]]] | None = None,
142
+ vertical_bounds_by_weight: dict[str, dict[str, list[int]]] | None = None,
143
+ ) -> dict[str, object]:
144
+ """Build the JSON dict matching inter.json schema (plus registry fields).
145
+
146
+ ``bearings`` is a v0.3.9 addition for per-glyph ink-width measurement
147
+ (used by ``measure_text_ink_width`` in core/text.py). Optional —
148
+ loaders that predate the field fall back to advance-width behavior.
149
+ """
150
+ result: dict[str, object] = {
151
+ "font_family": family,
152
+ "baseline_size_px": baseline_size_px,
153
+ "units": "tenths_of_pixels",
154
+ "bold_expansion_factor": bold_expansion_factor,
155
+ "fallback_width": compute_fallback_width(widths),
156
+ "aliases": aliases,
157
+ "is_monospace": is_monospace,
158
+ "char_width_px": char_width_px,
159
+ "widths": widths,
160
+ }
161
+ if bearings:
162
+ result["bearings"] = bearings
163
+ if vertical_bounds:
164
+ result["vertical_bounds"] = vertical_bounds
165
+ if widths_by_weight:
166
+ result["widths_by_weight"] = widths_by_weight
167
+ if bearings_by_weight:
168
+ result["bearings_by_weight"] = bearings_by_weight
169
+ if vertical_bounds_by_weight:
170
+ result["vertical_bounds_by_weight"] = vertical_bounds_by_weight
171
+ return result
172
+
173
+
174
+ # Known font configs. Add entries here to extend.
175
+ FONT_CONFIGS: dict[str, dict[str, object]] = {
176
+ "inter": {
177
+ "family": "Inter",
178
+ "baseline_size_px": 11,
179
+ "bold_expansion_factor": 1.0,
180
+ "aliases": ["inter", "system-ui", "sans-serif", "-apple-system", "blinkmacsystemfont", "segoe ui"],
181
+ "is_monospace": False,
182
+ "char_width_px": 0.0,
183
+ "metric_weights": [400, 700, 800, 900],
184
+ },
185
+ "orbitron": {
186
+ "family": "Orbitron",
187
+ "baseline_size_px": 20,
188
+ "bold_expansion_factor": 1.0,
189
+ "aliases": ["orbitron"],
190
+ "is_monospace": False,
191
+ "char_width_px": 0.0,
192
+ "metric_weights": [400, 700, 800, 900],
193
+ },
194
+ "jetbrains-mono": {
195
+ "family": "JetBrains Mono",
196
+ "baseline_size_px": 11,
197
+ "bold_expansion_factor": 1.0, # true monospace — no bold width change
198
+ "aliases": ["jetbrains mono", "jetbrains-mono", "sf mono", "menlo", "monospace"],
199
+ "is_monospace": True,
200
+ # char_width_px populated below from extracted widths (median).
201
+ "char_width_px": 0.0,
202
+ },
203
+ "chakra-petch": {
204
+ "family": "Chakra Petch",
205
+ "baseline_size_px": 12, # dominant rendered size in automata badge value text
206
+ "bold_expansion_factor": 1.0,
207
+ "aliases": ["chakra petch", "chakra-petch"],
208
+ "is_monospace": False,
209
+ "char_width_px": 0.0,
210
+ "metric_weights": [400, 700, 900],
211
+ "metric_weight_sources": {
212
+ "400": "chakra-petch",
213
+ "700": "chakra-petch",
214
+ "900": "chakra-petch",
215
+ },
216
+ },
217
+ "barlow-condensed-900": {
218
+ "family": "Barlow Condensed",
219
+ "baseline_size_px": 18, # dominant rendered size in brutalist strip value text
220
+ "bold_expansion_factor": 1.0, # 900 is the heaviest weight shipped; no further expansion
221
+ "aliases": ["barlow condensed", "barlow-condensed", "barlow condensed 900"],
222
+ "is_monospace": False,
223
+ "char_width_px": 0.0,
224
+ "metric_weights": [400, 700, 900],
225
+ "metric_weight_sources": {
226
+ "400": "barlow-condensed-700",
227
+ "700": "barlow-condensed-700",
228
+ "900": "barlow-condensed-900",
229
+ },
230
+ },
231
+ }
232
+
233
+
234
+ def load_metric_font_for_weight(slug: str, base_font: TTFont, config: dict[str, object], weight_int: int) -> TTFont:
235
+ """Return the font face used to extract metrics for ``weight_int``.
236
+
237
+ Variable fonts are instantiated by axis value. Static families can declare
238
+ ``metric_weight_sources`` to map weights to bundled font slugs.
239
+ """
240
+ weight_sources = config.get("metric_weight_sources")
241
+ if isinstance(weight_sources, dict):
242
+ source_slug = str(weight_sources.get(str(weight_int), slug))
243
+ source_path = FONTS_DIR / f"{source_slug}.b64"
244
+ if not source_path.exists():
245
+ raise FileNotFoundError(f"Missing font source for weight {weight_int}: {source_path}")
246
+ return load_font_from_b64(source_path)
247
+ if "fvar" in base_font:
248
+ return instantiateVariableFont(base_font, {"wght": weight_int}, inplace=False)
249
+ return base_font
250
+
251
+
252
+ def extract_one(slug: str) -> Path:
253
+ """Extract one font to ``data/font-metrics/{slug}.json``."""
254
+ if slug not in FONT_CONFIGS:
255
+ raise ValueError(f"Unknown font slug '{slug}'. Known: {sorted(FONT_CONFIGS)}")
256
+ config = FONT_CONFIGS[slug]
257
+ b64_path = FONTS_DIR / f"{slug}.b64"
258
+ if not b64_path.exists():
259
+ raise FileNotFoundError(f"Missing font source: {b64_path}")
260
+
261
+ font = load_font_from_b64(b64_path)
262
+ baseline = int(config["baseline_size_px"])
263
+ widths, bearings, vertical_bounds = extract_widths_and_bearings(font, baseline)
264
+ widths_by_weight: dict[str, dict[str, int]] = {}
265
+ bearings_by_weight: dict[str, dict[str, list[int]]] = {}
266
+ vertical_bounds_by_weight: dict[str, dict[str, list[int]]] = {}
267
+ metric_weights = config.get("metric_weights")
268
+ if isinstance(metric_weights, list):
269
+ for weight in metric_weights:
270
+ weight_int = int(weight)
271
+ weight_font = load_metric_font_for_weight(slug, font, config, weight_int)
272
+ weight_widths, weight_bearings, weight_vertical_bounds = extract_widths_and_bearings(weight_font, baseline)
273
+ key = str(weight_int)
274
+ widths_by_weight[key] = weight_widths
275
+ bearings_by_weight[key] = weight_bearings
276
+ vertical_bounds_by_weight[key] = weight_vertical_bounds
277
+
278
+ char_width_px = float(config["char_width_px"])
279
+ is_mono = bool(config["is_monospace"])
280
+ if is_mono and char_width_px == 0.0 and widths:
281
+ # Monospace: all chars have the same advance; pick the first mapped width.
282
+ advance_tenths = next(iter(widths.values()))
283
+ char_width_px = advance_tenths / 10.0
284
+
285
+ data = emit_metrics_json(
286
+ family=str(config["family"]),
287
+ baseline_size_px=baseline,
288
+ widths=widths,
289
+ bold_expansion_factor=float(config["bold_expansion_factor"]),
290
+ aliases=list(config["aliases"]), # type: ignore[arg-type]
291
+ is_monospace=is_mono,
292
+ char_width_px=char_width_px,
293
+ bearings=bearings,
294
+ vertical_bounds=vertical_bounds,
295
+ widths_by_weight=widths_by_weight,
296
+ bearings_by_weight=bearings_by_weight,
297
+ vertical_bounds_by_weight=vertical_bounds_by_weight,
298
+ )
299
+
300
+ out_path = METRICS_DIR / f"{slug}.json"
301
+ METRICS_DIR.mkdir(parents=True, exist_ok=True)
302
+ out_path.write_text(json.dumps(data, indent=2, ensure_ascii=False) + "\n")
303
+ return out_path
304
+
305
+
306
+ def main() -> int:
307
+ parser = argparse.ArgumentParser(description=__doc__)
308
+ parser.add_argument("slugs", nargs="*", help="Font slugs to extract (e.g. orbitron jetbrains-mono).")
309
+ parser.add_argument("--all", action="store_true", help="Extract every font in FONT_CONFIGS.")
310
+ args = parser.parse_args()
311
+
312
+ if args.all:
313
+ slugs = sorted(FONT_CONFIGS.keys())
314
+ elif args.slugs:
315
+ slugs = args.slugs
316
+ else:
317
+ parser.print_help()
318
+ return 1
319
+
320
+ for slug in slugs:
321
+ out = extract_one(slug)
322
+ sys.stdout.write(f" wrote {out.relative_to(ROOT)}\n")
323
+ return 0
324
+
325
+
326
+ if __name__ == "__main__":
327
+ sys.exit(main())