hyperweave 0.2.4__tar.gz → 0.2.5__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.5/.pre-commit-config.yaml +31 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/CHANGELOG.md +6 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/PKG-INFO +2 -2
- {hyperweave-0.2.4 → hyperweave-0.2.5}/README.md +1 -1
- {hyperweave-0.2.4 → hyperweave-0.2.5}/pyproject.toml +1 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/_version.py +2 -2
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/resolvers/chart.py +3 -11
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/connectors/github.py +2 -7
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/render/chart_engine.py +96 -43
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/fixtures/session.json +1 -1
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_chart_engine.py +40 -3
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_chart_frame.py +3 -11
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_serve_live_state.py +3 -9
- {hyperweave-0.2.4 → hyperweave-0.2.5}/uv.lock +91 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/.dockerignore +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/.github/workflows/ci.yml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/.github/workflows/deploy.yml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/.github/workflows/publish.yml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/.gitignore +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/Dockerfile +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/LICENSE +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/buttons/button-liquid.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/cards/card-butterfly.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/cards/card-python.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/cards/card-sunflower.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/cards/card-waves.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/badge_critical.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/badge_passing.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/badge_warning.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/banner.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/icons/discord.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/icons/notion.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/icons/reddit.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/icons/spotify.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/icons/youtube.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/marquee_counter.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/marquee_horizontal.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/marquee_vertical.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/profile-cards/chart_stars_full.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/profile-cards/stats.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/brutalist-emerald/strip.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/badge_critical.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/badge_passing.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/badge_warning.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/banner.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/icons/bluesky.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/icons/github.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/icons/instagram.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/icons/mastodon.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/icons/x.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/marquee_counter.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/marquee_horizontal.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/marquee_vertical.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/profile-cards/chart_stars_full.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/profile-cards/stats.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/chrome-horizon/strip.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/telemetry/master_card.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/telemetry/receipt.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/examples/telemetry/rhythm_strip.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/footers/inneraura-footer-liquid.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/footers/inneraura-footer-purple.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/footers/inneraura-footer.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/hyperweave-banner.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/icons/cobalt-sapphire-discord.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/icons/cobalt-sapphire-docs.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/icons/cobalt-sapphire-github.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/icons/cobalt-sapphire-instagram.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/icons/cobalt-sapphire-linkedin.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/icons/cobalt-sapphire-tiktok.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/icons/cobalt-sapphire-x.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/icons/cobalt-sapphire-youtube.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/marquees/badge-showcase-triple.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/marquees/genome-marquee-triple.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/marquees/sample-badges.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/404.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/callout-icons.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/divider.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/favicon.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/hero-banner.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/hyperweave-banner-v2.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/hyperweave-navbar-logo.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/loader.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/mintlify-assets/og-image.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/assets/timelines/hyperweave-roadmap.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/assets/favicon.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/assets/hyperweave-banner.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/assets/hyperweave-navbar-logo.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/assets/og-image.svg +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/explanation/architecture.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/explanation/camo-compatibility.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/explanation/cim-compliance.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/explanation/genome-profile-system.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/explanation/metadata-tiers.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/how-to/add-motion-to-badges.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/how-to/create-session-receipts.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/how-to/set-up-claude-code-hooks.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/how-to/use-live-data-badges.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/introduction.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/mint.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/quickstart.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/reference/cli.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/reference/compose-spec.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/reference/genomes.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/reference/http-api.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/reference/mcp-tools.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/reference/motions.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/reference/telemetry-contract.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/spec/hyperweave-protocol.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/tutorials/build-an-artifact-kit.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/tutorials/compose-your-first-badge.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/docs/tutorials/install-session-telemetry.mdx +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/fly.toml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/hooks/install.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/hooks/session_end.sh +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/justfile +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/scripts/extract_glyphs.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/scripts/generate_hw_compliant.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/scripts/generate_proofset.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/scripts/stress_test.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/__main__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/cli.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/assembler.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/context.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/engine.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/lanes.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/resolver.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/resolvers/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/resolvers/stats.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/compose/resolvers/timeline.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/config/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/config/genome_validator.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/config/loader.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/config/registry.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/config/settings.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/connectors/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/connectors/arxiv.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/connectors/base.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/connectors/cache.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/connectors/rest.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/color.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/contracts.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/enums.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/models.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/schema.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/state.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/text.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/core/thresholds.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/css/accessibility.css +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/css/bridge.css +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/css/expression.css +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/css/phase-colors.css +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/css/status.css +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/css/telemetry.css +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/font-metrics/inter.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/fonts/jetbrains-mono.b64 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/fonts/jetbrains-mono.meta.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/fonts/orbitron.b64 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/fonts/orbitron.meta.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/genomes/brutalist-emerald.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/genomes/chrome-horizon.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/genomes/telemetry-void.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/glyphs.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/border/chromatic-pulse.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/border/corner-trace.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/border/dual-orbit.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/border/entanglement.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/border/rimrun.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/bars.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/breach.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/broadcast.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/cascade.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/collapse.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/converge.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/crash.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/drop.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/kinetic/pulse.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/motions/static.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/policies/normal.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/policies/permissive.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/policies/ungoverned.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/profiles/brutalist.contract.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/profiles/brutalist.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/profiles/chrome.contract.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/profiles/chrome.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/specimens.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/telemetry/model-pricing.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/telemetry/stage-config.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/telemetry/stage-labels.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/telemetry/tool-classes.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/telemetry/tool-colors.yaml +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/arrow.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/aurora.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/beacon.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/bracket3d.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/chevron.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/crosshair.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/diamond.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/rocket.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/rules/bar.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/rules/dashed.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/rules/five-wave.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/rules/spectral.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/rules/straight.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/rules/wave.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/data/terminals/stijl.json +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/kit.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/mcp/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/mcp/__main__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/mcp/server.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/py.typed +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/render/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/render/fonts.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/render/glyphs.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/render/motion.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/render/templates.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/serve/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/serve/app.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/telemetry/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/telemetry/capture.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/telemetry/contract.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/telemetry/corrections.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/telemetry/cost.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/telemetry/models.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/telemetry/parser.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/telemetry/stages.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/filter.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/glyph-inline.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/glyph.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/gradient.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/metadata.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/metric.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/phase-segment.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/rule.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/status.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/terminal.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/components/treemap.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/document.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/error-badge.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/badge/brutalist-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/badge/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/badge/chrome-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/badge/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/badge/default-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/badge/default-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/badge.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/banner/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/banner/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/banner/default-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/banner.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/catalog.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/chart/brutalist-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/chart/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/chart/chrome-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/chart/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/chart.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/divider.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/icon/brutalist-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/icon/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/icon/chrome-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/icon/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/icon/default-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/icon/default-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/icon.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-counter/brutalist-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-counter/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-counter/chrome-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-counter/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-counter.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-horizontal/chrome-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-horizontal/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-horizontal.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-vertical/brutalist-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-vertical/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-vertical/chrome-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-vertical/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/marquee-vertical.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/master-card.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/receipt.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/rhythm-strip.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/stats/brutalist-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/stats/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/stats/chrome-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/stats/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/stats.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/brutalist-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/brutalist-status.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/chrome-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/chrome-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/chrome-status.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/default-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/default-defs.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip/default-status.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/strip.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/timeline/default-content.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/frames/timeline.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/border/chromatic-pulse.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/border/corner-trace.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/border/dual-orbit.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/border/entanglement.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/border/rimrun.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/bars.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/breach.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/broadcast.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/cascade.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/collapse.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/converge.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/crash.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/drop.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/src/hyperweave/templates/motions/kinetic/pulse.svg.j2 +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/__init__.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/conftest.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/fixtures/github_contributions/synthetic.html +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/fixtures/session.jsonl +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_assembler.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_connectors.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_core.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_github_scrape.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_kit.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_mcp.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_paradigm_dispatch.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_proofset.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_render.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_serve.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_state_inference.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_stats_card.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_telemetry.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_telemetry_integration.py +0 -0
- {hyperweave-0.2.4 → hyperweave-0.2.5}/tests/test_timeline.py +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Runs `ruff check` + `ruff format` automatically on every `git commit`.
|
|
2
|
+
# Mirrors the two lint steps CI enforces in .github/workflows/ci.yml so CI
|
|
3
|
+
# never surfaces formatting or lint failures that local commits should catch.
|
|
4
|
+
#
|
|
5
|
+
# One-time setup after cloning:
|
|
6
|
+
# uv sync --group dev
|
|
7
|
+
# uv run pre-commit install
|
|
8
|
+
#
|
|
9
|
+
# Manual run across the whole repo:
|
|
10
|
+
# uv run pre-commit run --all-files
|
|
11
|
+
|
|
12
|
+
repos:
|
|
13
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
14
|
+
rev: v0.9.0
|
|
15
|
+
hooks:
|
|
16
|
+
- id: ruff
|
|
17
|
+
args: [--fix]
|
|
18
|
+
- id: ruff-format
|
|
19
|
+
|
|
20
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
21
|
+
rev: v5.0.0
|
|
22
|
+
hooks:
|
|
23
|
+
- id: trailing-whitespace
|
|
24
|
+
exclude: \.svg$
|
|
25
|
+
- id: end-of-file-fixer
|
|
26
|
+
exclude: \.(svg|b64)$
|
|
27
|
+
- id: check-yaml
|
|
28
|
+
- id: check-toml
|
|
29
|
+
- id: check-merge-conflict
|
|
30
|
+
- id: check-added-large-files
|
|
31
|
+
args: [--maxkb=500]
|
|
@@ -5,6 +5,12 @@ 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.5] - 2026-04-13
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Chart bezier regression on certain data ranges.** The chrome chart bezier path used horizontal tangents at every anchor, which produced a smooth curve only when input points were widely and evenly spaced. On tighter or uneven distributions — common with real GitHub stargazer data — the curve degenerated into flat-then-vertical segments. Replaced with Fritsch-Carlson monotonic cubic interpolation (the same algorithm D3's `curveMonotoneX` uses), which guarantees the curve passes through every anchor, never overshoots between points, and handles any point spacing robustly.
|
|
13
|
+
|
|
8
14
|
## [0.2.4] - 2026-04-13
|
|
9
15
|
|
|
10
16
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperweave
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
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
|
|
@@ -397,4 +397,4 @@ HyperWeave is early. If you're interested in building genomes, extending frame t
|
|
|
397
397
|
[x]: https://x.com/InnerAuraLabs
|
|
398
398
|
[youtube]: https://www.youtube.com/@InnerAuraLabs
|
|
399
399
|
|
|
400
|
-
[return-top]: https://raw.githubusercontent.com/InnerAura/hyperweave/f36c8969d15d76da4400ebcfaa04ec1e2eacb170/assets/buttons/button-liquid.svg
|
|
400
|
+
[return-top]: https://raw.githubusercontent.com/InnerAura/hyperweave/f36c8969d15d76da4400ebcfaa04ec1e2eacb170/assets/buttons/button-liquid.svg
|
|
@@ -365,4 +365,4 @@ HyperWeave is early. If you're interested in building genomes, extending frame t
|
|
|
365
365
|
[x]: https://x.com/InnerAuraLabs
|
|
366
366
|
[youtube]: https://www.youtube.com/@InnerAuraLabs
|
|
367
367
|
|
|
368
|
-
[return-top]: https://raw.githubusercontent.com/InnerAura/hyperweave/f36c8969d15d76da4400ebcfaa04ec1e2eacb170/assets/buttons/button-liquid.svg
|
|
368
|
+
[return-top]: https://raw.githubusercontent.com/InnerAura/hyperweave/f36c8969d15d76da4400ebcfaa04ec1e2eacb170/assets/buttons/button-liquid.svg
|
|
@@ -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.5'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 5)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -40,11 +40,7 @@ def resolve_chart(
|
|
|
40
40
|
# date labels at bottom, and hero value at right.
|
|
41
41
|
# Dimensions match the target SVGs in tier2/genomes/.
|
|
42
42
|
paradigm = genome.get("paradigms", {}).get("chart", "brutalist")
|
|
43
|
-
vp = (
|
|
44
|
-
Viewport(x=80, y=160, w=750, h=250)
|
|
45
|
-
if paradigm == "chrome"
|
|
46
|
-
else Viewport(x=80, y=150, w=760, h=245)
|
|
47
|
-
)
|
|
43
|
+
vp = Viewport(x=80, y=160, w=750, h=250) if paradigm == "chrome" else Viewport(x=80, y=150, w=760, h=245)
|
|
48
44
|
|
|
49
45
|
# Three-state machine. "fresh" preserved (not renamed to "live") for
|
|
50
46
|
# backward compat with the existing data-hw-status contract; "empty" is
|
|
@@ -59,12 +55,8 @@ def resolve_chart(
|
|
|
59
55
|
current_stars = 0
|
|
60
56
|
empty_message = "DATA UNAVAILABLE"
|
|
61
57
|
else:
|
|
62
|
-
current_stars = int(
|
|
63
|
-
|
|
64
|
-
)
|
|
65
|
-
raw_points = list(
|
|
66
|
-
connector.get("points") or connector.get("star_history") or []
|
|
67
|
-
)
|
|
58
|
+
current_stars = int(connector.get("current_stars") or connector.get("stars_total") or 0)
|
|
59
|
+
raw_points = list(connector.get("points") or connector.get("star_history") or [])
|
|
68
60
|
if current_stars == 0:
|
|
69
61
|
# Truthful zero-star state (brand-new repo) — render empty, don't fabricate.
|
|
70
62
|
status = "empty"
|
|
@@ -191,10 +191,7 @@ async def fetch_stargazer_history(
|
|
|
191
191
|
# a duplicate-date "now" point, producing a zero time-range polyline. Use
|
|
192
192
|
# each stargazer's own timestamp instead — the whole page fits in one call.
|
|
193
193
|
if total_pages == 1:
|
|
194
|
-
single_page_url =
|
|
195
|
-
f"https://api.github.com/repos/{identifier}/stargazers"
|
|
196
|
-
f"?per_page={_STARGAZER_PAGE_SIZE}&page=1"
|
|
197
|
-
)
|
|
194
|
+
single_page_url = f"https://api.github.com/repos/{identifier}/stargazers?per_page={_STARGAZER_PAGE_SIZE}&page=1"
|
|
198
195
|
page_payload = await fetch_json(
|
|
199
196
|
single_page_url,
|
|
200
197
|
provider=PROVIDER,
|
|
@@ -204,9 +201,7 @@ async def fetch_stargazer_history(
|
|
|
204
201
|
if isinstance(page_payload, list):
|
|
205
202
|
for idx, entry in enumerate(page_payload):
|
|
206
203
|
if isinstance(entry, dict) and entry.get("starred_at"):
|
|
207
|
-
single_page_points.append(
|
|
208
|
-
{"date": entry["starred_at"], "count": idx + 1}
|
|
209
|
-
)
|
|
204
|
+
single_page_points.append({"date": entry["starred_at"], "count": idx + 1})
|
|
210
205
|
single_page_result: dict[str, Any] = {
|
|
211
206
|
"points": single_page_points,
|
|
212
207
|
"current_stars": total_stars,
|
|
@@ -136,11 +136,7 @@ def _project_points(
|
|
|
136
136
|
for i, p in enumerate(points):
|
|
137
137
|
# When all timestamps are identical (t_span <= 0), distribute points
|
|
138
138
|
# evenly by index rather than collapsing them all to vp.x.
|
|
139
|
-
frac_t = (
|
|
140
|
-
i / max(1, n - 1)
|
|
141
|
-
if t_span <= 0
|
|
142
|
-
else (p.date.timestamp() - t0) / t_span
|
|
143
|
-
)
|
|
139
|
+
frac_t = i / max(1, n - 1) if t_span <= 0 else (p.date.timestamp() - t0) / t_span
|
|
144
140
|
frac_v = (p.value - v_lo) / v_span
|
|
145
141
|
px = vp.x + round(frac_t * vp.w)
|
|
146
142
|
py = vp.y + vp.h - round(frac_v * vp.h)
|
|
@@ -157,30 +153,100 @@ def _build_polyline_points(projected: list[tuple[int, int]]) -> str:
|
|
|
157
153
|
|
|
158
154
|
|
|
159
155
|
def _build_bezier_path(projected: list[tuple[int, int]]) -> str:
|
|
160
|
-
"""Build a smooth cubic bezier path
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
156
|
+
"""Build a smooth cubic bezier path using Fritsch-Carlson monotonic cubic interpolation.
|
|
157
|
+
|
|
158
|
+
This is the same curve D3 renders via ``curveMonotoneX``. For data with
|
|
159
|
+
monotonically increasing x-coordinates (e.g. any time-series chart like
|
|
160
|
+
star history), the curve is guaranteed to:
|
|
161
|
+
|
|
162
|
+
- Pass through every anchor point (C0 continuity).
|
|
163
|
+
- Be C1-continuous (smooth tangent at every anchor).
|
|
164
|
+
- Be monotonic wherever the input is monotonic (no dips between rising
|
|
165
|
+
points).
|
|
166
|
+
- Not overshoot — control handles stay within their segment in x,
|
|
167
|
+
regardless of uneven x-spacing.
|
|
168
|
+
|
|
169
|
+
The previous implementation placed horizontal control handles at every
|
|
170
|
+
anchor (``c1y = y_prev``, ``c2y = y_cur``). That shape produced two
|
|
171
|
+
visual artifacts on real data:
|
|
172
|
+
|
|
173
|
+
1. **Flat-then-vertical** for bursty growth — horizontal tangents forced
|
|
174
|
+
each segment into a plateau → S-curve → plateau shape, so the chart
|
|
175
|
+
read as flat sections punctuated by sharp rises.
|
|
176
|
+
|
|
177
|
+
2. **Self-intersecting segments** when two adjacent anchors were close
|
|
178
|
+
in x — the hard-coded ``dx = max(4, (x_cur - x_prev) // 3)`` produced
|
|
179
|
+
``c2.x < c1.x``, rasterizing badly on mobile/Camo.
|
|
180
|
+
|
|
181
|
+
Fritsch-Carlson solves both by computing per-segment slopes, deriving a
|
|
182
|
+
tangent at each point from the neighboring slopes, and then rescaling
|
|
183
|
+
tangent magnitudes with the ``α² + β² > 9`` test so control handles
|
|
184
|
+
never extend past their segment.
|
|
185
|
+
|
|
186
|
+
References:
|
|
187
|
+
Fritsch, F. N.; Carlson, R. E. (1980). "Monotone Piecewise Cubic
|
|
188
|
+
Interpolation". SIAM Journal on Numerical Analysis. 17 (2): 238-246.
|
|
166
189
|
"""
|
|
167
|
-
|
|
190
|
+
n = len(projected)
|
|
191
|
+
if n == 0:
|
|
168
192
|
return ""
|
|
169
|
-
if
|
|
193
|
+
if n == 1:
|
|
170
194
|
x, y = projected[0]
|
|
171
195
|
return f"M{x},{y}"
|
|
172
|
-
|
|
196
|
+
if n == 2:
|
|
197
|
+
# Two points → straight-line bezier (no interior tangents to compute).
|
|
198
|
+
x0, y0 = projected[0]
|
|
199
|
+
x1, y1 = projected[1]
|
|
200
|
+
dx = (x1 - x0) / 3
|
|
201
|
+
c1x, c1y = round(x0 + dx), y0
|
|
202
|
+
c2x, c2y = round(x1 - dx), y1
|
|
203
|
+
return f"M{x0},{y0} C{c1x},{c1y} {c2x},{c2y} {x1},{y1}"
|
|
204
|
+
|
|
205
|
+
# 1. Per-segment slopes m_i = (y_{i+1} - y_i) / (x_{i+1} - x_i).
|
|
206
|
+
slopes: list[float] = []
|
|
207
|
+
for i in range(n - 1):
|
|
208
|
+
sx = projected[i + 1][0] - projected[i][0]
|
|
209
|
+
sy = projected[i + 1][1] - projected[i][1]
|
|
210
|
+
slopes.append(sy / sx if sx != 0 else 0.0)
|
|
211
|
+
|
|
212
|
+
# 2. Initial tangents at each anchor. Endpoints use the one adjacent slope;
|
|
213
|
+
# interior points use the average of the two adjacent slopes, but set to 0
|
|
214
|
+
# at turning points (where the two slopes have opposite sign).
|
|
215
|
+
tangents: list[float] = [0.0] * n
|
|
216
|
+
tangents[0] = slopes[0]
|
|
217
|
+
tangents[-1] = slopes[-1]
|
|
218
|
+
for i in range(1, n - 1):
|
|
219
|
+
if slopes[i - 1] * slopes[i] > 0:
|
|
220
|
+
tangents[i] = (slopes[i - 1] + slopes[i]) / 2
|
|
221
|
+
# else: turning point → tangent stays 0
|
|
222
|
+
|
|
223
|
+
# 3. Fritsch-Carlson overshoot prevention. For each segment, if the
|
|
224
|
+
# (alpha, beta) pair falls outside the monotonicity circle of radius 3,
|
|
225
|
+
# rescale both tangents by tau = 3 / sqrt(alpha^2 + beta^2).
|
|
226
|
+
for i in range(n - 1):
|
|
227
|
+
if slopes[i] == 0:
|
|
228
|
+
tangents[i] = 0.0
|
|
229
|
+
tangents[i + 1] = 0.0
|
|
230
|
+
continue
|
|
231
|
+
alpha = tangents[i] / slopes[i]
|
|
232
|
+
beta = tangents[i + 1] / slopes[i]
|
|
233
|
+
if alpha * alpha + beta * beta > 9:
|
|
234
|
+
tau = 3.0 / (alpha * alpha + beta * beta) ** 0.5
|
|
235
|
+
tangents[i] = tau * alpha * slopes[i]
|
|
236
|
+
tangents[i + 1] = tau * beta * slopes[i]
|
|
237
|
+
|
|
238
|
+
# 4. Convert tangents to Bezier control points. For each segment, the
|
|
239
|
+
# control x-offset is 1/3 of segment width; the y-offset is that same
|
|
240
|
+
# 1/3 width scaled by the anchor's tangent (slope).
|
|
173
241
|
parts: list[str] = [f"M{projected[0][0]},{projected[0][1]}"]
|
|
174
|
-
n
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
x_cur
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
c2x = x_cur - dx
|
|
183
|
-
c2y = y_cur
|
|
242
|
+
for i in range(n - 1):
|
|
243
|
+
x_prev, y_prev = projected[i]
|
|
244
|
+
x_cur, y_cur = projected[i + 1]
|
|
245
|
+
seg_dx = (x_cur - x_prev) / 3
|
|
246
|
+
c1x = round(x_prev + seg_dx)
|
|
247
|
+
c1y = round(y_prev + tangents[i] * seg_dx)
|
|
248
|
+
c2x = round(x_cur - seg_dx)
|
|
249
|
+
c2y = round(y_cur - tangents[i + 1] * seg_dx)
|
|
184
250
|
parts.append(f"C{c1x},{c1y} {c2x},{c2y} {x_cur},{y_cur}")
|
|
185
251
|
return " ".join(parts)
|
|
186
252
|
|
|
@@ -413,9 +479,7 @@ def _format_y_tick(value: int) -> str:
|
|
|
413
479
|
return f"{s}K"
|
|
414
480
|
|
|
415
481
|
|
|
416
|
-
def _build_y_labels(
|
|
417
|
-
ticks: list[int], v_min: int, v_max: int, vp: Viewport
|
|
418
|
-
) -> list[dict[str, Any]]:
|
|
482
|
+
def _build_y_labels(ticks: list[int], v_min: int, v_max: int, vp: Viewport) -> list[dict[str, Any]]:
|
|
419
483
|
"""Project tick values into ``{y, text}`` dicts for template consumption.
|
|
420
484
|
|
|
421
485
|
Uses the same (v_min, v_max) range the caller passes to
|
|
@@ -433,9 +497,7 @@ def _build_y_labels(
|
|
|
433
497
|
return out
|
|
434
498
|
|
|
435
499
|
|
|
436
|
-
def _build_x_year_labels(
|
|
437
|
-
points: list[ChartPoint], vp: Viewport
|
|
438
|
-
) -> list[dict[str, Any]]:
|
|
500
|
+
def _build_x_year_labels(points: list[ChartPoint], vp: Viewport) -> list[dict[str, Any]]:
|
|
439
501
|
"""Return year-string labels positioned at jan-1 boundaries in the data range.
|
|
440
502
|
|
|
441
503
|
Matches star-history.com's convention: just year numbers (2024, 2025, 2026)
|
|
@@ -454,9 +516,7 @@ def _build_x_year_labels(
|
|
|
454
516
|
t1 = points[-1].date.timestamp()
|
|
455
517
|
t_span = max(1.0, t1 - t0)
|
|
456
518
|
|
|
457
|
-
labels: list[dict[str, Any]] = [
|
|
458
|
-
{"x": vp.x, "text": str(y_start), "anchor": "start"}
|
|
459
|
-
]
|
|
519
|
+
labels: list[dict[str, Any]] = [{"x": vp.x, "text": str(y_start), "anchor": "start"}]
|
|
460
520
|
for y in range(y_start + 1, y_end + 1):
|
|
461
521
|
jan1 = datetime(y, 1, 1, tzinfo=UTC).timestamp()
|
|
462
522
|
if t0 < jan1 <= t1:
|
|
@@ -489,9 +549,7 @@ def _build_empty_state(vp: Viewport, message: str) -> str:
|
|
|
489
549
|
)
|
|
490
550
|
|
|
491
551
|
|
|
492
|
-
def _build_gridlines_from_ticks(
|
|
493
|
-
y_labels: list[dict[str, Any]], vp: Viewport
|
|
494
|
-
) -> str:
|
|
552
|
+
def _build_gridlines_from_ticks(y_labels: list[dict[str, Any]], vp: Viewport) -> str:
|
|
495
553
|
"""Horizontal gridlines at each Y-tick's Y-position.
|
|
496
554
|
|
|
497
555
|
Replaces the uniform ``_build_gridlines`` when real data is present — so
|
|
@@ -501,10 +559,7 @@ def _build_gridlines_from_ticks(
|
|
|
501
559
|
lines: list[str] = []
|
|
502
560
|
for label in y_labels:
|
|
503
561
|
y = int(label["y"])
|
|
504
|
-
lines.append(
|
|
505
|
-
f'<line x1="{vp.x}" y1="{y}" x2="{vp.x + vp.w}" y2="{y}" '
|
|
506
|
-
f'class="hw-chart-gridline"/>'
|
|
507
|
-
)
|
|
562
|
+
lines.append(f'<line x1="{vp.x}" y1="{y}" x2="{vp.x + vp.w}" y2="{y}" class="hw-chart-gridline"/>')
|
|
508
563
|
return "".join(lines)
|
|
509
564
|
|
|
510
565
|
|
|
@@ -621,9 +676,7 @@ def build_chart_svg(
|
|
|
621
676
|
# Empty state overlay: only when there are no data points AND a message
|
|
622
677
|
# was provided. Without a message the chart degrades silently (useful for
|
|
623
678
|
# embedded charts in stats.py that don't need a user-facing label).
|
|
624
|
-
empty_state_fragment = (
|
|
625
|
-
_build_empty_state(viewport, empty_message or "") if not points else ""
|
|
626
|
-
)
|
|
679
|
+
empty_state_fragment = _build_empty_state(viewport, empty_message or "") if not points else ""
|
|
627
680
|
|
|
628
681
|
return {
|
|
629
682
|
"defs": "",
|
|
@@ -140,6 +140,45 @@ def test_build_bezier_path_starts_with_M() -> None:
|
|
|
140
140
|
assert "C" in out # cubic bezier control points present
|
|
141
141
|
|
|
142
142
|
|
|
143
|
+
def test_build_bezier_path_no_degenerate_segments_on_close_points() -> None:
|
|
144
|
+
"""When adjacent anchors are close in x, control handles must not cross.
|
|
145
|
+
|
|
146
|
+
Regression for the chrome "flat-then-vertical" bug: the previous
|
|
147
|
+
horizontal-handle implementation used ``dx = max(4, (x_cur - x_prev) // 3)``,
|
|
148
|
+
which produced ``c2.x < c1.x`` when points were close. Catmull-Rom tangents
|
|
149
|
+
scale with local chord length and avoid this.
|
|
150
|
+
"""
|
|
151
|
+
import re
|
|
152
|
+
|
|
153
|
+
# Points clustered tightly in x (simulates slow-growth early period).
|
|
154
|
+
points = [(80, 410), (81, 390), (88, 368), (103, 348), (128, 325), (830, 169)]
|
|
155
|
+
path = _build_bezier_path(points)
|
|
156
|
+
segments = re.findall(r"C(\d+),(\d+) (\d+),(\d+) (\d+),(\d+)", path)
|
|
157
|
+
assert len(segments) == len(points) - 1
|
|
158
|
+
for c1x, _, c2x, _, _, _ in segments:
|
|
159
|
+
assert int(c2x) >= int(c1x), f"degenerate segment: c1x={c1x}, c2x={c2x} (c2 must not precede c1)"
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_build_bezier_path_tangents_follow_neighbor_slope() -> None:
|
|
163
|
+
"""Tangents should respect data slope — not force horizontal tangent at every anchor.
|
|
164
|
+
|
|
165
|
+
With the old horizontal-handle approach, the first segment's c1 always had
|
|
166
|
+
``c1.y == y_prev``. For data that rises, the new Catmull-Rom code shifts c1
|
|
167
|
+
toward the next point's y, producing a non-horizontal start.
|
|
168
|
+
"""
|
|
169
|
+
# Rising data: y decreases (flipped SVG coords mean smaller y = higher on chart).
|
|
170
|
+
points = [(0, 400), (100, 300), (200, 200), (300, 100)]
|
|
171
|
+
path = _build_bezier_path(points)
|
|
172
|
+
import re
|
|
173
|
+
|
|
174
|
+
first_segment = re.match(r"M0,400 C(\d+),(\d+)", path)
|
|
175
|
+
assert first_segment is not None
|
|
176
|
+
c1y = int(first_segment.group(2))
|
|
177
|
+
# Old code produced c1y == 400 (horizontal tangent). New code should
|
|
178
|
+
# tilt toward y_next=300, so c1y < 400.
|
|
179
|
+
assert c1y < 400, f"expected tangent to tilt upward, got c1y={c1y}"
|
|
180
|
+
|
|
181
|
+
|
|
143
182
|
def test_build_area_polygon_closes_to_baseline() -> None:
|
|
144
183
|
pts = [(10, 50), (30, 30), (50, 20)]
|
|
145
184
|
out = _build_area_polygon_points(pts, baseline_y=100)
|
|
@@ -285,9 +324,7 @@ def test_build_chart_svg_empty_with_message_renders_overlay(
|
|
|
285
324
|
sample_viewport: Viewport,
|
|
286
325
|
) -> None:
|
|
287
326
|
"""Zero-data path with an empty_message renders a centered overlay label."""
|
|
288
|
-
result = build_chart_svg(
|
|
289
|
-
[], sample_viewport, structural={}, empty_message="NEW REPO · NO STARS YET"
|
|
290
|
-
)
|
|
327
|
+
result = build_chart_svg([], sample_viewport, structural={}, empty_message="NEW REPO · NO STARS YET")
|
|
291
328
|
assert "NEW REPO" in result["empty_state"]
|
|
292
329
|
assert 'data-hw-zone="empty-state"' in result["empty_state"]
|
|
293
330
|
|
|
@@ -118,10 +118,7 @@ def test_chart_six_stars_renders_real_polyline_with_derived_labels() -> None:
|
|
|
118
118
|
timestamps yield distinct x-coordinates, and the derived Y ticks show
|
|
119
119
|
[0, 2, 4, 6] — never the hardcoded "3K".
|
|
120
120
|
"""
|
|
121
|
-
points = [
|
|
122
|
-
{"date": f"2025-{m:02d}-01T00:00:00Z", "count": i + 1}
|
|
123
|
-
for i, m in enumerate((1, 3, 5, 7, 9, 11))
|
|
124
|
-
]
|
|
121
|
+
points = [{"date": f"2025-{m:02d}-01T00:00:00Z", "count": i + 1} for i, m in enumerate((1, 3, 5, 7, 9, 11))]
|
|
125
122
|
spec = ComposeSpec(
|
|
126
123
|
type="chart",
|
|
127
124
|
genome_id="brutalist-emerald",
|
|
@@ -167,15 +164,10 @@ async def test_fetch_stargazer_history_single_page_uses_per_stargazer_timestamps
|
|
|
167
164
|
if url.endswith("/repos/jiahongc/cc-companion"):
|
|
168
165
|
return {"stargazers_count": 6}
|
|
169
166
|
if "page=1" in url:
|
|
170
|
-
return [
|
|
171
|
-
{"starred_at": f"2025-0{m}-01T00:00:00Z"}
|
|
172
|
-
for m in range(1, 7)
|
|
173
|
-
]
|
|
167
|
+
return [{"starred_at": f"2025-0{m}-01T00:00:00Z"} for m in range(1, 7)]
|
|
174
168
|
return {}
|
|
175
169
|
|
|
176
|
-
with patch(
|
|
177
|
-
"hyperweave.connectors.github.fetch_json", side_effect=fake_fetch_json
|
|
178
|
-
):
|
|
170
|
+
with patch("hyperweave.connectors.github.fetch_json", side_effect=fake_fetch_json):
|
|
179
171
|
result = await fetch_stargazer_history("jiahongc", "cc-companion")
|
|
180
172
|
|
|
181
173
|
assert result["current_stars"] == 6
|
|
@@ -53,24 +53,18 @@ async def test_badge_route_infers_passing_state(client: AsyncClient) -> None:
|
|
|
53
53
|
|
|
54
54
|
async def test_badge_route_explicit_state_wins(client: AsyncClient) -> None:
|
|
55
55
|
"""?state=passing must override the "failing" value inference."""
|
|
56
|
-
resp = await client.get(
|
|
57
|
-
"/v1/badge/build/failing/brutalist-emerald.static?state=passing"
|
|
58
|
-
)
|
|
56
|
+
resp = await client.get("/v1/badge/build/failing/brutalist-emerald.static?state=passing")
|
|
59
57
|
assert resp.status_code == 200
|
|
60
58
|
assert _root_status(resp.text) == "passing"
|
|
61
59
|
|
|
62
60
|
|
|
63
61
|
async def test_badge_route_percentage_ladder(client: AsyncClient) -> None:
|
|
64
62
|
"""Coverage 95%% should infer passing; 50%% should infer critical."""
|
|
65
|
-
resp_high = await client.get(
|
|
66
|
-
"/v1/badge/coverage/95%25/brutalist-emerald.static"
|
|
67
|
-
)
|
|
63
|
+
resp_high = await client.get("/v1/badge/coverage/95%25/brutalist-emerald.static")
|
|
68
64
|
assert resp_high.status_code == 200
|
|
69
65
|
assert _root_status(resp_high.text) == "passing"
|
|
70
66
|
|
|
71
|
-
resp_low = await client.get(
|
|
72
|
-
"/v1/badge/coverage/50%25/brutalist-emerald.static"
|
|
73
|
-
)
|
|
67
|
+
resp_low = await client.get("/v1/badge/coverage/50%25/brutalist-emerald.static")
|
|
74
68
|
assert resp_low.status_code == 200
|
|
75
69
|
assert _root_status(resp_low.text) == "critical"
|
|
76
70
|
|
|
@@ -171,6 +171,15 @@ wheels = [
|
|
|
171
171
|
{ url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" },
|
|
172
172
|
]
|
|
173
173
|
|
|
174
|
+
[[package]]
|
|
175
|
+
name = "cfgv"
|
|
176
|
+
version = "3.5.0"
|
|
177
|
+
source = { registry = "https://pypi.org/simple" }
|
|
178
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" }
|
|
179
|
+
wheels = [
|
|
180
|
+
{ url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" },
|
|
181
|
+
]
|
|
182
|
+
|
|
174
183
|
[[package]]
|
|
175
184
|
name = "click"
|
|
176
185
|
version = "8.3.1"
|
|
@@ -344,6 +353,15 @@ wheels = [
|
|
|
344
353
|
{ url = "https://files.pythonhosted.org/packages/06/06/d68a5d5d292c2ad2bc6a02e5ca2cb1bb9c15e941ab02f004a06a342d7f0f/cyclopts-4.10.0-py3-none-any.whl", hash = "sha256:50f333382a60df8d40ec14aa2e627316b361c4f478598ada1f4169d959bf9ea7", size = 204097, upload-time = "2026-03-14T14:09:32.504Z" },
|
|
345
354
|
]
|
|
346
355
|
|
|
356
|
+
[[package]]
|
|
357
|
+
name = "distlib"
|
|
358
|
+
version = "0.4.0"
|
|
359
|
+
source = { registry = "https://pypi.org/simple" }
|
|
360
|
+
sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" }
|
|
361
|
+
wheels = [
|
|
362
|
+
{ url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" },
|
|
363
|
+
]
|
|
364
|
+
|
|
347
365
|
[[package]]
|
|
348
366
|
name = "dnspython"
|
|
349
367
|
version = "2.8.0"
|
|
@@ -453,6 +471,15 @@ wheels = [
|
|
|
453
471
|
{ url = "https://files.pythonhosted.org/packages/70/ea/570122de7e24f72138d006f799768e14cc1ccf7fcb22b7750b2bd276c711/fastmcp-3.1.1-py3-none-any.whl", hash = "sha256:8132ba069d89f14566b3266919d6d72e2ec23dd45d8944622dca407e9beda7eb", size = 633754, upload-time = "2026-03-14T19:12:22.736Z" },
|
|
454
472
|
]
|
|
455
473
|
|
|
474
|
+
[[package]]
|
|
475
|
+
name = "filelock"
|
|
476
|
+
version = "3.25.2"
|
|
477
|
+
source = { registry = "https://pypi.org/simple" }
|
|
478
|
+
sdist = { url = "https://files.pythonhosted.org/packages/94/b8/00651a0f559862f3bb7d6f7477b192afe3f583cc5e26403b44e59a55ab34/filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", size = 40480, upload-time = "2026-03-11T20:45:38.487Z" }
|
|
479
|
+
wheels = [
|
|
480
|
+
{ url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" },
|
|
481
|
+
]
|
|
482
|
+
|
|
456
483
|
[[package]]
|
|
457
484
|
name = "h11"
|
|
458
485
|
version = "0.16.0"
|
|
@@ -546,6 +573,7 @@ dependencies = [
|
|
|
546
573
|
[package.dev-dependencies]
|
|
547
574
|
dev = [
|
|
548
575
|
{ name = "mypy" },
|
|
576
|
+
{ name = "pre-commit" },
|
|
549
577
|
{ name = "pytest" },
|
|
550
578
|
{ name = "pytest-asyncio" },
|
|
551
579
|
{ name = "pytest-cov" },
|
|
@@ -574,6 +602,7 @@ requires-dist = [
|
|
|
574
602
|
[package.metadata.requires-dev]
|
|
575
603
|
dev = [
|
|
576
604
|
{ name = "mypy", specifier = ">=1.14" },
|
|
605
|
+
{ name = "pre-commit", specifier = ">=4.0" },
|
|
577
606
|
{ name = "pytest", specifier = ">=8.0" },
|
|
578
607
|
{ name = "pytest-asyncio", specifier = ">=0.24" },
|
|
579
608
|
{ name = "pytest-cov", specifier = ">=6.0" },
|
|
@@ -586,6 +615,15 @@ dev = [
|
|
|
586
615
|
{ name = "types-pyyaml", specifier = ">=6.0.12.20250915" },
|
|
587
616
|
]
|
|
588
617
|
|
|
618
|
+
[[package]]
|
|
619
|
+
name = "identify"
|
|
620
|
+
version = "2.6.18"
|
|
621
|
+
source = { registry = "https://pypi.org/simple" }
|
|
622
|
+
sdist = { url = "https://files.pythonhosted.org/packages/46/c4/7fb4db12296cdb11893d61c92048fe617ee853f8523b9b296ac03b43757e/identify-2.6.18.tar.gz", hash = "sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd", size = 99580, upload-time = "2026-03-15T18:39:50.319Z" }
|
|
623
|
+
wheels = [
|
|
624
|
+
{ url = "https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl", hash = "sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737", size = 99394, upload-time = "2026-03-15T18:39:48.915Z" },
|
|
625
|
+
]
|
|
626
|
+
|
|
589
627
|
[[package]]
|
|
590
628
|
name = "idna"
|
|
591
629
|
version = "3.11"
|
|
@@ -957,6 +995,15 @@ wheels = [
|
|
|
957
995
|
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
|
|
958
996
|
]
|
|
959
997
|
|
|
998
|
+
[[package]]
|
|
999
|
+
name = "nodeenv"
|
|
1000
|
+
version = "1.10.0"
|
|
1001
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1002
|
+
sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" }
|
|
1003
|
+
wheels = [
|
|
1004
|
+
{ url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" },
|
|
1005
|
+
]
|
|
1006
|
+
|
|
960
1007
|
[[package]]
|
|
961
1008
|
name = "openapi-pydantic"
|
|
962
1009
|
version = "0.5.1"
|
|
@@ -1027,6 +1074,22 @@ wheels = [
|
|
|
1027
1074
|
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
1028
1075
|
]
|
|
1029
1076
|
|
|
1077
|
+
[[package]]
|
|
1078
|
+
name = "pre-commit"
|
|
1079
|
+
version = "4.5.1"
|
|
1080
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1081
|
+
dependencies = [
|
|
1082
|
+
{ name = "cfgv" },
|
|
1083
|
+
{ name = "identify" },
|
|
1084
|
+
{ name = "nodeenv" },
|
|
1085
|
+
{ name = "pyyaml" },
|
|
1086
|
+
{ name = "virtualenv" },
|
|
1087
|
+
]
|
|
1088
|
+
sdist = { url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" }
|
|
1089
|
+
wheels = [
|
|
1090
|
+
{ url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" },
|
|
1091
|
+
]
|
|
1092
|
+
|
|
1030
1093
|
[[package]]
|
|
1031
1094
|
name = "py-key-value-aio"
|
|
1032
1095
|
version = "0.4.4"
|
|
@@ -1304,6 +1367,19 @@ wheels = [
|
|
|
1304
1367
|
{ url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" },
|
|
1305
1368
|
]
|
|
1306
1369
|
|
|
1370
|
+
[[package]]
|
|
1371
|
+
name = "python-discovery"
|
|
1372
|
+
version = "1.2.2"
|
|
1373
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1374
|
+
dependencies = [
|
|
1375
|
+
{ name = "filelock" },
|
|
1376
|
+
{ name = "platformdirs" },
|
|
1377
|
+
]
|
|
1378
|
+
sdist = { url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb", size = 58872, upload-time = "2026-04-07T17:28:49.249Z" }
|
|
1379
|
+
wheels = [
|
|
1380
|
+
{ url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a", size = 31894, upload-time = "2026-04-07T17:28:48.09Z" },
|
|
1381
|
+
]
|
|
1382
|
+
|
|
1307
1383
|
[[package]]
|
|
1308
1384
|
name = "python-dotenv"
|
|
1309
1385
|
version = "1.2.2"
|
|
@@ -1706,6 +1782,21 @@ wheels = [
|
|
|
1706
1782
|
{ url = "https://files.pythonhosted.org/packages/e4/16/c1fd27e9549f3c4baf1dc9c20c456cd2f822dbf8de9f463824b0c0357e06/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6cde23eeda1a25c75b2e07d39970f3374105d5eafbaab2a4482be82f272d5a5e", size = 4296730, upload-time = "2025-10-16T22:17:00.744Z" },
|
|
1707
1783
|
]
|
|
1708
1784
|
|
|
1785
|
+
[[package]]
|
|
1786
|
+
name = "virtualenv"
|
|
1787
|
+
version = "21.2.1"
|
|
1788
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1789
|
+
dependencies = [
|
|
1790
|
+
{ name = "distlib" },
|
|
1791
|
+
{ name = "filelock" },
|
|
1792
|
+
{ name = "platformdirs" },
|
|
1793
|
+
{ name = "python-discovery" },
|
|
1794
|
+
]
|
|
1795
|
+
sdist = { url = "https://files.pythonhosted.org/packages/97/c5/aff062c66b42e2183201a7ace10c6b2e959a9a16525c8e8ca8e59410d27a/virtualenv-21.2.1.tar.gz", hash = "sha256:b66ffe81301766c0d5e2208fc3576652c59d44e7b731fc5f5ed701c9b537fa78", size = 5844770, upload-time = "2026-04-09T18:47:11.482Z" }
|
|
1796
|
+
wheels = [
|
|
1797
|
+
{ url = "https://files.pythonhosted.org/packages/20/0e/f083a76cb590e60dff3868779558eefefb8dfb7c9ed020babc7aa014ccbf/virtualenv-21.2.1-py3-none-any.whl", hash = "sha256:bd16b49c53562b28cf1a3ad2f36edb805ad71301dee70ddc449e5c88a9f919a2", size = 5828326, upload-time = "2026-04-09T18:47:09.331Z" },
|
|
1798
|
+
]
|
|
1799
|
+
|
|
1709
1800
|
[[package]]
|
|
1710
1801
|
name = "watchfiles"
|
|
1711
1802
|
version = "1.1.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|