# Static Artifact API Contract Contract version: `static-artifact-api-v1` This document defines the public JSON artifact surface for registry consumers. The artifacts are generated by `claude-skill-registry-core`; generated files in the merged `claude-skill-registry` repository are publish outputs, not source files to patch by hand. ## Locations - Core Pages base URL: `https://majiayu000.github.io/claude-skill-registry-core/` - Merged artifact raw base URL: `https://raw.githubusercontent.com/majiayu000/claude-skill-registry/main/` Core Pages is optimized for the web app and public read APIs. The merged artifact is optimized for bulk registry compatibility and raw archive browsing. ## Public Entry Points | Path | Location | Contract | | --- | --- | --- | | `search-index-lite.json` | Core Pages | Startup catalog index with deduped summaries and quality/security signals. | | `search-index.json` | Core Pages | Compatibility pointer for the full search payload. | | `search-index-manifest.json` | Core Pages | Full search shard manifest. | | `search-shards/part-000.json` | Core Pages | Full search shard part pattern. | | `featured.json` | Core Pages | Featured skills for the web app. | | `plugins.json` | Core Pages | Plugin catalog. | | `stats.json` | Core Pages | Generated counts, shard sizes, and summary statistics. | | `quality-index.json` | Core Pages | Compatibility pointer for quality records. | | `quality-index-manifest.json` | Core Pages | Quality shard manifest. | | `quality-shards/part-000.json` | Core Pages | Quality shard part pattern. | | `security-index.json` | Core Pages | Compatibility pointer for security records. | | `security-index-manifest.json` | Core Pages | Security shard manifest. | | `security-shards/part-000.json` | Core Pages | Security shard part pattern. | | `ranking-index.json` | Core Pages | Compatibility pointer for ranking records. | | `ranking-index-manifest.json` | Core Pages | Ranking shard manifest. | | `ranking-shards/part-000.json` | Core Pages | Ranking shard part pattern. | | `categories/index.json` | Core Pages | Category manifest index. | | `categories/.json` | Core Pages | Legacy category compatibility pointer. | | `categories//manifest.json` | Core Pages | Category part manifest. | | `categories//part-000.json` | Core Pages | Category part pattern. | | `registry_summary.json` | Core raw | Lightweight source summary and counts. | | `registry.json` | Merged raw | Compatibility pointer for the full registry payload. | | `registry-manifest.json` | Merged raw | Registry shard manifest. | | `registry-shards/00.json` | Merged raw | Registry shard pattern, keyed by two-character shard id. | | `provenance/merge-source.json` | Merged raw | Source refs used for the merged publish artifact. | Any new public JSON artifact must be added to this table in the same PR that adds or changes the generated artifact. ## Compatibility Pointers Large historical full-payload files are now small pointer files. A pointer object must include: - `schema_version: 1` - `total_count` as the canonical non-negative record count - `deprecated_full_payload: true` - `message` - `manifest` - `compat_since` - `compat_until` - `replacement` Pointer files must not contain a full `skills`, `records`, or `s` payload. Consumers must follow `manifest` or `replacement` instead of assuming the compatibility file contains all records. Current pointer entry points: - `search-index.json` - `quality-index.json` - `security-index.json` - `ranking-index.json` - `categories/.json` - `registry.json` Compatibility count aliases are limited to the following V1 window. Every alias must equal `total_count`; unlisted aliases are invalid. | Pointer | Canonical count | Allowed alias | Window | | --- | --- | --- | --- | | `search-index.json` | `total_count` | `t` | `static-artifact-api-v1` through `static-artifact-api-v2` | | quality/security/ranking pointers | `total_count` | `count` | `static-artifact-api-v1` through `static-artifact-api-v2` | | `categories/.json` | `total_count` | `count` | `static-artifact-api-v1` through `static-artifact-api-v2` | | `registry.json` | `total_count` | `registry_skill_count_dedup` | `static-artifact-api-v1` through `static-artifact-api-v2` | ## Manifests Manifest objects must include `schema_version: 1`, an `updated_at` or `generated_at` timestamp, canonical `total_count`, an exact shard/part count, and shard or part references. Entry counts must sum to `total_count`. Search, quality, security, and ranking manifests use shard entries with: - `path` - `gzip_path` when a gzip artifact is written - `count` - `bytes` - `gzip_bytes` when a gzip artifact is written - `sha256` Category manifests use part entries with: - `path` - `gzip_path` - `count` - `bytes` - `gzip_bytes` - `sha256` Category manifests also publish `part_strategy: bounded-sequential-stars-desc`. Parts are ordered by stars descending, then name and install path, so consumers may fetch only the first part for a bounded top-skills leaderboard. Consumers must fail closed if this strategy or the first-part identity/count metadata is absent or invalid. Registry manifests use shard entries with: - `id` - `path` - `gzip_path` - `count` - `bytes` - `gzip_bytes` - `sha256` The registry manifest contains exactly the canonical 256 lowercase hexadecimal ids `00` through `ff`, once each. An id maps only to `registry-shards/.json` and `registry-shards/.json.gz`; the payload `shard` must equal that id. Every registry skill belongs to the first two hexadecimal characters of `sha256("|")`, where the install key is `repo/path`, then `repo`, then `local/path`, then `local/category/name`; an absent or empty branch is `main`. Consumers should validate `sha256` when they need reproducible syncs. Consumers should prefer `gzip_path` when bandwidth matters and plain `path` when a simpler client is more important. ## Shard Payloads Shard payloads must include: - `schema_version` - an identity field for the shard or part - `count` - a bounded payload array Search shard payload arrays are `s`. Lite search document payload arrays are `skills`. Signal shard payload arrays are `records`. Category part payload arrays are `skills`. Registry shard payload arrays are `skills`. Each shard/part `count` must equal its payload array length and manifest entry count. Manifest entry `bytes`, `gzip_bytes`, and `sha256` describe the referenced plain/gzip files exactly; gzip JSON must be structurally identical to plain JSON. ## Same-set Count Groups Counts are compared only inside explicitly identical sets: - Registry dedup set: `registry.json`, `registry-manifest.json`, `registry_summary.json`, and `stats.json.registry_skill_count_dedup`. - Search/category scan set: search pointer/manifest, category index/manifests, and `stats.json.indexed_skill_count_scan_shape`. - Stable-id dedup set: lite search, quality/security/ranking pointers/manifests, and `stats.json.lite_index_count`. Featured subsets, plugin counts, and raw archive counts are not compared to these groups. Security signal records expose `security_status` plus `security_decision` when scanner evidence was available. The decision object contains the scanner name, scanner version, ruleset hash, source content hash, scan timestamp, and a deterministic decision id. Missing security decisions must be treated as unknown evidence, not clean evidence. Shard ordering is deterministic for a given generator version, but consumers must not treat ordering as a stable API unless the manifest explicitly documents the ordering strategy. ## Deprecation Rules Removing or changing a public entry point is a breaking change. A breaking change must either: - add a new path and leave the old path as a compatibility pointer, or - update this contract with a migration note and a compatibility window. Compatibility pointer fields: - `compat_since`: first date or version when the pointer behavior was present - `compat_until`: planned end of this V1 compatibility window - `replacement`: path or path pattern consumers should use `compat_until` is required for every V1 compatibility pointer. Consumers must treat a pointer without it as invalid rather than guessing an unannounced removal date. ## Consumer Guidance For startup search, use `search-index-lite.json` first. For exhaustive search, follow `search-index.json` to `search-index-manifest.json`, then load the listed search shards. For category browsing, load `categories/index.json`, then follow the selected category manifest and parts. Do not fetch every category part on startup. For trust and ranking overlays, load the pointer, then the corresponding manifest and shards. Treat missing signal records as unknown, not clean. For full registry sync, consumers should prefer manifests and bounded shards to giant single-payload JSON files. Load the merged artifact `registry-manifest.json` and every shard it lists; `registry.json` is compatibility-only. Missing manifests or shards, invalid JSON, and malformed payload shapes are errors and must not be silently ignored. Minimal standard-library Python example: ```python import json from urllib.parse import urljoin from urllib.request import urlopen manifest_url = ( "https://raw.githubusercontent.com/majiayu000/" "claude-skill-registry/main/registry-manifest.json" ) def load_json(url): with urlopen(url) as response: return json.load(response) manifest = load_json(manifest_url) if not isinstance(manifest, dict): raise ValueError("registry manifest must be a JSON object") shards = manifest.get("shards") if not isinstance(shards, list) or not shards: raise ValueError("registry manifest must contain a non-empty 'shards' list") skills = [] for shard in shards: if not isinstance(shard, dict): raise ValueError("registry shard entries must be JSON objects") path = shard.get("path") if not isinstance(path, str) or not path: raise ValueError("registry shard entries must contain a non-empty 'path'") shard_url = urljoin(manifest_url, path) payload = load_json(shard_url) if not isinstance(payload, dict) or not isinstance(payload.get("skills"), list): raise ValueError(f"{shard_url} must contain a 'skills' list") skills.extend(payload["skills"]) print(f"loaded {len(skills)} skills") ``` The example intentionally lets HTTP and JSON decoding errors propagate so a partial registry sync cannot look successful.