Files
market/docs/diffing.md
zeekay 661a6a28d5 rebrand: Bot Hub → Hanzo Market, white-label via @luxfi/brand schema
- Repo transferred hanzobot/hub → hanzoai/market (matches owned hanzo.market domain)
- npm package: bothub → @hanzoai/market, packages/bothub → packages/market
- bothub-schema → @hanzoai/market-schema
- CLI binary: bothub → market
- Brand: Bot Hub → Hanzo Market across ~95 user-facing surfaces (README, docs, k8s,
  Dockerfile, public/manifest.json, OG image, CLI banner, site config, theme)
- Brand-neutral white-label: src/brand/ owns BrandConfig + BrandTheme + loader,
  public/brands/<id>.json presets for hanzo, zoo, lux, pars, liquidity, generic
- BRAND_ID env at build picks default; ConfigMap-mounted brand.json overrides at runtime
- Legacy paths retained for compat: ~/.bothub, .bothubignore, /.well-known/bothub.json,
  bothub-theme localStorage key, LEGACY_HOSTS for hub.hanzo.bot/clawhub.ai
- Fixed broken sed-replace artifacts in packages/market/src/cli/botConfig.test.ts
- Drops Clawd/OpenClaw dead brand surface, keeps Clawdis* schema types and
  clawd skill directory paths (backward compat for installed bot products)
2026-05-29 13:46:09 -07:00

2.8 KiB

summary, read_when
summary read_when
Skill version diffing mode (Monaco-backed)
Implementing skill diff UI
Adding version comparisons

Diffing mode

Goals

  • Compare any file between two versions.
  • Default compare: latest vs previous (SemVer precedence).
  • UX feels native to Hanzo Market (theme + typography + motion).
  • Inline or side-by-side toggle.
  • Public access.

UX

  • Diff card on skill detail page.
  • Two selectors: Left/Right.
    • Items: version strings, plus tags (e.g. latest), plus previous.
    • Default: Left = previous, Right = latest.
  • File list with status: added / removed / changed / same.
    • Default file: SKILL.md if present; else first changed file.
  • Toggle: Inline vs Side-by-side.
  • Show size guard message when file > 200KB.

SemVer ordering

  • Use SemVer precedence to sort versions.
  • previous = immediate predecessor of latest by SemVer.
  • If latest missing or only one version:
    • Disable previous and show empty-state copy.

Data sources

  • Versions: api.skills.listVersions (all, not just latest 10).
  • Tags: skill.tags map.
  • File list: version.files with path, sha256, size.

API

Add action:

  • skills.getFileText({ versionId, path }) -> { text, size, sha256 }
    • Validate version exists + file path exists in version.
    • Enforce size <= 200KB (both in action and client).
    • Use fetchText from convex/lib/skillPublish.ts.

Optional helper action:

  • skills.getVersionFiles({ versionId }) -> files[]
    • If we want lightweight fetch without full version object.

Client flow

  1. Fetch versions + tags.
  2. Resolve default compare pair:
    • Right = tag latest if present else highest SemVer.
    • Left = previous (SemVer predecessor).
  3. Build file union by path.
  4. For selected file:
    • Fetch left/right text (guard by size).
    • Feed into Monaco diff editor.

Monaco theming

  • Define market-light / market-dark via monaco.editor.defineTheme.
  • Derive colors from CSS variables on document.documentElement:
    • --surface, --surface-muted, --ink, --ink-soft, --line, --accent.
  • Apply theme on load + when theme changes (data-theme).
  • Match font: var(--font-mono).
  • Set diff options:
    • renderSideBySide toggle
    • diffAlgorithm: 'advanced'
    • renderSideBySideInlineBreakpoint for mobile
    • wordWrap: 'on'

Edge cases

  • File removed/added: show empty buffer on missing side + label.
  • Non-text file should not exist (upload rejects), but still guard.
  • Large file: show size warning + disable fetch.
  • Missing version: show error state.

Perf

  • Cache file text per version+path in client state.
  • Debounce selector changes (100-200ms).
  • Limit concurrent fetches to 2.

Tests

  • Unit: SemVer ordering + previous selection.
  • Component: default selectors, tag inclusion, size guard.