Skip to content

Skill Registry with rolling leaderboards - #597

Open
QuanCheng-QC wants to merge 5 commits into
developfrom
feature/skill-registry-mvp
Open

Skill Registry with rolling leaderboards#597
QuanCheng-QC wants to merge 5 commits into
developfrom
feature/skill-registry-mvp

Conversation

@QuanCheng-QC

@QuanCheng-QC QuanCheng-QC commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Skill Registry with rolling leaderboards

18 files changed, +3764 / -35, 5 commits.

Why this change

Product feedback from the team lead on the size and usability of the Skill ecosystem:

  • User-provided custom Skills are limited to the Workspace they were uploaded into, so other users cannot discover or reuse them.
  • Authors should be able to publish a Skill; other users should be able to install it, fork it, inspect its version history, and see original-author attribution.
  • Weekly or monthly "best Skill" rankings would help good work surface.
  • The current Skill inventory is not competitive with other vendors, so the built-in catalog and future user-generated Skills need a shared, extensible registry.

The branch went through several rounds of review focused on publication security, namespace impersonation, version-install correctness, backward compatibility for installed built-in Skills, and regressions caused by moving the catalog into the Registry.

Suggested reading order

The diff is large; this order makes it tractable:

  1. workspace/backend/alembic/versions/030_add_skill_registry_mvp.py — the data model
  2. workspace/backend/alembic/versions/031_add_skill_activity_events.py — the ranking signal stream
  3. workspace/backend/app/skill_registry.py — shared helpers, catalog sync, publication scanning, activity recording
  4. workspace/backend/app/routers/registry.py — search, leaderboard, detail, download, publish, fork, moderation
  5. workspace/backend/app/routers/workspaces.py — diff only: install / uninstall / list / register / private versions
  6. workspace/frontend/components/skills/skills-view.tsx — Skill Hub
  7. packages/agent-connector/src/adapters/base.js — launcher install path

Before this change

  • Custom Skills were stored in Workspace.settings["custom_skills"] JSONB and were visible only inside one Workspace.
  • A custom Skill had no first-class identity, immutable versions, author namespace, license, or fork lineage.
  • Users could not search Skills published by other users, inspect version history, or fork a Skill into their own Workspace.
  • Reusing Workspace file records for public releases would couple published content to file deletion, trash, and Workspace lifecycle behavior.
  • Built-in catalog data, frontend static metadata, and custom Skills used separate paths that could not support a searchable marketplace.

After this change

1. Registry foundation

Adds namespaces, Workspace Skills, private versions, public Skills, public versions, immutable artifacts, and per-agent installation state, together with migration 030.

  • Uploading a private Skill creates a version; the author can add later private versions and see the full timeline.
  • Public mirrored versions use content-addressed artifacts, independent of the Workspace file lifecycle.
  • Published mirrored versions are immutable and retain their version, changelog, and attribution snapshot.
  • Forks record the exact source version and preserve original attribution.

2. Public search, details, publishing, forking, and take-down

  • Skill Hub can search public Skills and filter by category and tags.
  • Public details show namespace, license, version history, changelog, and source.
  • Markdown custom Skills can be published after the author explicitly selects a derivative-friendly license (MIT, Apache-2.0, CC-BY-4.0, CC-BY-SA-4.0). There is no default license.
  • Users can fork a Registry Skill into their own Workspace.
  • Publication is reversible. POST /registry/skills/{id}/visibility unlists or re-lists a skill; POST /registry/skills/{id}/versions/{vid}/yank withdraws one version, after which the next published version takes over and history keeps the yanked entry for attribution. Both are publisher-only, so reserved upstream namespaces — which have no owner — are unreachable.
  • An unlisted skill leaves search entirely, so its publication state is surfaced on the author's own private copy. Without that, re-listing would have no reachable entry point.
  • Public publishing requires a signed-in identity with at least Workspace member access. A Workspace token cannot act as an author identity.

3. Rolling leaderboards (migration 031)

GET /registry/leaderboard?board=community|official&window=7|30, scored by installs + forks over a rolling window.

Two boards, deliberately. The curated catalog arrives with an audience a new author cannot match; ranked together, the community would never reach the top of a mixed board and the ranking would stop being an incentive. community ranks user-published skills, official ranks the built-in catalog.

A new append-only stream, because the existing table cannot answer the question. agent_skill_installations is current state keyed by (workspace, agent, skill) and drops rows on uninstall — it knows who has a skill now, never how much traction it got last week. skill_activity_events never updates or deletes, so any window is a plain time-range aggregation.

Abuse control happens at write time, not query time:

  • A repeat signal from the same (skill, workspace, agent) inside 30 days is not recorded. That window is ≥ the longest ranking window, so one origin is worth at most one point on any board and an install/uninstall loop cannot pump a score.
  • Installs of a skill by the workspace that authored it are recorded but flagged self_authored, and excluded from ranking. The raw stream stays complete for later analysis.
  • install_count now follows the same rules. This matters beyond the leaderboard: search orders by install_count, so before this change a reinstall loop could push a skill up the default listing.

Built-in install counts also start incrementing at all. They report under their historical catalog slug, which the previous UUID-only lookup never resolved — this was the known follow-up flagged in the last review round, and it is fixed here with a regression test.

4. Built-in catalog integration

  • The built-in catalog is synchronized at startup under a PostgreSQL advisory transaction lock. Anonymous GET requests no longer write to the database.
  • The entire built-in catalog (all 66 entries) is exposed as upstream pointers. Nothing in it is mirrored or redistributed by us. Only the license label differs by upstream: Apache-2.0 for TerminalSkills/skills, MIT for OpenSenseNova/SenseNova-Skills, and LicenseRef-Upstream for Anthropic entries, whose packages mix open and source-available terms.
  • Built-in Skills retain their logos, tags, curated featured state, translated descriptions, and historical catalog-slug installation keys.
  • Installation state written by the temporary UUID-based build remains visible, and uninstall removes both UUID and slug aliases.
  • The static frontend catalog is used only when the Registry is unreachable. An empty search result does not reintroduce removed content.

5. Installation integrity and publication safeguards

Integrity guarantees differ by source mode, and reviewers should read them separately:

Mirrored (user-published UGC) Upstream pointer (built-in catalog)
Storage Content-addressed artifact, ours Upstream GitHub repo
Version pinning Immutable, pinned by version id Not pinned — launcher fetches main/master
Integrity check SHA-256 verified by both the backend download path and the launcher None
Content scanning Frontmatter validation, pipe-to-shell rejection, size and encoding limits Not scanned (scan_result: not_mirrored)

Upstream commit pinning and integrity verification for the built-in catalog are deliberately out of scope here and tracked as follow-up work. Behavior for built-in Skills is unchanged from develop.

Additional safeguards:

  • Public UGC is Markdown-only in this MVP. ZIP and scripted packages remain available for private Skills but cannot be published.
  • User namespaces are reused by owner_user_id, and every new user namespace slug carries an identity suffix, so a display name can never claim a canonical brand URL.
  • Startup synchronization never renames a public namespace and never reactivates removed, unlisted, or yanked content. A namespace conflict is logged as a warning and that upstream owner is skipped.

User-visible behavior

Before: a user uploaded a Skill; it stayed private to one Workspace and could not be searched, published, forked, or versioned publicly.

After: a user uploads a Skill, iterates on it through private versions, then explicitly picks a license and publishes a Markdown version. Other users search it, see the author and version history, install it, or fork it. The author can withdraw a version or take the whole listing down later. Skills that get traction surface on a rolling community leaderboard, ranked separately from the built-in catalog.

TODO: attach Skill Hub screenshots — leaderboard panel, search results, public detail with version timeline, license confirmation before publish, fork action, private version timeline.

Impact scope

Backend — adds migrations 030 and 031 plus Registry tables; adds public search, leaderboard, detail, version download, publish, fork, visibility, yank, and private-version APIs; changes custom Skill registration, listing, install, uninstall, and status callbacks; synchronizes the built-in catalog at startup, with multi-worker startup protected by an advisory transaction lock.

Frontend — makes the Registry the primary Skill Hub data source; adds server-side search, the leaderboard panel, private and public version timelines, new-version upload, explicit license confirmation, publish, fork, and take-down actions; disables public publishing for self-hosted domains and signed-out users without affecting private Skill upload and use.

Launcher / agent-connector — adds Registry artifact download, SHA-256 verification, and pinned-version installation; reuses existing path-safety, SKILL.md validation, and adapter install behavior. Mirrored Registry packages are limited to Claude, Cursor, and Codex adapters in this MVP; upstream catalog compatibility is unchanged.

Compatibility

  • Legacy custom_skills data uses dual-read with lazy materialization. Entries that cannot be materialized because their backing file is missing stay visible with a re-upload message.
  • Built-in Skills continue to use catalog slugs as installation-state keys, so existing users do not see every installed Skill reset to "not installed."
  • Leaderboards start empty on an existing deployment: they read only the new event stream, so installs that happened before migration 031 have no signal. Boards fill in as new installs and forks arrive.

Verification

  • Skill-related backend tests: 47 passed.
  • tests/test_skill_registry.py grew from 4 to 27 cases, covering publication, search, immutable download, fork attribution, reserved and colliding namespaces, private-version installation and listing, yank protection, publisher-only moderation, dual-key status cleanup, counter resolution, ranking order, self-install exclusion, reinstall-loop dedup, board isolation, and rolling-window expiry.
  • Launcher skill-installer.test.js: 50 passed, including two Registry cases (pinned download with digest verification, and rejection of a tampered artifact).
  • Frontend tsc --noEmit and next build: passed.
  • Full backend suite: same failure set as develop; this branch introduces no new failures.

Risks and rollback

  • Migrations 030 and 031 must be applied before the app starts. Without 030, startup logs LIFESPAN: skill registry bootstrap failed and Registry endpoints return empty results; the rest of Workspace stays available. Without 031, the leaderboard endpoint fails and the frontend hides the panel rather than showing an error.
  • Rolling the schema back is lossy. Forked Skills and every private version after the first exist only in the new tables — they are not written back to the legacy custom_skills JSON. After a downgrade, those Skills disappear from the Skill Hub even though their FileRecord rows survive. Export or re-register them before rolling back. Ranking history is lost outright.
  • 030's downgrade() drops tables unconditionally, without the existence guards upgrade() uses. Do not run it against a database where the tables may be partially present.
  • On first startup, if historical data occupies a reserved namespace slug, startup logs a warning and skips that upstream owner rather than silently renaming a public URL. No repair CLI ships in this PR.
  • The dedup window and the installs+forks scoring formula are baked into recorded data and rank ordering. Changing them later makes historical boards incomparable, so they are worth agreeing on during review rather than after.

Out of scope for this MVP

Not a complete Skill marketplace. Remaining for later iterations:

  • Trending/velocity ranking and richer signals (retention, ratings, stars) beyond installs and forks.
  • Author profiles, reporting workflows, and a moderation UI.
  • Public scripted UGC and sandboxed automated review; mirrored installs remain limited to Claude, Cursor, and Codex adapters.
  • Upstream commit pinning and integrity verification for built-in catalog entries.
  • Large-scale mirroring of third-party repositories to grow inventory.
  • An administrator repair CLI for historical namespace conflicts.
  • A single shared source of truth for frontend and backend catalog tags.

@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openagents-workspace Ready Ready Preview Aug 7, 2026 5:25am

Request Review

Closes the gap between the Registry foundation and the product requirement:
authors can now iterate and retract their published work, and rolling
leaderboards give community skills a surface of their own.

Rankings (migration 031)
- New append-only skill_activity_events stream. agent_skill_installations is
  current state and drops rows on uninstall, so it can never answer "how much
  traction did this skill get last week".
- Abuse control at write time: a repeat signal from the same
  (skill, workspace, agent) within 30 days is not recorded, and an author's
  installs of their own skill are flagged and excluded from ranking.
- install_count now follows the same rules. Search orders by it, so a reinstall
  loop could previously push a skill up the default listing.
- GET /registry/leaderboard: separate community and official boards over a
  rolling 7- or 30-day window, scored by installs + forks.

Publication control
- POST /registry/skills/{id}/visibility toggles a listing public/unlisted.
- POST /registry/skills/{id}/versions/{vid}/yank withdraws one version; the
  next published version takes over, and history keeps the yanked entry for
  attribution.
- Both are publisher-only. Reserved upstream namespaces have no owner, so
  catalog pointers stay unreachable.
- An unlisted skill leaves search, so its publication state is surfaced on the
  author's private copy — otherwise re-listing would be unreachable.

Private version iteration
- GET /skills/custom/{id}/versions, symmetric with the existing POST.
- Skill Hub gains the private version timeline and a new-version upload; the
  create endpoint previously had no frontend caller at all.

Built-in install counts also start incrementing: they report under the
historical catalog slug, which the UUID-only lookup never resolved.

Verification: skill registry tests 12 -> 27; full backend suite matches the
develop baseline; launcher 50 passed; tsc and production build clean.
Visibility was decided from the selected board alone, and the board tabs live
inside the panel. With the community board empty — the normal state of a fresh
or self-hosted deployment — the whole panel disappeared, taking the only route
to the official board with it.

Probe both boards once on mount instead: hide the panel only when neither has
data, and open on whichever board does. A missing endpoint (older backend, or
migration 031 not yet applied) still hides it silently.
@QuanCheng-QC QuanCheng-QC changed the title feat add compact public Skill Registry MVP Skill Registry with rolling leaderboards Aug 8, 2026
@QuanCheng-QC QuanCheng-QC reopened this Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant