feat(registry): migrate registry entries from Markdown to JSON#80
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
15 issues found across 122 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed. cubic prioritises the most important files to review.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/registry/content/registry/openai/codex.json">
<violation number="1" location="apps/registry/content/registry/openai/codex.json:19">
P1: Use the real npm package name in the alias. `@openai/codex` is the published package, so the current alias breaks npm-based registry lookups for Codex.</violation>
</file>
<file name="packages/schema/registry-entry.schema.json">
<violation number="1" location="packages/schema/registry-entry.schema.json:112">
P2: Disallow `branch` and `tag` together in the GitHub source schema. Without that exclusion, the generated JSON Schema validates entries that `registryEntrySchema` rejects.</violation>
</file>
<file name="scripts/migrate-registry-to-json.test.ts">
<violation number="1" location="scripts/migrate-registry-to-json.test.ts:1">
P2: Place this test in the configured Vitest `test/` tree (or expand the include glob), otherwise it will never run.</violation>
</file>
<file name=".please/docs/ideas/telemetry-driven-registry.md">
<violation number="1" location=".please/docs/ideas/telemetry-driven-registry.md:55">
P2: This overstates version resolution as lockfile-only; GitHub entries in ASK resolve their version from the inline `@ref`, not from project lockfiles.
(Based on your team's feedback about ASK version resolution.) [FEEDBACK_USED]</violation>
</file>
<file name="apps/registry/app/pages/index.vue">
<violation number="1" location="apps/registry/app/pages/index.vue:73">
P2: Render the `ask add` example from a package alias, not from `entry.repo`. Using `owner/repo` here points npm/pypi/etc entries at the GitHub flow instead of the curated ecosystem spec.</violation>
</file>
<file name="apps/registry/content/registry/mastra-ai/mastra.json">
<violation number="1" location="apps/registry/content/registry/mastra-ai/mastra.json:26">
P1: The npm source for `@mastra/core` points to `dist/docs`, but that directory is not present in the published package.</violation>
<violation number="2" location="apps/registry/content/registry/mastra-ai/mastra.json:47">
P1: The npm source for `@mastra/memory` points to `dist/docs`, but that directory is not present in the published package.</violation>
</file>
<file name="apps/registry/content/registry/nuxt/ui.json">
<violation number="1" location="apps/registry/content/registry/nuxt/ui.json:16">
P1: Use the scoped npm package name `@nuxt/ui` here. Alias lookups are exact, so registering this package as `nuxt-ui` makes `/api/registry/npm/%40nuxt%2Fui` miss the Nuxt UI entry.</violation>
</file>
<file name="apps/registry/content/registry/spring-projects/spring-security.json">
<violation number="1" location="apps/registry/content/registry/spring-projects/spring-security.json:20">
P2: Use a real Maven coordinate for this alias. `spring-security` is not a valid Spring Maven package name, so coordinate-based lookups will miss this entry.</violation>
</file>
<file name=".please/docs/tracks/active/telemetry-driven-registry-20260413/spec.md">
<violation number="1" location=".please/docs/tracks/active/telemetry-driven-registry-20260413/spec.md:26">
P3: FR-6 points to a non-existent skill path; use the real `.claude/skills/ask-registry/` location so the migration work updates the correct files.</violation>
<violation number="2" location=".please/docs/tracks/active/telemetry-driven-registry-20260413/spec.md:54">
P2: This assumption is inaccurate: the JSON `data` collection requires different query fields (`stem` in this repo), so saying it behaves identically to `page` will mislead follow-up work.</violation>
</file>
<file name="apps/registry/content/registry/jerryjliu/llama_index.json">
<violation number="1" location="apps/registry/content/registry/jerryjliu/llama_index.json:27">
P1: This GitHub source path does not exist in `jerryjliu/llama_index`, so docs ingestion for this registry entry will fail.</violation>
</file>
<file name="apps/registry/app/pages/registry/[...slug].vue">
<violation number="1" location="apps/registry/app/pages/registry/[...slug].vue:48">
P2: Use a package alias for the Quick Start command instead of the bare repo. Rendering `entry.repo` makes npm-backed entries add a GitHub spec such as `facebook/react`, which bypasses the lockfile-based npm resolution users previously got from `npm:react`.</violation>
</file>
<file name="apps/registry/content/registry/microsoft/agent-framework.json">
<violation number="1" location="apps/registry/content/registry/microsoft/agent-framework.json:14">
P1: Use the real NuGet package ID here; `agent-framework` will not match `Microsoft.Agents.AI` lookups.</violation>
</file>
<file name="apps/registry/content/registry/vercel/ai.json">
<violation number="1" location="apps/registry/content/registry/vercel/ai.json:27">
P1: The npm docs path is wrong for `ai`; the published package ships docs under `docs/`, not `dist/docs`. Pointing at a non-existent directory will break npm-source docs resolution for this entry.</violation>
</file>
Architecture diagram
sequenceDiagram
participant Dev as Contributor (IDE)
participant Schema as Schema Package
participant Files as content/registry/*.json
participant Nuxt as Nuxt Content (v3)
participant API as Registry API
participant Web as Web UI (Nuxt Page)
participant CLI as CLI Client
Note over Schema,Files: NEW: Schema Generation & Validation
Schema->>Schema: zod-to-json-schema
Schema-->>Files: NEW: Publish registry.schema.json
Dev->>Files: Create/Update JSON entry
Files->>Dev: NEW: IDE autocomplete & validation
Note over Nuxt,Files: CHANGED: Content Collection Model
Nuxt->>Files: CHANGED: Load collection (type: 'data')
Note right of Nuxt: Migration from type: 'page' (.md)<br/>to type: 'data' (.json)
Note over CLI,API: Runtime API Flow (Unchanged Output)
CLI->>API: GET /api/registry/:owner/:repo
API->>Nuxt: queryCollection('registry')
Nuxt-->>API: Return JSON data
API-->>CLI: 200 OK (Identical Schema)
Note over Web,Nuxt: CHANGED: Web Navigation & Rendering
Web->>Nuxt: CHANGED: query by 'stem' (formerly 'path')
Nuxt-->>Web: Return Data Entry
Web->>Web: CHANGED: Direct data render (No ContentRenderer)
Note right of Web: Removed Vue components<br/>for Markdown body rendering
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Deploying ask-registry with
|
| Latest commit: |
423c222
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://70a9e733.ask-registry.pages.dev |
| Branch Preview URL: | https://amondnet-phantom-station.ask-registry.pages.dev |
There was a problem hiding this comment.
4 issues found across 13 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/registry/content/registry/spring-projects/spring-security.json">
<violation number="1" location="apps/registry/content/registry/spring-projects/spring-security.json:16">
P1: Preserve the existing `spring-security` package identity here and add the Maven coordinate as an extra alias; otherwise this entry changes `package.name` in the API response and breaks existing `/api/registry/maven/spring-security` lookups.</violation>
</file>
<file name="apps/registry/content/registry/nuxt/ui.json">
<violation number="1" location="apps/registry/content/registry/nuxt/ui.json:20">
P2: Keep the legacy `nuxt-ui` alias here. Setting the only alias to the same value as `package.name` removes the old lookup key and can break existing alias-based resolution.</violation>
</file>
<file name="apps/registry/content/registry/vercel/ai.json">
<violation number="1" location="apps/registry/content/registry/vercel/ai.json:27">
P1: Keep the `ai` npm source at `dist/docs`; `docs` does not match this package's documented curated npm docs path and can break npm-based doc resolution.</violation>
</file>
<file name="apps/registry/app/pages/index.vue">
<violation number="1" location="apps/registry/app/pages/index.vue:72">
P2: Don't advertise the first package alias as the entry's install command. For monorepo entries, this silently picks one package (for example `@mastra/core`) even though the card represents the whole repo.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
2 issues found across 4 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/registry/app/pages/registry/[...slug].vue">
<violation number="1" location="apps/registry/app/pages/registry/[...slug].vue:47">
P2: This guards the curated alias behind `packages.length === 1`, so multi-package entries now fall back to `entry.repo` even when `entry.packages[0].aliases[0]` exists. Render the first alias whenever it exists, and only fall back to `entry.repo` when no alias is available.
(Based on your team's feedback about rendering Quick Start commands from the curated ecosystem alias.) [FEEDBACK_USED]</violation>
</file>
<file name="apps/registry/app/pages/index.vue">
<violation number="1" location="apps/registry/app/pages/index.vue:72">
P2: This `length === 1` guard drops the curated `ecosystem:name` quick-start for any entry with multiple packages. Use the first alias whenever it exists, and fall back to `entry.repo` only when no alias is available.
(Based on your team's feedback about rendering Quick Start commands from the curated ecosystem alias.) [FEEDBACK_USED]</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/registry/app/pages/index.vue">
<violation number="1" location="apps/registry/app/pages/index.vue:72">
P2: Only use the package alias for single-package entries; this now picks the first package alias for multi-package entries and can show the wrong quick-start command.
(Based on your team's feedback about rendering repo for multi-package entries.) [FEEDBACK_USED]</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/registry/wrangler.jsonc">
<violation number="1" location="apps/registry/wrangler.jsonc:39">
P2: `vars.SKIP_DEPENDENCY_INSTALL` is a runtime Pages Function binding, so it will not skip dependency installation during the Cloudflare Pages build.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Registry JSON migration track: convert registry entries from Markdown with YAML frontmatter to plain JSON files in Nuxt Content v3. Includes ideation document, spec, plan, and GitHub Issue #78.
- T002: add zod-to-json-schema dependency and registryEntryJsonSchema export - add generate script that writes registry-entry.schema.json to package root - re-export from packages/schema/src/index.ts - Tests: passed [/please:implement]
- T001: one-shot script extracts YAML frontmatter from registry .md files and writes .json - Tests: passed (9/9) [/please:implement]
[/please:implement]
Run the migration script to extract YAML frontmatter from each .md file and write it as a plain .json file, discarding the unused markdown body.
- content.config.ts: type 'page' → 'data', source **/*.md → **/*.json - Detail page: remove ContentRenderer, dead ecosystem/strategies fields - Index page: remove dead ecosystem badge - Both pages: use entry.repo for quick-start command
Data collections in Nuxt Content v3 do not have a `path` field.
Replace all `entry.path` and `.where('path', ...)` with `stem`-based
equivalents. Also fix console.log → consola in generate script.
- Move track active/ → completed/ - Add retrospective to plan.md - Update CLAUDE.md with Nuxt Content data collection gotchas
- Fix openai/codex.json alias to use @openai/codex (official package name) - Fix nuxt/ui.json package name and alias to use @nuxt/ui (scoped name) - Fix jerryjliu/llama_index.json github path from docs/docs to docs - Fix microsoft/agent-framework.json alias to use Microsoft.Agents.AI (real NuGet ID) - Fix vercel/ai.json npm source path from dist/docs to docs (ai package ships docs/) - Fix spring-projects/spring-security.json Maven alias to proper coordinate - Add not constraint to JSON Schema to disallow branch+tag together in github source - Expand vitest include glob to pick up scripts/*.test.ts (migration tests were unreachable) - Fix telemetry-driven-registry.md: clarify GitHub entries use inline @ref for version - Fix spec.md assumption: data collection uses stem not path - Fix spec.md FR-6: use correct .claude/skills/ask-registry/ skill path - Fix index.vue and [...slug].vue: render ask add from package alias not entry.repo
- spring-security: restore package name to spring-security, add both maven:spring-security and maven:org.springframework.security:spring-security-core aliases to preserve backward-compat lookups while adding proper Maven coordinate - nuxt/ui: add legacy nuxt-ui alias alongside @nuxt/ui to avoid breaking existing /api/registry/npm/nuxt-ui lookups - index.vue, [...slug].vue: only show ecosystem:name for single-package entries; fall back to entry.repo for monorepo entries (multiple packages) to avoid misleadingly advertising only the first package as the install command
Remove packages.length === 1 guard so multi-package entries also render the curated ecosystem:name quick-start command when a first alias exists.
Cloudflare Pages builds use Node.js jiti (CJS require) to load content.config.ts, which fails when the exports map only has an "import" condition. Add "default" fallback so both CJS and ESM consumers can resolve the package. Also removes stale "not: required [branch, tag]" constraint from the generated JSON Schema (regenerated from source).
9c4ac59 to
3990a8b
Compare
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Requires human review: This is a significant data migration and refactor of core registry logic (Markdown to JSON) which requires human verification of data integrity and routing changes.
Cloudflare Pages was running with Root directory = apps/registry, so `bun run build` invoked Nuxt directly and skipped turbo's workspace build graph. The schema package (`@pleaseai/ask-schema`) never had its `dist/` emitted, and Nuxt's content.config.ts failed to resolve it. Relocate wrangler.jsonc to the repo root and point `pages_build_output_dir` at `apps/registry/dist` so the Cloudflare project can set Root directory = repo root. The root build command (`bun install && bun run build` → `turbo build`) then builds the schema workspace dep before the registry app. Adjust `preview:cf` to reference the relocated config file so local `wrangler pages dev` continues to work from apps/registry.
Summary
type: 'page'totype: 'data'zod-to-json-schema) for IDE autocompleteecosystem,strategies,ContentRenderer)path→stemqueries for data collection compatibilityCloses #78
Context
The registry serves as a CLI-routing lookup table only — the markdown body in each entry was never consumed by any client. JSON eliminates YAML indentation pitfalls, enables IDE validation via JSON Schema, and lowers the community contribution barrier.
This is Phase 1 of the Telemetry-Driven Registry initiative.
Test plan
bun run --cwd packages/schema test— 53 tests passbun run --cwd apps/registry build— Cloudflare Pages build succeedsbun run --cwd apps/registry test— unit tests pass/api/registry/facebook/reactreturns correct response/api/registry/npm/reactalias lookup worksVerification Checklist
Automated Tests
bun run --cwd apps/registry buildsucceeds with JSON entriesGET /api/registry/facebook/reactreturns identical responseGET /api/registry/npm/reactalias lookup workspackages/schematests passAcceptance Criteria
.jsonwith identical data.mdfiles incontent/registry/Summary by cubic
Migrates the registry from Markdown to JSON to simplify contributions, enable IDE validation, and prepare for telemetry-driven auto-registration. Also fixes Cloudflare Pages builds by moving
wrangler.jsoncto the repo root so the workspace builds in order. Addresses #78.type: 'data'withregistry/**/*.jsonregistryEntrySchemaviazod-to-json-schema; added adefaultexport condition for CJS/JITI; removed thebranch+tagexclusivity ruleContentRendererand dead fields; replacedpathusage withstemfor links and queriesecosystem:name) when present; otherwise falls back toentry.repo@openai/codex,@nuxt/ui(kept legacynuxt-ui), restoredspring-securitywith both Maven coordinates; correctedllama_indexdocs pathwrangler.jsoncto repo root and setpages_build_output_dirtoapps/registry/distso Cloudflare Pages runs the root build (turbo build) and emits the@pleaseai/ask-schemadist before the registry app buildsWritten for commit 423c222. Summary will update on new commits.