hyperweave 0.3.2__tar.gz → 0.3.4__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 (426) hide show
  1. {hyperweave-0.3.2 → hyperweave-0.3.4}/CHANGELOG.md +38 -0
  2. {hyperweave-0.3.2 → hyperweave-0.3.4}/PKG-INFO +3 -3
  3. {hyperweave-0.3.2 → hyperweave-0.3.4}/README.md +2 -2
  4. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/_version.py +2 -2
  5. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/cli.py +266 -46
  6. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/layout.py +72 -27
  7. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/resolver.py +81 -16
  8. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/models.py +11 -0
  9. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/paradigm.py +41 -0
  10. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/genomes/brutalist.json +36 -18
  11. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/paradigms/brutalist.yaml +24 -0
  12. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/render/chart_engine.py +7 -1
  13. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/receipt_paths.py +23 -13
  14. hyperweave-0.3.4/src/hyperweave/templates/components/chart-milestone-brutalist.svg.j2 +37 -0
  15. hyperweave-0.3.4/src/hyperweave/templates/frames/badge/brutalist-dark-content.j2 +95 -0
  16. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart/brutalist-dark-content.j2 +15 -7
  17. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart/brutalist-defs.j2 +91 -9
  18. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart/brutalist-light-content.j2 +17 -7
  19. hyperweave-0.3.4/src/hyperweave/templates/frames/divider/brutalist-seam.svg.j2 +49 -0
  20. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/divider.svg.j2 +22 -10
  21. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats/brutalist-light-content.j2 +12 -3
  22. hyperweave-0.3.4/tests/test_badge_brutalist_dark.py +343 -0
  23. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_chart_engine.py +7 -3
  24. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_chromatic_coverage_validator.py +29 -8
  25. hyperweave-0.3.4/tests/test_divider_genome_specific.py +244 -0
  26. hyperweave-0.3.4/tests/test_doctor.py +208 -0
  27. hyperweave-0.3.4/tests/test_install_hook.py +233 -0
  28. hyperweave-0.3.4/tests/test_receipt_paths.py +165 -0
  29. hyperweave-0.3.4/tests/test_stats_brutalist.py +125 -0
  30. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_telemetry_integration.py +76 -12
  31. hyperweave-0.3.2/src/hyperweave/templates/frames/badge/brutalist-dark-content.j2 +0 -55
  32. hyperweave-0.3.2/src/hyperweave/templates/frames/divider/brutalist-seam.svg.j2 +0 -39
  33. hyperweave-0.3.2/tests/test_divider_genome_specific.py +0 -93
  34. hyperweave-0.3.2/tests/test_receipt_paths.py +0 -129
  35. {hyperweave-0.3.2 → hyperweave-0.3.4}/.dockerignore +0 -0
  36. {hyperweave-0.3.2 → hyperweave-0.3.4}/.github/workflows/ci.yml +0 -0
  37. {hyperweave-0.3.2 → hyperweave-0.3.4}/.github/workflows/deploy.yml +0 -0
  38. {hyperweave-0.3.2 → hyperweave-0.3.4}/.github/workflows/publish.yml +0 -0
  39. {hyperweave-0.3.2 → hyperweave-0.3.4}/.gitignore +0 -0
  40. {hyperweave-0.3.2 → hyperweave-0.3.4}/.pre-commit-config.yaml +0 -0
  41. {hyperweave-0.3.2 → hyperweave-0.3.4}/Dockerfile +0 -0
  42. {hyperweave-0.3.2 → hyperweave-0.3.4}/LICENSE +0 -0
  43. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/buttons/button-liquid.svg +0 -0
  44. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/cards/card-butterfly.svg +0 -0
  45. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/cards/card-python.svg +0 -0
  46. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/cards/card-sunflower.svg +0 -0
  47. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/cards/card-waves.svg +0 -0
  48. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/badge_critical.svg +0 -0
  49. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/badge_passing.svg +0 -0
  50. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/badge_warning.svg +0 -0
  51. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/banner.svg +0 -0
  52. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/icons/discord.svg +0 -0
  53. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/icons/notion.svg +0 -0
  54. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/icons/reddit.svg +0 -0
  55. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/icons/spotify.svg +0 -0
  56. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/icons/youtube.svg +0 -0
  57. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/marquee_counter.svg +0 -0
  58. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/marquee_horizontal.svg +0 -0
  59. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/marquee_vertical.svg +0 -0
  60. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/profile-cards/chart_stars_full.svg +0 -0
  61. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/profile-cards/stats.svg +0 -0
  62. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/brutalist-emerald/strip.svg +0 -0
  63. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/badge_critical.svg +0 -0
  64. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/badge_passing.svg +0 -0
  65. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/badge_warning.svg +0 -0
  66. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/banner.svg +0 -0
  67. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/icons/bluesky.svg +0 -0
  68. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/icons/github.svg +0 -0
  69. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/icons/instagram.svg +0 -0
  70. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/icons/mastodon.svg +0 -0
  71. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/icons/x.svg +0 -0
  72. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/marquee_counter.svg +0 -0
  73. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/marquee_horizontal.svg +0 -0
  74. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/marquee_vertical.svg +0 -0
  75. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/profile-cards/chart_stars_full.svg +0 -0
  76. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/profile-cards/stats.svg +0 -0
  77. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/chrome-horizon/strip.svg +0 -0
  78. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/telemetry/master_card.svg +0 -0
  79. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/telemetry/receipt.svg +0 -0
  80. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/telemetry/receipt_claude-code_medium.svg +0 -0
  81. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/telemetry/receipt_codex_large.svg +0 -0
  82. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/telemetry/receipt_voltage_xlarge.svg +0 -0
  83. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/telemetry/rhythm_strip.svg +0 -0
  84. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/examples/telemetry/rhythm_strip_voltage_xlarge.svg +0 -0
  85. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/footers/inneraura-footer-liquid.svg +0 -0
  86. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/footers/inneraura-footer-purple.svg +0 -0
  87. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/footers/inneraura-footer.svg +0 -0
  88. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/hyperweave-banner.svg +0 -0
  89. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/icons/cobalt-sapphire-discord.svg +0 -0
  90. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/icons/cobalt-sapphire-docs.svg +0 -0
  91. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/icons/cobalt-sapphire-github.svg +0 -0
  92. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/icons/cobalt-sapphire-instagram.svg +0 -0
  93. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/icons/cobalt-sapphire-linkedin.svg +0 -0
  94. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/icons/cobalt-sapphire-tiktok.svg +0 -0
  95. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/icons/cobalt-sapphire-x.svg +0 -0
  96. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/icons/cobalt-sapphire-youtube.svg +0 -0
  97. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/marquees/badge-showcase-triple.svg +0 -0
  98. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/marquees/genome-marquee-triple.svg +0 -0
  99. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/marquees/sample-badges.svg +0 -0
  100. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/404.svg +0 -0
  101. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/callout-icons.svg +0 -0
  102. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/divider.svg +0 -0
  103. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/favicon.svg +0 -0
  104. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/hero-banner.svg +0 -0
  105. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/hyperweave-banner-v2.svg +0 -0
  106. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/hyperweave-navbar-logo.svg +0 -0
  107. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/loader.svg +0 -0
  108. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/mintlify-assets/og-image.svg +0 -0
  109. {hyperweave-0.3.2 → hyperweave-0.3.4}/assets/timelines/hyperweave-roadmap.svg +0 -0
  110. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/assets/favicon.svg +0 -0
  111. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/assets/hyperweave-banner.svg +0 -0
  112. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/assets/hyperweave-navbar-logo.svg +0 -0
  113. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/assets/og-image.svg +0 -0
  114. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/explanation/architecture.mdx +0 -0
  115. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/explanation/camo-compatibility.mdx +0 -0
  116. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/explanation/cim-compliance.mdx +0 -0
  117. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/explanation/genome-profile-system.mdx +0 -0
  118. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/explanation/metadata-tiers.mdx +0 -0
  119. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/how-to/add-motion-to-badges.mdx +0 -0
  120. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/how-to/create-session-receipts.mdx +0 -0
  121. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/how-to/set-up-claude-code-hooks.mdx +0 -0
  122. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/how-to/use-live-data-badges.mdx +0 -0
  123. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/introduction.mdx +0 -0
  124. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/mint.json +0 -0
  125. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/quickstart.mdx +0 -0
  126. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/reference/cli.mdx +0 -0
  127. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/reference/compose-spec.mdx +0 -0
  128. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/reference/genomes.mdx +0 -0
  129. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/reference/http-api.mdx +0 -0
  130. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/reference/mcp-tools.mdx +0 -0
  131. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/reference/motions.mdx +0 -0
  132. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/reference/telemetry-contract.mdx +0 -0
  133. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/spec/hyperweave-protocol.mdx +0 -0
  134. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/tutorials/build-an-artifact-kit.mdx +0 -0
  135. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/tutorials/compose-your-first-badge.mdx +0 -0
  136. {hyperweave-0.3.2 → hyperweave-0.3.4}/docs/tutorials/install-session-telemetry.mdx +0 -0
  137. {hyperweave-0.3.2 → hyperweave-0.3.4}/fly.toml +0 -0
  138. {hyperweave-0.3.2 → hyperweave-0.3.4}/hooks/install.py +0 -0
  139. {hyperweave-0.3.2 → hyperweave-0.3.4}/hooks/session_end.sh +0 -0
  140. {hyperweave-0.3.2 → hyperweave-0.3.4}/justfile +0 -0
  141. {hyperweave-0.3.2 → hyperweave-0.3.4}/pyproject.toml +0 -0
  142. {hyperweave-0.3.2 → hyperweave-0.3.4}/scripts/extract_font_metrics.py +0 -0
  143. {hyperweave-0.3.2 → hyperweave-0.3.4}/scripts/extract_glyphs.py +0 -0
  144. {hyperweave-0.3.2 → hyperweave-0.3.4}/scripts/generate_proofset.py +0 -0
  145. {hyperweave-0.3.2 → hyperweave-0.3.4}/scripts/probe_live_stats.py +0 -0
  146. {hyperweave-0.3.2 → hyperweave-0.3.4}/scripts/probe_star_history.py +0 -0
  147. {hyperweave-0.3.2 → hyperweave-0.3.4}/scripts/stress_test.py +0 -0
  148. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/__init__.py +0 -0
  149. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/__main__.py +0 -0
  150. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/__init__.py +0 -0
  151. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/assembler.py +0 -0
  152. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/bar_chart.py +0 -0
  153. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/context.py +0 -0
  154. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/engine.py +0 -0
  155. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/lanes.py +0 -0
  156. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/palette.py +0 -0
  157. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/reasoning.py +0 -0
  158. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/resolvers/__init__.py +0 -0
  159. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/resolvers/chart.py +0 -0
  160. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/resolvers/stats.py +0 -0
  161. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/rhythm.py +0 -0
  162. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/rhythm_strip.py +0 -0
  163. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/treemap.py +0 -0
  164. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/compose/validate_paradigms.py +0 -0
  165. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/config/__init__.py +0 -0
  166. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/config/genome_validator.py +0 -0
  167. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/config/loader.py +0 -0
  168. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/config/registry.py +0 -0
  169. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/config/settings.py +0 -0
  170. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/connectors/__init__.py +0 -0
  171. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/connectors/arxiv.py +0 -0
  172. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/connectors/base.py +0 -0
  173. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/connectors/cache.py +0 -0
  174. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/connectors/github.py +0 -0
  175. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/connectors/rest.py +0 -0
  176. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/__init__.py +0 -0
  177. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/cell_layout.py +0 -0
  178. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/color.py +0 -0
  179. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/contracts.py +0 -0
  180. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/enums.py +0 -0
  181. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/font_metrics.py +0 -0
  182. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/schema.py +0 -0
  183. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/state.py +0 -0
  184. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/text.py +0 -0
  185. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/core/thresholds.py +0 -0
  186. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/badge_modes.yaml +0 -0
  187. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/css/accessibility.css +0 -0
  188. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/css/bridge.css +0 -0
  189. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/css/expression.css +0 -0
  190. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/css/status.css +0 -0
  191. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/font-metrics/chakra-petch.json +0 -0
  192. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/font-metrics/inter.json +0 -0
  193. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/font-metrics/jetbrains-mono.json +0 -0
  194. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/font-metrics/orbitron.json +0 -0
  195. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/barlow-condensed-700.b64 +0 -0
  196. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/barlow-condensed-700.meta.json +0 -0
  197. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/barlow-condensed-900.b64 +0 -0
  198. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/barlow-condensed-900.meta.json +0 -0
  199. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/chakra-petch.b64 +0 -0
  200. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/chakra-petch.meta.json +0 -0
  201. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/jetbrains-mono.b64 +0 -0
  202. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/jetbrains-mono.meta.json +0 -0
  203. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/orbitron.b64 +0 -0
  204. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/fonts/orbitron.meta.json +0 -0
  205. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/genomes/automata.json +0 -0
  206. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/genomes/chrome.json +0 -0
  207. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/genomes/telemetry-claude-code.json +0 -0
  208. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/genomes/telemetry-codex.json +0 -0
  209. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/genomes/telemetry-cream.json +0 -0
  210. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/genomes/telemetry-voltage.json +0 -0
  211. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/glyphs.json +0 -0
  212. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/motions/border/chromatic-pulse.yaml +0 -0
  213. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/motions/border/corner-trace.yaml +0 -0
  214. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/motions/border/dual-orbit.yaml +0 -0
  215. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/motions/border/entanglement.yaml +0 -0
  216. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/motions/border/rimrun.yaml +0 -0
  217. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/motions/static.yaml +0 -0
  218. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/paradigms/cellular.yaml +0 -0
  219. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/paradigms/chrome.yaml +0 -0
  220. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/paradigms/default.yaml +0 -0
  221. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/policies/normal.json +0 -0
  222. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/policies/permissive.json +0 -0
  223. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/policies/ungoverned.json +0 -0
  224. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/profiles/brutalist.contract.json +0 -0
  225. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/profiles/brutalist.yaml +0 -0
  226. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/profiles/chrome.contract.json +0 -0
  227. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/profiles/chrome.yaml +0 -0
  228. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/reasoning/__init__.py +0 -0
  229. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/reasoning/brutalist.yaml +0 -0
  230. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/specimens.yaml +0 -0
  231. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/telemetry/model-pricing.yaml +0 -0
  232. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/telemetry/runtimes/claude-code.yaml +0 -0
  233. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/telemetry/runtimes/codex.yaml +0 -0
  234. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/telemetry/stage-config.yaml +0 -0
  235. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/telemetry/stage-labels.yaml +0 -0
  236. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/telemetry/tool-colors.yaml +0 -0
  237. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/arrow.json +0 -0
  238. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/aurora.json +0 -0
  239. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/beacon.json +0 -0
  240. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/bracket3d.json +0 -0
  241. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/chevron.json +0 -0
  242. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/crosshair.json +0 -0
  243. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/diamond.json +0 -0
  244. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/rocket.json +0 -0
  245. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/rules/bar.json +0 -0
  246. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/rules/dashed.json +0 -0
  247. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/rules/five-wave.json +0 -0
  248. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/rules/spectral.json +0 -0
  249. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/rules/straight.json +0 -0
  250. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/rules/wave.json +0 -0
  251. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/data/terminals/stijl.json +0 -0
  252. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/kit.py +0 -0
  253. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/mcp/__init__.py +0 -0
  254. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/mcp/__main__.py +0 -0
  255. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/mcp/server.py +0 -0
  256. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/py.typed +0 -0
  257. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/render/__init__.py +0 -0
  258. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/render/fonts.py +0 -0
  259. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/render/glyphs.py +0 -0
  260. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/render/motion.py +0 -0
  261. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/render/templates.py +0 -0
  262. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/serve/__init__.py +0 -0
  263. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/serve/app.py +0 -0
  264. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/serve/data_tokens.py +0 -0
  265. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/__init__.py +0 -0
  266. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/capture.py +0 -0
  267. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/codex_parser.py +0 -0
  268. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/contract.py +0 -0
  269. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/corrections.py +0 -0
  270. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/cost.py +0 -0
  271. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/models.py +0 -0
  272. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/parser.py +0 -0
  273. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/runtimes.py +0 -0
  274. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/telemetry/stages.py +0 -0
  275. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-area.svg.j2 +0 -0
  276. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-axes.svg.j2 +0 -0
  277. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-empty-state.svg.j2 +0 -0
  278. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-gridlines.svg.j2 +0 -0
  279. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-markers/circle.svg.j2 +0 -0
  280. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-markers/diamond.svg.j2 +0 -0
  281. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-markers/endpoint-diamond.svg.j2 +0 -0
  282. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-markers/endpoint-rect.svg.j2 +0 -0
  283. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-markers/rect.svg.j2 +0 -0
  284. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-milestone.svg.j2 +0 -0
  285. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/chart-polyline.svg.j2 +0 -0
  286. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/filter.svg.j2 +0 -0
  287. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/glyph-inline.svg.j2 +0 -0
  288. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/glyph.svg.j2 +0 -0
  289. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/gradient.svg.j2 +0 -0
  290. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/metadata.svg.j2 +0 -0
  291. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/metric.svg.j2 +0 -0
  292. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/phase-segment.svg.j2 +0 -0
  293. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/rule.svg.j2 +0 -0
  294. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/status.svg.j2 +0 -0
  295. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/components/terminal.svg.j2 +0 -0
  296. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/document.svg.j2 +0 -0
  297. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/error-badge.svg.j2 +0 -0
  298. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/brutalist-content.j2 +0 -0
  299. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/brutalist-defs.j2 +0 -0
  300. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/brutalist-light-content.j2 +0 -0
  301. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/cellular-content.j2 +0 -0
  302. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/cellular-defs.j2 +0 -0
  303. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/chrome-content.j2 +0 -0
  304. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/chrome-defs.j2 +0 -0
  305. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/default-content.j2 +0 -0
  306. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge/default-defs.j2 +0 -0
  307. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/badge.svg.j2 +0 -0
  308. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/catalog.svg.j2 +0 -0
  309. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart/brutalist-content.j2 +0 -0
  310. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart/cellular-content.j2 +0 -0
  311. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart/cellular-defs.j2 +0 -0
  312. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart/chrome-content.j2 +0 -0
  313. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart/chrome-defs.j2 +0 -0
  314. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/chart.svg.j2 +0 -0
  315. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/divider/chrome-band.svg.j2 +0 -0
  316. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon/brutalist-content.j2 +0 -0
  317. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon/brutalist-defs.j2 +0 -0
  318. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon/cellular-content.j2 +0 -0
  319. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon/cellular-defs.j2 +0 -0
  320. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon/chrome-content.j2 +0 -0
  321. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon/chrome-defs.j2 +0 -0
  322. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon/default-content.j2 +0 -0
  323. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon/default-defs.j2 +0 -0
  324. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/icon.svg.j2 +0 -0
  325. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-content.j2 +0 -0
  326. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-defs.j2 +0 -0
  327. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-overlay.j2 +0 -0
  328. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/cellular-content.j2 +0 -0
  329. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/cellular-defs.j2 +0 -0
  330. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/cellular-overlay.j2 +0 -0
  331. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/chrome-content.j2 +0 -0
  332. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/chrome-defs.j2 +0 -0
  333. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/chrome-overlay.j2 +0 -0
  334. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/default-content.j2 +0 -0
  335. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal/default-defs.j2 +0 -0
  336. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/marquee-horizontal.svg.j2 +0 -0
  337. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/master-card.svg.j2 +0 -0
  338. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/receipt.svg.j2 +0 -0
  339. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/rhythm-strip.svg.j2 +0 -0
  340. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats/brutalist-content.j2 +0 -0
  341. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats/brutalist-dark-content.j2 +0 -0
  342. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats/brutalist-defs.j2 +0 -0
  343. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats/cellular-content.j2 +0 -0
  344. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats/cellular-defs.j2 +0 -0
  345. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats/chrome-content.j2 +0 -0
  346. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats/chrome-defs.j2 +0 -0
  347. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/stats.svg.j2 +0 -0
  348. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/brutalist-content.j2 +0 -0
  349. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/brutalist-dark-content.j2 +0 -0
  350. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/brutalist-defs.j2 +0 -0
  351. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/brutalist-light-content.j2 +0 -0
  352. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/brutalist-status.j2 +0 -0
  353. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/cellular-content.j2 +0 -0
  354. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/cellular-defs.j2 +0 -0
  355. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/cellular-status.j2 +0 -0
  356. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/chrome-content.j2 +0 -0
  357. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/chrome-defs.j2 +0 -0
  358. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/chrome-status.j2 +0 -0
  359. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/default-content.j2 +0 -0
  360. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/default-defs.j2 +0 -0
  361. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip/default-status.j2 +0 -0
  362. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/frames/strip.svg.j2 +0 -0
  363. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/motions/border/chromatic-pulse.svg.j2 +0 -0
  364. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/motions/border/corner-trace.svg.j2 +0 -0
  365. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/motions/border/dual-orbit.svg.j2 +0 -0
  366. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/motions/border/entanglement.svg.j2 +0 -0
  367. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/motions/border/rimrun.svg.j2 +0 -0
  368. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/partials/provider-glyphs.svg.j2 +0 -0
  369. {hyperweave-0.3.2 → hyperweave-0.3.4}/src/hyperweave/templates/partials/state-signal-cascade.j2 +0 -0
  370. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/__init__.py +0 -0
  371. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/conftest.py +0 -0
  372. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/fixtures/codex_session.jsonl +0 -0
  373. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/fixtures/codex_session_patches.jsonl +0 -0
  374. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/fixtures/github_contributions/synthetic.html +0 -0
  375. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/fixtures/session.json +0 -0
  376. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/fixtures/session.jsonl +0 -0
  377. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/fixtures/synthetic_session.jsonl +0 -0
  378. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/helpers.py +0 -0
  379. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/snapshots/url_stability/divider_band_chrome_static.svg +0 -0
  380. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/snapshots/url_stability/icon_github_chrome_static.svg +0 -0
  381. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_assembler.py +0 -0
  382. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_badge_cellular.py +0 -0
  383. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_badge_layout.py +0 -0
  384. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_badge_mode.py +0 -0
  385. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_chart_frame.py +0 -0
  386. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_chrome_variants.py +0 -0
  387. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_codex_parser.py +0 -0
  388. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_compose_bar_chart.py +0 -0
  389. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_compose_rhythm_strip.py +0 -0
  390. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_compose_treemap.py +0 -0
  391. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_compose_variant_field.py +0 -0
  392. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_connectors.py +0 -0
  393. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_core.py +0 -0
  394. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_data_tokens.py +0 -0
  395. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_divider_cellular.py +0 -0
  396. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_font_gating.py +0 -0
  397. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_font_metrics_chakra.py +0 -0
  398. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_genome_automata.py +0 -0
  399. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_github_scrape.py +0 -0
  400. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_kit.py +0 -0
  401. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_marquee_v0_2_16.py +0 -0
  402. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_mcp.py +0 -0
  403. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_paradigm_cellular.py +0 -0
  404. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_paradigm_dispatch.py +0 -0
  405. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_paradigm_extensibility.py +0 -0
  406. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_parse_transcript_auto.py +0 -0
  407. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_proofset.py +0 -0
  408. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_receipt_token_compliance.py +0 -0
  409. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_render.py +0 -0
  410. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_resolver_rhythm.py +0 -0
  411. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_runtime_registries.py +0 -0
  412. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_serve.py +0 -0
  413. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_serve_live_state.py +0 -0
  414. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_slot_metric_state.py +0 -0
  415. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_state_inference.py +0 -0
  416. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_stats_card.py +0 -0
  417. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_strip_brutalist_grammar.py +0 -0
  418. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_strip_cellular.py +0 -0
  419. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_strip_status_toggle.py +0 -0
  420. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_telemetry.py +0 -0
  421. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_telemetry_contract_per_stage.py +0 -0
  422. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_telemetry_skin_dispatch.py +0 -0
  423. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_tool_class_completeness.py +0 -0
  424. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_url_stability.py +0 -0
  425. {hyperweave-0.3.2 → hyperweave-0.3.4}/tests/test_variant_default_resolution.py +0 -0
  426. {hyperweave-0.3.2 → hyperweave-0.3.4}/uv.lock +0 -0
@@ -5,6 +5,44 @@ 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.4] - 2026-05-13
9
+
10
+ `install-hook` now detects Claude Code and Codex automatically. A new `hyperweave doctor` command shows hook status, transcripts, and recent receipts at a glance.
11
+
12
+ ### Added
13
+
14
+ - **`hyperweave doctor`** — shows hook registration, transcript directories, recent receipts, and version info per runtime.
15
+ - **`install-hook --runtime all`** — registers hooks for both runtimes regardless of auto-detection.
16
+
17
+ ### Changed
18
+
19
+ - **`install-hook` default** — without `--runtime`, detects which runtimes are installed and registers hooks for each. `--runtime claude-code` or `--runtime codex` scopes to one.
20
+
21
+ ### Fixed
22
+
23
+ - **Receipt footer** — restores the full relative path (`.hyperweave/receipts/{slug}.svg`); v0.3.3 had stripped the directory prefix.
24
+
25
+ ### Notes
26
+
27
+ - Codex receipts refresh live as the session progresses, reflecting cumulative state after each turn.
28
+
29
+ ## [0.3.3] - 2026-05-12
30
+
31
+ ### Fixed
32
+
33
+ - **Receipt filenames** — use consistent underscore separators; the footer displays the same human-readable filename.
34
+ - **Dark brutalist badge panels** — match the prototype: left panel reads `brand_panel_fill`, label reads `ink-primary`, seam-gap rect restored so the divider region renders the same in any markdown viewer.
35
+ - **Badge layout engine** — brutalist badges land every interior gap (accent→glyph, glyph→label, label→seam, seam→value, value→indicator, indicator→right border) on a single 5px rhythm. `measure_text` now consumes the paradigm's declared `value_letter_spacing_em` so the engine reserves the actual rendered width instead of under-counting by `(n-1) * font_size * em`.
36
+ - **Dark brutalist star charts** — header glyph fill routes through `var(--dna-signal)` (was an orphaned brand-text white). 6px solid left accent rail anchors the chart as a Y-axis spine; outer perimeter softens to a 1.5px hairline at 0.25 opacity so the rail dominates the read.
37
+ - **Light scholar star charts** — area gradient resolves through each variant's panel color across all 6 light variants instead of falling back to the seam color. Substrate-aware paper grain with multiply blend; perimeter inset and grain layer order match the prototype.
38
+ - **Activity graph bars** — light scholar stat cards use the correct accent color.
39
+ - **Divider tick marks** — resolve through the genome palette instead of a hardcoded green.
40
+
41
+ ### Changed
42
+
43
+ - **Star chart milestone callouts** — now include date context (e.g. `1K · JAN 24`) so the chart is self-documenting without cross-referencing external star history tools.
44
+ - **Star chart milestone markers** — data points use a filled square marker (■) to visually distinguish them from the regular interval crosshair (+) markers.
45
+
8
46
  ## [0.3.2] - 2026-05-11
9
47
 
10
48
  Brutalist gets 12 variants split by substrate: 6 dark monochromes (celadon, carbon, alloy, temper, pigment, ember) and 6 light scholars (archive, signal, pulse, depth, afterimage, primer). Metadata pipeline wires 12 fields that were silently hardcoded. Per-frame reasoning populates `hw:reasoning` from per-genome YAML.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperweave
3
- Version: 0.3.2
3
+ Version: 0.3.4
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
@@ -197,11 +197,11 @@ Why genome and not theme? Because brand isn't a design problem, it's an infrastr
197
197
  <tr>
198
198
  <th align="left">Dashboard<br/><sub>strip</sub></th>
199
199
  <td>
200
- <img src="https://hyperweave.app/v1/strip/readme-ai/brutalist.static?data=gh:eli64s/readme-ai.stars,gh:eli64s/readme-ai.forks,pypi:readmeai.version&subtitle=eli64s/readme-ai&glyph=github&variant=celadon" alt="strip"/>
200
+ <img src="https://hyperweave.app/v1/strip/hyperweave/brutalist.static?data=gh:InnerAura/hyperweave.stars,pypi:hyperweave.version,gh:InnerAura/hyperweave.build&subtitle=InnerAura/hyperweave&glyph=github&variant=celadon" alt="strip"/>
201
201
  <br/>
202
202
  <ul>
203
203
  <li><sub><code>/v1/strip/{title}/{genome}.static?data={tokens}&subtitle={text}&glyph={glyph}&variant={variant}</code></sub></li>
204
- <li><sub><code>hyperweave.app/v1/strip/readme-ai/brutalist.static?data=gh:eli64s/readme-ai.stars,gh:eli64s/readme-ai.forks,pypi:readmeai.version&subtitle=eli64s/readme-ai&glyph=github&variant=celadon</code></sub></li>
204
+ <li><sub><code>hyperweave.app/v1/strip/hyperweave/brutalist.static?data=gh:InnerAura/hyperweave.stars,pypi:hyperweave.version,gh:InnerAura/hyperweave.build&subtitle=InnerAura/hyperweave&glyph=github&variant=celadon</code></sub></li>
205
205
  </ul>
206
206
  </td>
207
207
  </tr>
@@ -165,11 +165,11 @@ Why genome and not theme? Because brand isn't a design problem, it's an infrastr
165
165
  <tr>
166
166
  <th align="left">Dashboard<br/><sub>strip</sub></th>
167
167
  <td>
168
- <img src="https://hyperweave.app/v1/strip/readme-ai/brutalist.static?data=gh:eli64s/readme-ai.stars,gh:eli64s/readme-ai.forks,pypi:readmeai.version&subtitle=eli64s/readme-ai&glyph=github&variant=celadon" alt="strip"/>
168
+ <img src="https://hyperweave.app/v1/strip/hyperweave/brutalist.static?data=gh:InnerAura/hyperweave.stars,pypi:hyperweave.version,gh:InnerAura/hyperweave.build&subtitle=InnerAura/hyperweave&glyph=github&variant=celadon" alt="strip"/>
169
169
  <br/>
170
170
  <ul>
171
171
  <li><sub><code>/v1/strip/{title}/{genome}.static?data={tokens}&subtitle={text}&glyph={glyph}&variant={variant}</code></sub></li>
172
- <li><sub><code>hyperweave.app/v1/strip/readme-ai/brutalist.static?data=gh:eli64s/readme-ai.stars,gh:eli64s/readme-ai.forks,pypi:readmeai.version&subtitle=eli64s/readme-ai&glyph=github&variant=celadon</code></sub></li>
172
+ <li><sub><code>hyperweave.app/v1/strip/hyperweave/brutalist.static?data=gh:InnerAura/hyperweave.stars,pypi:hyperweave.version,gh:InnerAura/hyperweave.build&subtitle=InnerAura/hyperweave&glyph=github&variant=celadon</code></sub></li>
173
173
  </ul>
174
174
  </td>
175
175
  </tr>
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.3.2'
22
- __version_tuple__ = version_tuple = (0, 3, 2)
21
+ __version__ = version = '0.3.4'
22
+ __version_tuple__ = version_tuple = (0, 3, 4)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -361,39 +361,56 @@ def session(
361
361
 
362
362
  frame_type = "receipt" if action == "receipt" else "rhythm-strip"
363
363
  genome_slug = _normalize_genome_slug(genome) if genome else ""
364
+
365
+ # Pre-compute the receipt's on-disk filename (when applicable) so the
366
+ # footer can render the same path as the file the user sees. The compose
367
+ # pipeline reads receipt_filename_hint when set; an empty hint falls back
368
+ # to the legacy UUID-path footer (HTTP / MCP). Pass the FULL relative
369
+ # path (not just the basename) so the footer is self-documenting — a
370
+ # reader sees ".hyperweave/receipts/{slug}.svg" and knows where to find
371
+ # the file without prior context. Long footers trigger left-truncation
372
+ # of the constant prefix at resolver.py:_truncate_path_left.
373
+ filename_hint = ""
374
+ if action == "receipt" and not output:
375
+ from datetime import datetime as _dt
376
+
377
+ from hyperweave.telemetry.receipt_paths import receipt_filename
378
+
379
+ sess = contract.get("session", {})
380
+ sid = sess.get("id", "unknown")
381
+ session_name = sess.get("name", "")
382
+ start_iso = sess.get("start", "")
383
+ try:
384
+ ts = _dt.fromisoformat(start_iso)
385
+ except (TypeError, ValueError):
386
+ ts = _dt.now()
387
+ user_events = contract.get("user_events", []) or []
388
+ first_prompt = user_events[0].get("preview", "") if user_events else ""
389
+ hw_dir = Path(".hyperweave") / "receipts"
390
+ hw_dir.mkdir(parents=True, exist_ok=True)
391
+ output = hw_dir / receipt_filename(
392
+ timestamp=ts,
393
+ session_name=session_name,
394
+ session_id=sid,
395
+ prompt_text=first_prompt,
396
+ )
397
+ filename_hint = str(output)
398
+ elif action == "receipt" and output:
399
+ # Explicit --output: surface whatever path shape the user provided.
400
+ filename_hint = str(output)
401
+
364
402
  spec = ComposeSpec(
365
403
  type=frame_type,
366
404
  genome_id=genome_slug,
367
405
  telemetry_data=contract,
406
+ receipt_filename_hint=filename_hint,
368
407
  )
369
408
  result = do_compose(spec)
370
409
 
371
410
  if action == "receipt":
372
- # Default output: .hyperweave/receipts/{date}_{time}_{slug}.svg
373
- if not output:
374
- from datetime import datetime as _dt
375
-
376
- from hyperweave.telemetry.receipt_paths import receipt_filename
377
-
378
- sess = contract.get("session", {})
379
- sid = sess.get("id", "unknown")
380
- session_name = sess.get("name", "")
381
- start_iso = sess.get("start", "")
382
- try:
383
- ts = _dt.fromisoformat(start_iso)
384
- except (TypeError, ValueError):
385
- ts = _dt.now()
386
- user_events = contract.get("user_events", []) or []
387
- first_prompt = user_events[0].get("preview", "") if user_events else ""
388
- hw_dir = Path(".hyperweave") / "receipts"
389
- hw_dir.mkdir(parents=True, exist_ok=True)
390
- output = hw_dir / receipt_filename(
391
- timestamp=ts,
392
- session_name=session_name,
393
- session_id=sid,
394
- prompt_text=first_prompt,
395
- )
396
-
411
+ # output is guaranteed non-None here: the receipt branch above either
412
+ # received an explicit --output or computed a default path.
413
+ assert output is not None
397
414
  output.parent.mkdir(parents=True, exist_ok=True)
398
415
  output.write_text(result.svg)
399
416
 
@@ -554,12 +571,13 @@ def _install_codex_hook(hook_command: str, full_slug: str) -> None:
554
571
  """Write a Stop hook to ``~/.codex/hooks.json`` + enable codex_hooks feature.
555
572
 
556
573
  Per developers.openai.com/codex/hooks, Codex CLI fires Stop hooks
557
- PER-TURN (not per-session). Receipts therefore render at every turn
558
- boundary rather than once at session end. Document this caveat
559
- prominentlyusers may want to manually invoke
560
- ``hyperweave session receipt <transcript-path>`` once a session
561
- completes instead. v0.2.24 will revisit when codex notify-config
562
- surfaces a session-scoped event.
574
+ PER-TURN (after every assistant response). The receipt rewrites the
575
+ same deterministic filename each turn, so the on-disk file becomes a
576
+ live mid-session telemetry window opening it during a long session
577
+ shows the current state, and the final write at session-end carries
578
+ the complete cumulative receipt. This is intentional; future versions
579
+ will lean into live-receipt consumers (file watchers, dashboards)
580
+ rather than collapse it back to a single session-end event.
563
581
 
564
582
  Also writes ``[features] codex_hooks = true`` to ``~/.codex/config.toml``
565
583
  (preserving any other keys); the feature flag is required for the
@@ -615,8 +633,8 @@ def _install_codex_hook(hook_command: str, full_slug: str) -> None:
615
633
  typer.echo(f"Installed Stop hook in {hooks_path}{pinned}")
616
634
  typer.echo(f"Set [features] codex_hooks = true in {config_path}")
617
635
  typer.echo(
618
- "Note: Codex Stop fires per-turn — receipts render multiple times per session. "
619
- "v0.2.24 will refine to a session-scoped event.",
636
+ "Note: Codex Stop fires per-turn — the receipt file refreshes live as the "
637
+ "session progresses, always reflecting current cumulative state.",
620
638
  err=True,
621
639
  )
622
640
 
@@ -630,6 +648,37 @@ _HOOK_INSTALLERS = {
630
648
  "codex": _install_codex_hook,
631
649
  }
632
650
 
651
+ # Runtime → (config_dirname_under_home, cli_binary_name). Drives both the
652
+ # auto-detect path (config dir OR binary on PATH) and `hyperweave doctor`
653
+ # state reporting. Config-dir presence means "agent has been run at least
654
+ # once"; binary-on-PATH covers fresh installs where the dir hasn't been
655
+ # created yet. The installers create their dirs on demand, so installing
656
+ # for a binary-only runtime is safe.
657
+ _RUNTIME_DETECTION = {
658
+ "claude-code": (".claude", "claude"),
659
+ "codex": (".codex", "codex"),
660
+ }
661
+
662
+
663
+ def _detect_installed_runtimes() -> list[tuple[str, str]]:
664
+ """Detect installed agent runtimes via config-dir-OR-binary-on-PATH.
665
+
666
+ Returns ``(runtime_key, signal)`` tuples in ``_RUNTIME_DETECTION`` order.
667
+ Signal is ``"initialized"`` when the runtime's config dir exists (agent
668
+ has been run at least once), ``"binary_only"`` when only the CLI is on
669
+ PATH (fresh install, config dir not created yet). Runtimes with
670
+ neither signal are omitted entirely.
671
+ """
672
+ import shutil
673
+
674
+ detected: list[tuple[str, str]] = []
675
+ for runtime, (dirname, binname) in _RUNTIME_DETECTION.items():
676
+ if (Path.home() / dirname).exists():
677
+ detected.append((runtime, "initialized"))
678
+ elif shutil.which(binname):
679
+ detected.append((runtime, "binary_only"))
680
+ return detected
681
+
633
682
 
634
683
  @app.command("install-hook")
635
684
  def install_hook(
@@ -649,28 +698,55 @@ def install_hook(
649
698
  typer.Option(
650
699
  "--runtime",
651
700
  help=(
652
- "Agent runtime to install the receipt hook for. 'claude-code' (default) "
653
- "writes a SessionEnd hook to ~/.claude/settings.json. 'codex' writes a "
654
- "Stop hook to ~/.codex/hooks.json plus enables [features] codex_hooks "
655
- "in ~/.codex/config.toml. Codex Stop is per-turn, not per-session — "
656
- "see release notes for caveats."
701
+ "Agent runtime to install the receipt hook for. Empty (default) "
702
+ "auto-detects installed runtimes (~/.claude, ~/.codex, or 'claude'/"
703
+ "'codex' on PATH) and registers for each present. 'claude-code' "
704
+ "writes a SessionEnd hook to ~/.claude/settings.json. 'codex' writes "
705
+ "a Stop hook to ~/.codex/hooks.json plus [features] codex_hooks in "
706
+ "~/.codex/config.toml. 'all' forces both regardless of detection."
657
707
  ),
658
708
  ),
659
- ] = "claude-code",
709
+ ] = "",
660
710
  ) -> None:
661
- """Install a session-receipt hook for the chosen agent runtime."""
711
+ """Install session-receipt hooks for installed agent runtimes.
712
+
713
+ Default behavior detects which agent CLIs are installed (Claude Code,
714
+ Codex) via config dir presence or binary on PATH, and registers receipt
715
+ hooks for each. Pass ``--runtime <name>`` to scope to a single runtime,
716
+ or ``--runtime all`` to force both regardless of detection.
717
+ """
662
718
  from hyperweave.compose.resolver import _genome_supports_receipts
663
719
 
664
- if runtime not in _HOOK_INSTALLERS:
720
+ # Resolve targets:
721
+ # "" (default) → auto-detect installed runtimes (config dir OR binary)
722
+ # "all" → both runtimes regardless of detection
723
+ # "<name>" → just that runtime (legacy explicit form)
724
+ if runtime == "":
725
+ detected = _detect_installed_runtimes()
726
+ if not detected:
727
+ typer.echo(
728
+ "Error: no agent runtime detected (~/.claude, ~/.codex, or "
729
+ "'claude'/'codex' on PATH). Install Claude Code or Codex CLI, "
730
+ "or pass --runtime <name> to force.",
731
+ err=True,
732
+ )
733
+ raise typer.Exit(1)
734
+ targets = [rt for rt, _signal in detected]
735
+ elif runtime == "all":
736
+ targets = list(_HOOK_INSTALLERS)
737
+ elif runtime in _HOOK_INSTALLERS:
738
+ targets = [runtime]
739
+ else:
665
740
  typer.echo(
666
- f"Error: unknown runtime '{runtime}'. Supported: {sorted(_HOOK_INSTALLERS)}",
741
+ f"Error: unknown runtime '{runtime}'. Supported: {sorted(_HOOK_INSTALLERS)} or 'all'.",
667
742
  err=True,
668
743
  )
669
744
  raise typer.Exit(1)
670
745
 
671
- # Validate --genome BEFORE writing the hook. install-hook fails loud (unlike
672
- # the receipt CLI which silently falls through) because pinning a bad genome
673
- # would produce silent surprises every session-end until someone notices.
746
+ # Validate --genome BEFORE writing any hook. install-hook fails loud
747
+ # (unlike the receipt CLI which silently falls through) because pinning
748
+ # a bad genome would produce silent surprises every session-end until
749
+ # someone notices. Validate once even when targeting multiple runtimes.
674
750
  full_slug = ""
675
751
  if genome:
676
752
  full_slug = _normalize_genome_slug(genome)
@@ -685,7 +761,151 @@ def install_hook(
685
761
 
686
762
  hook_command = f"hyperweave session receipt --genome {full_slug}" if full_slug else "hyperweave session receipt"
687
763
 
688
- _HOOK_INSTALLERS[runtime](hook_command, full_slug)
764
+ for target in targets:
765
+ _HOOK_INSTALLERS[target](hook_command, full_slug)
766
+
767
+
768
+ def _doctor_runtime_status(runtime: str, home_dir: Path) -> str:
769
+ """Parse a runtime's hook config and return a one-line status string.
770
+
771
+ Returns ``✓`` when the hyperweave hook is wired correctly, ``✗`` when
772
+ the runtime is initialized but no hyperweave hook is registered, or
773
+ ``⚠`` when the wiring is partial (malformed config; codex missing the
774
+ [features] codex_hooks flag). The string is rendered verbatim by
775
+ ``doctor``.
776
+ """
777
+ import json
778
+
779
+ if runtime == "claude-code":
780
+ settings_path = home_dir / "settings.json"
781
+ if not settings_path.exists():
782
+ return (
783
+ f"✗ {runtime}: ~/.claude/ exists but no settings.json — "
784
+ f"run 'hyperweave install-hook --runtime {runtime}'"
785
+ )
786
+ try:
787
+ settings = json.loads(settings_path.read_text())
788
+ except json.JSONDecodeError:
789
+ return f"⚠ {runtime}: ~/.claude/settings.json is malformed"
790
+ for entry in settings.get("hooks", {}).get("SessionEnd", []) or []:
791
+ if not isinstance(entry, dict):
792
+ continue
793
+ for hook in entry.get("hooks", []) or []:
794
+ if not isinstance(hook, dict):
795
+ continue
796
+ cmd = str(hook.get("command", ""))
797
+ if "hyperweave session" in cmd:
798
+ return f"✓ {runtime}: hook registered — {cmd}"
799
+ return f"✗ {runtime}: initialized but no hyperweave hook — run 'hyperweave install-hook --runtime {runtime}'"
800
+
801
+ if runtime == "codex":
802
+ hooks_path = home_dir / "hooks.json"
803
+ config_path = home_dir / "config.toml"
804
+ registered_cmd: str | None = None
805
+ if hooks_path.exists():
806
+ try:
807
+ hooks = json.loads(hooks_path.read_text())
808
+ except json.JSONDecodeError:
809
+ return f"⚠ {runtime}: ~/.codex/hooks.json is malformed"
810
+ for entry in hooks.get("Stop", []) or []:
811
+ if not isinstance(entry, dict):
812
+ continue
813
+ cmd = str(entry.get("command", ""))
814
+ if "hyperweave session" in cmd:
815
+ registered_cmd = cmd
816
+ break
817
+ if not registered_cmd:
818
+ return (
819
+ f"✗ {runtime}: initialized but no hyperweave hook — run 'hyperweave install-hook --runtime {runtime}'"
820
+ )
821
+ # [features] codex_hooks = true must be present for the hook to fire;
822
+ # the install command writes it, but a hand-edited config could miss it.
823
+ feature_ok = False
824
+ if config_path.exists():
825
+ in_features = False
826
+ for line in config_path.read_text().splitlines():
827
+ stripped = line.strip()
828
+ if stripped == "[features]":
829
+ in_features = True
830
+ continue
831
+ if in_features and stripped.startswith("["):
832
+ in_features = False
833
+ continue
834
+ if in_features and stripped.startswith("codex_hooks") and "true" in stripped:
835
+ feature_ok = True
836
+ break
837
+ if not feature_ok:
838
+ return (
839
+ f"⚠ {runtime}: hook registered but [features] codex_hooks = true "
840
+ f"is missing — re-run 'hyperweave install-hook --runtime {runtime}'"
841
+ )
842
+ return f"✓ {runtime}: hook registered — {registered_cmd}"
843
+
844
+ return f"? {runtime}: unknown runtime"
845
+
846
+
847
+ @app.command()
848
+ def doctor() -> None:
849
+ """Diagnose hyperweave telemetry wiring across agent runtimes.
850
+
851
+ Reports per-runtime detection state (initialized / binary-only /
852
+ absent), hook registration status, transcript dir state, and recent
853
+ receipt activity in the current directory. Read-only — never
854
+ modifies any config. Always exits 0.
855
+ """
856
+ import shutil
857
+ from datetime import datetime, timedelta
858
+
859
+ from hyperweave import __version__
860
+
861
+ typer.echo(f"hyperweave doctor — v{__version__}")
862
+ typer.echo("")
863
+ typer.echo("Runtimes:")
864
+ for runtime, (dirname, binname) in _RUNTIME_DETECTION.items():
865
+ home_dir = Path.home() / dirname
866
+ if home_dir.exists():
867
+ typer.echo(f" {_doctor_runtime_status(runtime, home_dir)}")
868
+ elif bin_path := shutil.which(binname):
869
+ typer.echo(
870
+ f" ⚠ {runtime}: CLI on PATH at {bin_path} but ~/{dirname}/ "
871
+ f"not initialized — run '{binname}' once, then "
872
+ f"'hyperweave install-hook --runtime {runtime}'"
873
+ )
874
+ else:
875
+ typer.echo(f" ✗ {runtime}: not detected")
876
+
877
+ typer.echo("")
878
+ typer.echo("Transcripts:")
879
+ for runtime, subdir in (("claude-code", "projects"), ("codex", "sessions")):
880
+ dirname = _RUNTIME_DETECTION[runtime][0]
881
+ root = Path.home() / dirname / subdir
882
+ display_root = f"~/{dirname}/{subdir}"
883
+ if not root.exists():
884
+ typer.echo(f" {runtime}: {display_root} (not found)")
885
+ continue
886
+ files = list(root.rglob("*.jsonl"))
887
+ if not files:
888
+ typer.echo(f" {runtime}: {display_root}/ (empty)")
889
+ continue
890
+ most_recent = max(files, key=lambda p: p.stat().st_mtime)
891
+ mtime = datetime.fromtimestamp(most_recent.stat().st_mtime)
892
+ typer.echo(f" {runtime}: {len(files)} transcript(s), most recent {mtime:%Y-%m-%d %H:%M}")
893
+
894
+ typer.echo("")
895
+ typer.echo("Receipts (./.hyperweave/receipts/):")
896
+ receipts_dir = Path(".hyperweave") / "receipts"
897
+ if not receipts_dir.exists():
898
+ typer.echo(" (no receipts directory in cwd)")
899
+ return
900
+ svgs = [p for p in receipts_dir.iterdir() if p.is_file() and p.suffix == ".svg"]
901
+ if not svgs:
902
+ typer.echo(" (no receipts)")
903
+ return
904
+ cutoff = datetime.now() - timedelta(days=7)
905
+ recent = [p for p in svgs if datetime.fromtimestamp(p.stat().st_mtime) > cutoff]
906
+ most_recent = max(svgs, key=lambda p: p.stat().st_mtime)
907
+ typer.echo(f" {len(recent)} receipt(s) in last 7 days, {len(svgs)} total")
908
+ typer.echo(f" most recent: {most_recent.name}")
689
909
 
690
910
 
691
911
  @app.command("validate-genome")
@@ -110,6 +110,8 @@ def compute_badge_layout(
110
110
  value_font_size: float,
111
111
  right_canvas_inset: int = 0,
112
112
  min_total_w: int = 60,
113
+ inner_bit_ratio: float = 0.5,
114
+ rhythm_gap: int = 0,
113
115
  ) -> BadgeLayout:
114
116
  """Compute every position the badge templates need from input measurements.
115
117
 
@@ -121,44 +123,83 @@ def compute_badge_layout(
121
123
 
122
124
  The centering correctness is verified by ``tests/test_badge_layout``
123
125
  against short / long / version / license / python_requires values.
126
+
127
+ When ``rhythm_gap > 0`` (brutalist v0.3.3 sets 8), the layout collapses
128
+ every interior gap to a single value: accent_right→glyph_left,
129
+ glyph_right→label_first, label_last→seam_left, seam_right→value_first,
130
+ value_last→indicator_left, indicator_right→right_border. Caller must
131
+ also set ``ind_pad_r=rhythm_gap`` so the indicator gaps land on the
132
+ same rhythm.
124
133
  """
125
134
  # Glyph pixel position. Mirrors resolver.py logic: paradigms with a
126
135
  # left-edge decoration zone (cellular pattern strip x=2..~20) reserve
127
136
  # space via ``glyph_left_offset``; brutalist/chrome declare 0.
137
+ # When rhythm_gap is set, the glyph sits exactly ``rhythm_gap`` right
138
+ # of the accent bar so the accent→glyph gap matches the global rhythm.
128
139
  if has_glyph:
129
- glyph_x = (inset + accent_w + 4) if inset else (accent_w + 3)
130
- glyph_x += glyph_left_offset
140
+ if rhythm_gap > 0:
141
+ glyph_x = accent_w + rhythm_gap + glyph_left_offset
142
+ else:
143
+ glyph_x = (inset + accent_w + 4) if inset else (accent_w + 3)
144
+ glyph_x += glyph_left_offset
131
145
  glyph_y = round((height - glyph_size) / 2, 1)
132
146
  else:
133
147
  glyph_x, glyph_y = 0, 0.0
134
148
 
135
149
  # Label area starts after the glyph (or after the accent + paradigm
136
- # left-edge decoration when there's no glyph). The no-glyph branch
137
- # must respect glyph_left_offset too cellular pattern strip runs
138
- # to ~x=20 even when no glyph is rendered.
139
- label_start = (glyph_x + glyph_size + glyph_gap) if has_glyph else (accent_w + 6 + glyph_left_offset)
150
+ # left-edge decoration when there's no glyph). When rhythm_gap > 0,
151
+ # the glyph→label gap (with-glyph) and accent→label gap (no-glyph)
152
+ # both equal rhythm_gap.
153
+ if rhythm_gap > 0:
154
+ label_start = (glyph_x + glyph_size + rhythm_gap) if has_glyph else (accent_w + rhythm_gap + glyph_left_offset)
155
+ else:
156
+ label_start = (glyph_x + glyph_size + glyph_gap) if has_glyph else (accent_w + 6 + glyph_left_offset)
140
157
 
141
158
  # Left panel width — fits the label plus paradigm-driven right padding.
142
- label_pad_r = 9 if use_mono else 8
159
+ # rhythm_gap mode forces label_pad_r = rhythm_gap so label_last→seam_left
160
+ # equals the global rhythm. Legacy mode keeps the 9 (mono) / 8 (non-mono)
161
+ # default tuned for chrome/cellular's denser label kerning.
162
+ label_pad_r = rhythm_gap if rhythm_gap > 0 else (9 if use_mono else 8)
143
163
  left_panel = round(label_start + measured_label_w + label_pad_r)
144
164
  left_panel = max(left_panel, 30)
145
165
 
146
- # Label text center is the midpoint of the label area. For uppercase
147
- # labels the visual right edge is 6px shy of the panel boundary so
148
- # the cap glyphs don't kiss the seam.
149
- label_area_end = left_panel - (6 if label_uppercase else 0)
150
- label_x = round((label_start + label_area_end) / 2, 1)
166
+ # Label text center. Legacy mode centers the label in [label_start,
167
+ # label_area_end] with a 6px shy-from-seam adjustment for uppercase
168
+ # labels. rhythm_gap mode aligns label_first with label_start exactly
169
+ # (label_x = label_start + w/2) so the accent_right→label_first gap
170
+ # lands at ``rhythm_gap`` regardless of label_w. The legacy area-center
171
+ # formula leaves a (panel_w - label_w)/2 interior gutter inside the
172
+ # label area, which collapses the structural gap to ~(rhythm_gap +
173
+ # interior_gutter)/2 — visible as 12.2/4.2 asymmetry on a 35.64px
174
+ # label in a 44px area when targeting an 8px rhythm.
175
+ if rhythm_gap > 0:
176
+ label_area_end = left_panel
177
+ label_x = round(label_start + measured_label_w / 2, 1)
178
+ else:
179
+ label_area_end = left_panel - (6 if label_uppercase else 0)
180
+ label_x = round((label_start + label_area_end) / 2, 1)
151
181
 
152
182
  # Right-panel allocation. ``ls_extra`` accounts for non-mono letter-
153
183
  # spacing overrun (each char carries 0.4 of trailing tracking).
154
184
  indicator_alloc = (indicator_size + ind_pad_r) if show_indicator else 0
155
185
  ls_extra = value_raw_len * 0.4 if (not use_mono and value_raw_len) else 0
156
- # right_panel reserves: val_pad_l (left interior gutter), the measured
157
- # value text + letter-spacing overrun, val_min_gap (right interior gutter),
158
- # and indicator_alloc when stateful. Pre-v0.3.0 reserved 2 * val_min_gap
159
- # which left ~val_min_gap of unaccounted slack on stateless badges
160
- # (visible as ~4.5px right padding instead of symmetric ~3px).
161
- right_panel = val_pad_l + measured_value_w + ls_extra + val_min_gap + indicator_alloc
186
+ # Gap between value text right edge and the indicator's left edge. For
187
+ # stateful badges this mirrors ``ind_pad_r`` (gap right of indicator) so
188
+ # the indicator sits with equal interior padding on both sides — the
189
+ # cohesive-balance contract the brutalist v16 prototype encodes. For
190
+ # stateless badges there's no indicator, so the trailing pad collapses
191
+ # to ``val_min_gap`` (3px tight right gutter; tighter than the stateful
192
+ # symmetric gap because there's no marker to balance against).
193
+ text_to_indicator_gap = ind_pad_r if show_indicator else val_min_gap
194
+ # rhythm_gap mode overrides ``val_pad_l`` (seam→value gap) to the
195
+ # global rhythm. Legacy mode keeps the resolver-supplied val_pad_l
196
+ # (3px) for chrome/cellular/default paradigms.
197
+ effective_val_pad_l = rhythm_gap if rhythm_gap > 0 else val_pad_l
198
+ # right_panel reserves: effective_val_pad_l (left interior gutter), the
199
+ # measured value text + letter-spacing overrun, text_to_indicator_gap
200
+ # (right interior gutter), and indicator_alloc when stateful. Symmetric
201
+ # stateful: text + ind_pad_r + indicator_size + ind_pad_r.
202
+ right_panel = effective_val_pad_l + measured_value_w + ls_extra + text_to_indicator_gap + indicator_alloc
162
203
  total_w = round(left_panel + sep_w + seam_w + right_panel)
163
204
  total_w = max(total_w, min_total_w)
164
205
 
@@ -176,13 +217,14 @@ def compute_badge_layout(
176
217
  # which is the midpoint of [zone_left, indicator_left_edge], not
177
218
  # [zone_left, zone_right]. Old formula skewed text by val_min_gap/2
178
219
  # toward the indicator and was undefined when no indicator rendered.
179
- value_zone_left = right_panel_x + val_pad_l
220
+ value_zone_left = right_panel_x + effective_val_pad_l
180
221
  # When stateless (no indicator), the slab's right edge is total_w minus
181
- # any paradigm-specific canvas inset (cellular: 2; brutalist/chrome: 0).
182
- # val_min_gap is the symmetric trailing pad together they place
183
- # value_zone_right at the slab's interior right boundary so a centered
184
- # text lands at slab geometric center.
185
- value_zone_right = (indicator_x - val_min_gap) if show_indicator else (total_w - right_canvas_inset - val_min_gap)
222
+ # any paradigm-specific canvas inset (cellular: 2; brutalist/chrome: 0)
223
+ # minus val_min_gap (tight 3px trailing pad). When stateful, the right
224
+ # edge sits ind_pad_r inside the indicator's left edge mirroring the
225
+ # right-of-indicator gap so the indicator reads as equidistant from
226
+ # the value text and from the badge's right border.
227
+ value_zone_right = (indicator_x - ind_pad_r) if show_indicator else (total_w - right_canvas_inset - val_min_gap)
186
228
  value_zone_width = value_zone_right - value_zone_left
187
229
  value_x = round((value_zone_left + value_zone_right) / 2, 1)
188
230
 
@@ -196,9 +238,12 @@ def compute_badge_layout(
196
238
  indicator_y = round(text_y - value_font_size * 0.3 - indicator_size / 2, 1)
197
239
 
198
240
  # Indicator inner-bit geometry — moved from cellular/brutalist
199
- # template-side arithmetic. The bit is half the indicator side,
200
- # centered.
201
- inner_bit_w = indicator_size // 2
241
+ # template-side arithmetic. v0.3.3 generalizes the ratio so brutalist
242
+ # can render the prototype's 6/10 (0.6) bit instead of the cellular
243
+ # 4/8 (0.5) default — caller passes a paradigm-driven ratio. Rounded
244
+ # to the nearest integer so the bit lands on a pixel grid; offset is
245
+ # the half-difference, which can be a half-pixel for odd ratios.
246
+ inner_bit_w = round(indicator_size * inner_bit_ratio)
202
247
  inner_bit_offset = (indicator_size - inner_bit_w) / 2
203
248
 
204
249
  return BadgeLayout(