hyperweave 0.2.7__tar.gz → 0.2.8__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.
- {hyperweave-0.2.7 → hyperweave-0.2.8}/CHANGELOG.md +19 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/PKG-INFO +1 -1
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/_version.py +2 -2
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/context.py +9 -5
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/connectors/base.py +63 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/connectors/github.py +178 -24
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/render/chart_engine.py +112 -98
- hyperweave-0.2.8/src/hyperweave/templates/components/chart-area.svg.j2 +11 -0
- hyperweave-0.2.8/src/hyperweave/templates/components/chart-axes.svg.j2 +2 -0
- hyperweave-0.2.8/src/hyperweave/templates/components/chart-empty-state.svg.j2 +8 -0
- hyperweave-0.2.8/src/hyperweave/templates/components/chart-gridlines.svg.j2 +2 -0
- hyperweave-0.2.8/src/hyperweave/templates/components/chart-milestone.svg.j2 +7 -0
- hyperweave-0.2.8/src/hyperweave/templates/components/chart-polyline.svg.j2 +10 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/chart/brutalist-content.j2 +22 -8
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/chart/chrome-content.j2 +21 -7
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_chart_engine.py +74 -22
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_connectors.py +381 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/.dockerignore +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/.github/workflows/ci.yml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/.github/workflows/deploy.yml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/.github/workflows/publish.yml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/.gitignore +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/.pre-commit-config.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/Dockerfile +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/LICENSE +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/README.md +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/buttons/button-liquid.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/cards/card-butterfly.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/cards/card-python.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/cards/card-sunflower.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/cards/card-waves.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/badge_critical.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/badge_passing.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/badge_warning.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/banner.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/icons/discord.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/icons/notion.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/icons/reddit.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/icons/spotify.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/icons/youtube.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/marquee_counter.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/marquee_horizontal.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/marquee_vertical.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/profile-cards/chart_stars_full.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/profile-cards/stats.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/brutalist-emerald/strip.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/badge_critical.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/badge_passing.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/badge_warning.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/banner.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/icons/bluesky.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/icons/github.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/icons/instagram.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/icons/mastodon.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/icons/x.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/marquee_counter.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/marquee_horizontal.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/marquee_vertical.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/profile-cards/chart_stars_full.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/profile-cards/stats.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/chrome-horizon/strip.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/telemetry/master_card.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/telemetry/receipt.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/examples/telemetry/rhythm_strip.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/footers/inneraura-footer-liquid.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/footers/inneraura-footer-purple.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/footers/inneraura-footer.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/hyperweave-banner.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/icons/cobalt-sapphire-discord.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/icons/cobalt-sapphire-docs.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/icons/cobalt-sapphire-github.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/icons/cobalt-sapphire-instagram.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/icons/cobalt-sapphire-linkedin.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/icons/cobalt-sapphire-tiktok.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/icons/cobalt-sapphire-x.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/icons/cobalt-sapphire-youtube.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/marquees/badge-showcase-triple.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/marquees/genome-marquee-triple.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/marquees/sample-badges.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/404.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/callout-icons.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/divider.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/favicon.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/hero-banner.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/hyperweave-banner-v2.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/hyperweave-navbar-logo.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/loader.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/mintlify-assets/og-image.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/assets/timelines/hyperweave-roadmap.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/assets/favicon.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/assets/hyperweave-banner.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/assets/hyperweave-navbar-logo.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/assets/og-image.svg +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/explanation/architecture.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/explanation/camo-compatibility.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/explanation/cim-compliance.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/explanation/genome-profile-system.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/explanation/metadata-tiers.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/how-to/add-motion-to-badges.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/how-to/create-session-receipts.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/how-to/set-up-claude-code-hooks.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/how-to/use-live-data-badges.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/introduction.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/mint.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/quickstart.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/reference/cli.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/reference/compose-spec.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/reference/genomes.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/reference/http-api.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/reference/mcp-tools.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/reference/motions.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/reference/telemetry-contract.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/spec/hyperweave-protocol.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/tutorials/build-an-artifact-kit.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/tutorials/compose-your-first-badge.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/docs/tutorials/install-session-telemetry.mdx +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/fly.toml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/hooks/install.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/hooks/session_end.sh +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/justfile +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/pyproject.toml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/scripts/extract_font_metrics.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/scripts/extract_glyphs.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/scripts/generate_hw_compliant.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/scripts/generate_proofset.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/scripts/stress_test.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/__main__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/cli.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/assembler.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/engine.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/lanes.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/resolver.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/resolvers/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/resolvers/chart.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/resolvers/stats.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/resolvers/timeline.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/rhythm.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/compose/validate_paradigms.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/config/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/config/genome_validator.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/config/loader.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/config/registry.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/config/settings.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/connectors/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/connectors/arxiv.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/connectors/cache.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/connectors/rest.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/color.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/contracts.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/enums.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/font_metrics.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/models.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/paradigm.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/schema.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/state.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/text.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/core/thresholds.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/css/accessibility.css +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/css/bridge.css +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/css/expression.css +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/css/phase-colors.css +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/css/status.css +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/css/telemetry.css +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/font-metrics/inter.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/font-metrics/jetbrains-mono.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/font-metrics/orbitron.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/fonts/jetbrains-mono.b64 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/fonts/jetbrains-mono.meta.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/fonts/orbitron.b64 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/fonts/orbitron.meta.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/genomes/brutalist-emerald.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/genomes/chrome-horizon.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/genomes/telemetry-void.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/glyphs.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/border/chromatic-pulse.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/border/corner-trace.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/border/dual-orbit.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/border/entanglement.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/border/rimrun.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/bars.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/breach.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/broadcast.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/cascade.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/collapse.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/converge.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/crash.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/drop.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/kinetic/pulse.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/motions/static.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/paradigms/brutalist.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/paradigms/chrome.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/paradigms/default.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/policies/normal.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/policies/permissive.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/policies/ungoverned.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/profiles/brutalist.contract.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/profiles/brutalist.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/profiles/chrome.contract.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/profiles/chrome.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/specimens.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/telemetry/model-pricing.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/telemetry/stage-config.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/telemetry/stage-labels.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/telemetry/tool-classes.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/telemetry/tool-colors.yaml +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/arrow.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/aurora.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/beacon.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/bracket3d.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/chevron.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/crosshair.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/diamond.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/rocket.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/rules/bar.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/rules/dashed.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/rules/five-wave.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/rules/spectral.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/rules/straight.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/rules/wave.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/data/terminals/stijl.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/kit.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/mcp/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/mcp/__main__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/mcp/server.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/py.typed +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/render/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/render/fonts.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/render/glyphs.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/render/motion.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/render/templates.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/serve/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/serve/app.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/telemetry/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/telemetry/capture.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/telemetry/contract.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/telemetry/corrections.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/telemetry/cost.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/telemetry/models.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/telemetry/parser.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/telemetry/stages.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/chart-markers/circle.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/chart-markers/diamond.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/chart-markers/endpoint-diamond.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/chart-markers/endpoint-rect.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/chart-markers/rect.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/filter.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/glyph-inline.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/glyph.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/gradient.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/metadata.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/metric.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/phase-segment.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/rule.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/status.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/terminal.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/components/treemap.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/document.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/error-badge.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/badge/brutalist-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/badge/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/badge/chrome-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/badge/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/badge/default-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/badge/default-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/badge.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/banner/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/banner/chrome-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/banner/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/banner/default-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/banner/default-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/banner.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/catalog.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/chart/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/chart/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/chart.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/divider.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/icon/brutalist-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/icon/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/icon/chrome-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/icon/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/icon/default-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/icon/default-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/icon.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-counter/brutalist-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-counter/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-counter/chrome-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-counter/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-counter.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-horizontal/chrome-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-horizontal/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-horizontal.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-vertical/brutalist-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-vertical/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-vertical/chrome-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-vertical/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/marquee-vertical.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/master-card.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/receipt.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/rhythm-strip.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/stats/brutalist-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/stats/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/stats/chrome-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/stats/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/stats.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/brutalist-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/brutalist-status.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/chrome-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/chrome-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/chrome-status.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/default-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/default-defs.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip/default-status.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/strip.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/timeline/default-content.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/frames/timeline.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/border/chromatic-pulse.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/border/corner-trace.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/border/dual-orbit.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/border/entanglement.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/border/rimrun.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/bars.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/breach.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/broadcast.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/cascade.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/collapse.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/converge.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/crash.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/drop.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/src/hyperweave/templates/motions/kinetic/pulse.svg.j2 +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/__init__.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/conftest.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/fixtures/github_contributions/synthetic.html +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/fixtures/session.json +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/fixtures/session.jsonl +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/helpers.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_assembler.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_chart_frame.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_core.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_github_scrape.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_kit.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_mcp.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_paradigm_dispatch.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_paradigm_extensibility.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_proofset.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_render.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_resolver_rhythm.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_serve.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_serve_live_state.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_state_inference.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_stats_card.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_telemetry.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_telemetry_integration.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/tests/test_timeline.py +0 -0
- {hyperweave-0.2.7 → hyperweave-0.2.8}/uv.lock +0 -0
|
@@ -5,6 +5,25 @@ 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.2.8] - 2026-04-20
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Star history charts now render readably on large repositories.** Previously, repos with more than ~40,000 stars produced a flat-then-vertical "hockey stick" because GitHub's stargazer REST endpoint hard-caps deep pagination, so the only data reachable was a small cluster of early-history stars followed by a single jump to today. Star history now sources from GitHub's GraphQL API and adapts its sampling window to the repo: small repos continue to get full lifetime views, large repos get a detailed recent-growth curve similar to the one star-history.com shows.
|
|
13
|
+
- **Star-count milestone labels no longer stack on top of each other.** When sampled points clustered temporally, the milestone labels (`500`, `1K`, `5K`, `10K`, ...) would render in a single illegible pile on top of the crossing point. Milestones now maintain a minimum 40-pixel horizontal gap; any labels that would overlap with an already-placed one are dropped in favor of the first (lowest-threshold) milestone in the cluster.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **All chart rendering now flows through template partials.** The chart engine's remaining rendering paths — axes, gridlines, polyline, area fill, milestones, and the empty-state overlay — joined the marker layer in Jinja. The engine module returns structured Python data; Jinja partials under `templates/components/` produce the final SVG. No visual change; output is byte-identical for the shipped genomes on unchanged inputs.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **`fetch_graphql` connector primitive.** New async helper in the connector layer that handles POST with JSON bodies, GitHub bearer-token rotation, circuit-breaker coordination, and SSRF validation — mirroring the existing `fetch_json` contract. This unlocks future migration of the stats card's six REST sub-fetches to a single GraphQL call, and keeps a single canonical place for authenticated-POST plumbing.
|
|
22
|
+
|
|
23
|
+
### Dev
|
|
24
|
+
|
|
25
|
+
- GraphQL stargazer pipeline is covered by unit tests for the primary path, REST fallback on failure, no-token skip, mega-repo window cap, small-repo history exhaustion, downsampling correctness, and current-UTC now-point stamping.
|
|
26
|
+
|
|
8
27
|
## [0.2.7] - 2026-04-20
|
|
9
28
|
|
|
10
29
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperweave
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
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
|
|
@@ -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.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
21
|
+
__version__ = version = '0.2.8'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 8)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -337,12 +337,16 @@ def _ctx_chart(spec: ComposeSpec, resolved: ResolvedArtifact, css: dict[str, str
|
|
|
337
337
|
ctx["chart_viewport_w"] = 0
|
|
338
338
|
ctx["chart_viewport_h"] = 0
|
|
339
339
|
ctx["chart_defs"] = ""
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
ctx["
|
|
340
|
+
# Post-v0.2.8: axes / gridlines / milestones / markers all return structured
|
|
341
|
+
# lists; polyline / area / empty_state are dicts or None so templates can
|
|
342
|
+
# use ``{% if %}`` to guard includes without a StrictUndefined trap.
|
|
343
|
+
ctx["chart_axes"] = []
|
|
344
|
+
ctx["chart_gridlines"] = []
|
|
345
|
+
ctx["chart_area"] = None
|
|
346
|
+
ctx["chart_polyline"] = None
|
|
344
347
|
ctx["chart_markers"] = []
|
|
345
|
-
ctx["chart_milestones"] =
|
|
348
|
+
ctx["chart_milestones"] = []
|
|
349
|
+
ctx["chart_empty_state"] = None
|
|
346
350
|
ctx["data_hw_status"] = "fresh"
|
|
347
351
|
ctx.update(resolved.frame_context)
|
|
348
352
|
return ctx
|
|
@@ -216,3 +216,66 @@ async def fetch_text(
|
|
|
216
216
|
merged.update(headers)
|
|
217
217
|
response = await fetch(url, provider=provider, headers=merged)
|
|
218
218
|
return response.text
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
# GraphQL POST
|
|
222
|
+
|
|
223
|
+
_GITHUB_GRAPHQL_URL: str = "https://api.github.com/graphql"
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
async def fetch_graphql(
|
|
227
|
+
query: str,
|
|
228
|
+
variables: dict[str, Any] | None = None,
|
|
229
|
+
*,
|
|
230
|
+
provider: str = "github",
|
|
231
|
+
url: str = _GITHUB_GRAPHQL_URL,
|
|
232
|
+
) -> dict[str, Any]:
|
|
233
|
+
"""POST a GraphQL query and return the parsed JSON response.
|
|
234
|
+
|
|
235
|
+
Mirrors :func:`fetch_json`'s contract (SSRF validation, per-provider
|
|
236
|
+
circuit breaker, timeouts, GitHub Bearer-token injection) but speaks
|
|
237
|
+
POST with a JSON body. The single GraphQL endpoint for GitHub is
|
|
238
|
+
baked into the default URL so callers don't have to remember it.
|
|
239
|
+
|
|
240
|
+
GraphQL always returns HTTP 200 with a ``data`` field and an optional
|
|
241
|
+
``errors`` list — HTTP-level failures trip the breaker, but query-level
|
|
242
|
+
errors (invalid field, missing perms) come through as response body
|
|
243
|
+
and are the caller's responsibility to inspect.
|
|
244
|
+
"""
|
|
245
|
+
validate_url(url)
|
|
246
|
+
|
|
247
|
+
breaker = get_breaker(provider)
|
|
248
|
+
if not breaker.allow_request():
|
|
249
|
+
raise CircuitOpenError(
|
|
250
|
+
f"Circuit breaker open for provider {provider!r}. Retry after {breaker.recovery_timeout}s."
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
merged_headers: dict[str, str] = {
|
|
254
|
+
"User-Agent": f"HyperWeave/{__version__} (https://hyperweave.app)",
|
|
255
|
+
"Accept": "application/json",
|
|
256
|
+
"Content-Type": "application/json",
|
|
257
|
+
}
|
|
258
|
+
if provider == "github":
|
|
259
|
+
token = _get_github_token()
|
|
260
|
+
if token:
|
|
261
|
+
merged_headers["Authorization"] = f"Bearer {token}"
|
|
262
|
+
|
|
263
|
+
timeout = httpx.Timeout(
|
|
264
|
+
connect=CONNECT_TIMEOUT,
|
|
265
|
+
read=TOTAL_TIMEOUT,
|
|
266
|
+
write=TOTAL_TIMEOUT,
|
|
267
|
+
pool=TOTAL_TIMEOUT,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
body: dict[str, Any] = {"query": query, "variables": variables or {}}
|
|
271
|
+
|
|
272
|
+
try:
|
|
273
|
+
async with httpx.AsyncClient(timeout=timeout) as client:
|
|
274
|
+
response = await client.post(url, headers=merged_headers, json=body)
|
|
275
|
+
response.raise_for_status()
|
|
276
|
+
breaker.record_success()
|
|
277
|
+
data: dict[str, Any] = response.json()
|
|
278
|
+
return data
|
|
279
|
+
except (httpx.HTTPStatusError, httpx.RequestError) as exc:
|
|
280
|
+
breaker.record_failure()
|
|
281
|
+
raise ConnectorError(f"GraphQL fetch failed for {provider!r}: {exc}") from exc
|
|
@@ -8,7 +8,14 @@ import re
|
|
|
8
8
|
from datetime import UTC, datetime
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
|
-
from hyperweave.connectors.base import
|
|
11
|
+
from hyperweave.connectors.base import (
|
|
12
|
+
CircuitOpenError,
|
|
13
|
+
ConnectorError,
|
|
14
|
+
_get_github_token,
|
|
15
|
+
fetch_graphql,
|
|
16
|
+
fetch_json,
|
|
17
|
+
fetch_text,
|
|
18
|
+
)
|
|
12
19
|
from hyperweave.connectors.cache import get_cache
|
|
13
20
|
|
|
14
21
|
PROVIDER = "github"
|
|
@@ -144,6 +151,25 @@ _STARGAZER_PAGE_SIZE = 100
|
|
|
144
151
|
_STARGAZER_PAGE_CAP = 400
|
|
145
152
|
_STARGAZER_ACCEPT_HEADER = "application/vnd.github.v3.star+json"
|
|
146
153
|
|
|
154
|
+
# GraphQL-path constants. Walking backwards from "now" via cursor pagination
|
|
155
|
+
# bypasses the REST 400-page cap entirely. For small repos (≤2000 stars) we
|
|
156
|
+
# get full lifetime coverage; for mega-repos we get a recent-growth window,
|
|
157
|
+
# which is the behavior star-history.com uses for the same reason.
|
|
158
|
+
_GRAPHQL_PAGE_SIZE = 100
|
|
159
|
+
_GRAPHQL_MAX_PAGES = 20 # 20 * 100 = 2000 most-recent stargazers
|
|
160
|
+
|
|
161
|
+
_STARGAZER_GRAPHQL_QUERY = """
|
|
162
|
+
query StargazerWindow($owner: String!, $repo: String!, $cursor: String) {
|
|
163
|
+
repository(owner: $owner, name: $repo) {
|
|
164
|
+
stargazerCount
|
|
165
|
+
stargazers(last: 100, before: $cursor) {
|
|
166
|
+
pageInfo { startCursor hasPreviousPage }
|
|
167
|
+
edges { starredAt }
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
"""
|
|
172
|
+
|
|
147
173
|
|
|
148
174
|
async def fetch_stargazer_history(
|
|
149
175
|
owner: str,
|
|
@@ -152,19 +178,14 @@ async def fetch_stargazer_history(
|
|
|
152
178
|
) -> dict[str, Any]:
|
|
153
179
|
"""Fetch sampled star history for ``owner/repo`` as cumulative data points.
|
|
154
180
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
time marker for the cumulative count at ``(page - 1) * 30``.
|
|
164
|
-
5. Cache under ``github:{owner}/{repo}:stargazer-history``.
|
|
165
|
-
|
|
166
|
-
Returns a dict with keys ``points`` (list of ``{date, count}``), ``current_stars``,
|
|
167
|
-
``repo``, ``ttl``. Raises ``ValueError`` on invalid identifier.
|
|
181
|
+
Public dispatcher. Prefers GraphQL when a token is available (unlocks the
|
|
182
|
+
recent-growth window on mega-repos beyond GitHub's 400-page REST cap);
|
|
183
|
+
falls back to REST sampling on GraphQL failure or missing token. Caches
|
|
184
|
+
successful results under ``github:{owner}/{repo}:stargazer-history``.
|
|
185
|
+
|
|
186
|
+
Returns a dict with keys ``points`` (list of ``{date, count}``),
|
|
187
|
+
``current_stars``, ``repo``, ``ttl``. Raises ``ValueError`` on invalid
|
|
188
|
+
identifier.
|
|
168
189
|
"""
|
|
169
190
|
if not owner or not repo:
|
|
170
191
|
raise ValueError("fetch_stargazer_history requires owner and repo")
|
|
@@ -176,25 +197,162 @@ async def fetch_stargazer_history(
|
|
|
176
197
|
if cached is not None:
|
|
177
198
|
return cached # type: ignore[no-any-return]
|
|
178
199
|
|
|
200
|
+
result: dict[str, Any] | None = None
|
|
201
|
+
|
|
202
|
+
# Primary path: GraphQL (requires auth). Walks backwards from most-recent
|
|
203
|
+
# so mega-repos get a detailed recent-growth curve instead of a hockey
|
|
204
|
+
# stick. A per-page budget of 20 * 100 = 2000 stargazers per cold fetch
|
|
205
|
+
# keeps us well under the 5000-points/hour GraphQL rate limit.
|
|
206
|
+
if _get_github_token():
|
|
207
|
+
try:
|
|
208
|
+
result = await _fetch_stargazer_history_graphql(owner, repo, sample_pages)
|
|
209
|
+
except (ConnectorError, CircuitOpenError):
|
|
210
|
+
result = None # fall through to REST
|
|
211
|
+
|
|
212
|
+
if result is None:
|
|
213
|
+
# Fallback path: REST sampling. Works unauth at 60 req/hr but caps at
|
|
214
|
+
# ~40k stars on mega-repos (GitHub's deep-pagination wall).
|
|
215
|
+
result = await _fetch_stargazer_history_rest(owner, repo, sample_pages)
|
|
216
|
+
|
|
217
|
+
cache.set(cache_key, result, STARGAZER_HISTORY_TTL)
|
|
218
|
+
return result
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
async def _fetch_stargazer_history_graphql(
|
|
222
|
+
owner: str,
|
|
223
|
+
repo: str,
|
|
224
|
+
sample_pages: int,
|
|
225
|
+
) -> dict[str, Any]:
|
|
226
|
+
"""GraphQL stargazer fetch — walks cursor pagination backwards from most-recent.
|
|
227
|
+
|
|
228
|
+
The REST ``/stargazers`` endpoint caps deep pagination at ~400 pages, so
|
|
229
|
+
for a 361k-star repo we could only ever see stars #1 to #40000 — the
|
|
230
|
+
early hype window — producing the flat-then-vertical "hockey stick"
|
|
231
|
+
curve. GraphQL cursor pagination has no such cap; we simply walk backward
|
|
232
|
+
from the endpoint, collect up to ``_GRAPHQL_MAX_PAGES`` pages, and stop
|
|
233
|
+
early if we exhaust the repo's history (small repos get full lifetime).
|
|
234
|
+
"""
|
|
235
|
+
identifier = f"{owner}/{repo}"
|
|
236
|
+
variables: dict[str, Any] = {"owner": owner, "repo": repo, "cursor": None}
|
|
237
|
+
|
|
238
|
+
all_timestamps: list[str] = []
|
|
239
|
+
total_stars = 0
|
|
240
|
+
|
|
241
|
+
for _ in range(_GRAPHQL_MAX_PAGES):
|
|
242
|
+
response = await fetch_graphql(_STARGAZER_GRAPHQL_QUERY, variables, provider=PROVIDER)
|
|
243
|
+
repo_data = (response.get("data") or {}).get("repository")
|
|
244
|
+
if not repo_data:
|
|
245
|
+
# Repo doesn't exist or query errored — return empty honestly.
|
|
246
|
+
return {
|
|
247
|
+
"points": [],
|
|
248
|
+
"current_stars": 0,
|
|
249
|
+
"repo": identifier,
|
|
250
|
+
"ttl": STARGAZER_HISTORY_TTL,
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
total_stars = int(repo_data.get("stargazerCount", 0))
|
|
254
|
+
if total_stars == 0:
|
|
255
|
+
return {
|
|
256
|
+
"points": [],
|
|
257
|
+
"current_stars": 0,
|
|
258
|
+
"repo": identifier,
|
|
259
|
+
"ttl": STARGAZER_HISTORY_TTL,
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
stargazers = repo_data.get("stargazers") or {}
|
|
263
|
+
edges = stargazers.get("edges") or []
|
|
264
|
+
# GraphQL `last/before` returns edges in ASC chronological order.
|
|
265
|
+
# Prepend so the accumulated list stays sorted oldest→newest across
|
|
266
|
+
# multiple backward walks.
|
|
267
|
+
page_timestamps = [e["starredAt"] for e in edges if isinstance(e, dict) and e.get("starredAt")]
|
|
268
|
+
all_timestamps = page_timestamps + all_timestamps
|
|
269
|
+
|
|
270
|
+
page_info = stargazers.get("pageInfo") or {}
|
|
271
|
+
if not page_info.get("hasPreviousPage"):
|
|
272
|
+
break
|
|
273
|
+
variables["cursor"] = page_info.get("startCursor")
|
|
274
|
+
|
|
275
|
+
if not all_timestamps:
|
|
276
|
+
return {
|
|
277
|
+
"points": [],
|
|
278
|
+
"current_stars": total_stars,
|
|
279
|
+
"repo": identifier,
|
|
280
|
+
"ttl": STARGAZER_HISTORY_TTL,
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
points = _downsample_timestamps(all_timestamps, sample_pages, total_stars)
|
|
284
|
+
# Append honest "now" point — matches the v0.2.7 §1.4 contract.
|
|
285
|
+
points.append({"date": datetime.now(UTC).isoformat(), "count": total_stars})
|
|
286
|
+
points.sort(key=lambda p: p["date"])
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
"points": points,
|
|
290
|
+
"current_stars": total_stars,
|
|
291
|
+
"repo": identifier,
|
|
292
|
+
"ttl": STARGAZER_HISTORY_TTL,
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def _downsample_timestamps(
|
|
297
|
+
timestamps: list[str],
|
|
298
|
+
n_samples: int,
|
|
299
|
+
total_stars: int,
|
|
300
|
+
) -> list[dict[str, Any]]:
|
|
301
|
+
"""Reduce N ascending timestamps to ``n_samples`` evenly-spaced points.
|
|
302
|
+
|
|
303
|
+
The count at each sampled timestamp is computed backwards from
|
|
304
|
+
``total_stars``: since ``timestamps`` represents the most-recent
|
|
305
|
+
``len(timestamps)`` stargazers in chronological order, the final
|
|
306
|
+
timestamp corresponds to ``total_stars`` and the earliest to
|
|
307
|
+
``total_stars - (n - 1)``.
|
|
308
|
+
"""
|
|
309
|
+
n = len(timestamps)
|
|
310
|
+
if n == 0:
|
|
311
|
+
return []
|
|
312
|
+
base = total_stars - (n - 1)
|
|
313
|
+
if n <= n_samples:
|
|
314
|
+
return [{"date": ts, "count": base + idx} for idx, ts in enumerate(timestamps)]
|
|
315
|
+
|
|
316
|
+
# Pick n_samples evenly-spaced indices across [0, n-1], always including
|
|
317
|
+
# the endpoints so the curve starts and ends at the captured extremes.
|
|
318
|
+
if n_samples <= 1:
|
|
319
|
+
return [{"date": timestamps[-1], "count": total_stars}]
|
|
320
|
+
step = (n - 1) / (n_samples - 1)
|
|
321
|
+
indices = sorted({round(i * step) for i in range(n_samples)})
|
|
322
|
+
return [{"date": timestamps[idx], "count": base + idx} for idx in indices]
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
async def _fetch_stargazer_history_rest(
|
|
326
|
+
owner: str,
|
|
327
|
+
repo: str,
|
|
328
|
+
sample_pages: int = 12,
|
|
329
|
+
) -> dict[str, Any]:
|
|
330
|
+
"""REST-based stargazer sampling — the v0.2.7 behavior preserved as fallback.
|
|
331
|
+
|
|
332
|
+
Used when no ``HW_GITHUB_TOKENS`` is set or when the GraphQL path fails.
|
|
333
|
+
Samples evenly across pages ``[1, min(total_pages, 400)]`` and stamps the
|
|
334
|
+
now-point with the current UTC timestamp. Bounded by GitHub's 400-page
|
|
335
|
+
deep-pagination cap: produces a truthful but limited view of mega-repos.
|
|
336
|
+
"""
|
|
337
|
+
identifier = f"{owner}/{repo}"
|
|
338
|
+
|
|
179
339
|
# Step 1: total stars
|
|
180
340
|
repo_url = f"https://api.github.com/repos/{identifier}"
|
|
181
341
|
repo_data = await fetch_json(repo_url, provider=PROVIDER)
|
|
182
342
|
total_stars = int(repo_data.get("stargazers_count", 0))
|
|
183
343
|
if total_stars == 0:
|
|
184
|
-
|
|
344
|
+
return {
|
|
185
345
|
"points": [],
|
|
186
346
|
"current_stars": 0,
|
|
187
347
|
"repo": identifier,
|
|
188
348
|
"ttl": STARGAZER_HISTORY_TTL,
|
|
189
349
|
}
|
|
190
|
-
cache.set(cache_key, empty_result, STARGAZER_HISTORY_TTL)
|
|
191
|
-
return empty_result
|
|
192
350
|
|
|
193
351
|
# Step 2: compute total pages (clamped at GitHub's deep-pagination cap)
|
|
194
352
|
total_pages = max(1, math.ceil(total_stars / _STARGAZER_PAGE_SIZE))
|
|
195
353
|
effective_pages = min(total_pages, _STARGAZER_PAGE_CAP)
|
|
196
354
|
|
|
197
|
-
# Single-page case: repo has ≤
|
|
355
|
+
# Single-page case: repo has ≤ 100 stars. The "first starred_at of the page"
|
|
198
356
|
# sampling trick would otherwise collapse to a single aggregated point plus
|
|
199
357
|
# a duplicate-date "now" point, producing a zero time-range polyline. Use
|
|
200
358
|
# each stargazer's own timestamp instead — the whole page fits in one call.
|
|
@@ -210,14 +368,12 @@ async def fetch_stargazer_history(
|
|
|
210
368
|
for idx, entry in enumerate(page_payload):
|
|
211
369
|
if isinstance(entry, dict) and entry.get("starred_at"):
|
|
212
370
|
single_page_points.append({"date": entry["starred_at"], "count": idx + 1})
|
|
213
|
-
|
|
371
|
+
return {
|
|
214
372
|
"points": single_page_points,
|
|
215
373
|
"current_stars": total_stars,
|
|
216
374
|
"repo": identifier,
|
|
217
375
|
"ttl": STARGAZER_HISTORY_TTL,
|
|
218
376
|
}
|
|
219
|
-
cache.set(cache_key, single_page_result, STARGAZER_HISTORY_TTL)
|
|
220
|
-
return single_page_result
|
|
221
377
|
|
|
222
378
|
# Cap the sample count at the number of reachable pages.
|
|
223
379
|
sample_count = min(sample_pages, effective_pages)
|
|
@@ -264,14 +420,12 @@ async def fetch_stargazer_history(
|
|
|
264
420
|
points.append({"date": datetime.now(UTC).isoformat(), "count": total_stars})
|
|
265
421
|
points.sort(key=lambda p: p["date"])
|
|
266
422
|
|
|
267
|
-
|
|
423
|
+
return {
|
|
268
424
|
"points": points,
|
|
269
425
|
"current_stars": total_stars,
|
|
270
426
|
"repo": identifier,
|
|
271
427
|
"ttl": STARGAZER_HISTORY_TTL,
|
|
272
428
|
}
|
|
273
|
-
cache.set(cache_key, result, STARGAZER_HISTORY_TTL)
|
|
274
|
-
return result
|
|
275
429
|
|
|
276
430
|
|
|
277
431
|
# ── Session 2A+2B: contribution calendar scraping ──────────────────────────
|