Skip to content

feat: v0.2 agent-first registry with CLI, MCP, and static registry#28

Merged
devallibus merged 21 commits into
masterfrom
development
Mar 8, 2026
Merged

feat: v0.2 agent-first registry with CLI, MCP, and static registry#28
devallibus merged 21 commits into
masterfrom
development

Conversation

@devallibus
Copy link
Copy Markdown
Owner

Summary

Transforms ShaderBase from a git-backed shader corpus into a full agent-first registry (shadcn-style distribution model):

  • Static registry buildscripts/build-registry.ts generates index.json + per-shader bundles from shaders/*/, deployed to Cloudflare Pages CDN
  • CLI package (shaderbase) — search and add commands; copies GLSL + recipe files into the user's project
  • MCP server — Cloudflare Worker with search_shaders and get_shader tools for AI agent integration
  • Web app cleanup — removed 564-line manual submission form, simplified to AI-only parse → GitHub PR creation flow
  • Comprehensive tests — 25 tests across schema, CLI, MCP, registry build, and web app server functions
  • CI pipeline — builds registry on every PR, deploys to Cloudflare Pages on master push
  • D1 database — created shaderbase-reviews with migration applied

Live Deployments

Architecture Decisions

Documented in GitHub issues #23-#27 under milestone "v0.2 — Agent-First Registry"

Test plan

  • bun run test — 25 tests pass (schema, CLI, MCP, registry)
  • bun run validate:shaders — 3 manifests valid
  • bun run build:registry — generates 4 JSON files
  • Web app builds successfully
  • Registry deployed and serving JSON
  • MCP server health check returns ok
  • Verify CI pipeline passes on this PR

🤖 Generated with Claude Code

devallibus and others added 18 commits March 7, 2026 00:55
The /shaders route's validateSearch was redirecting /shaders/$name to
/shaders/$name?q=, blocking the detail page from loading (307 loop).

Fix: remove validateSearch from the parent /shaders route and read the
query param manually. Add Outlet support so the /shaders route acts as
a layout when child routes (/shaders/$name) are active.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The /shaders route was both a page and a parent for /shaders/$name,
causing the browse page to not render when using Outlet. Split into:
- shaders.tsx: layout route that renders <Outlet>
- shaders.index.tsx: browse page (renders at /shaders)
- shaders.$name.tsx: detail page (renders at /shaders/$name)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add .data/ (SQLite databases), .output/ and .nitro/ (build artifacts),
and .playwright-mcp/ (test screenshots) to gitignore.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scaffold packages/cli/ with Zod schemas for the static registry format:
- RegistryIndexEntry: searchable metadata per shader
- RegistryIndex: top-level index with version and shader list
- RegistryShaderBundle: full shader detail with inlined GLSL and recipes
- Full provenance passthrough for adapted/ported shaders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…orpus

Reads shaders/*/shader.json, validates, inlines GLSL source and recipe
code, produces registry/index.json + per-shader bundles. Adds
bun run build:registry command.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- search: filter shaders by query, category, pipeline, environment, tags
- add: write GLSL + recipe files into user's project (shadcn-style)
- registry-client: HTTP fetch for index and shader bundles from CDN

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
npx shaderbase search --query gradient
npx shaderbase add gradient-radial --env r3f --dir src/shaders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cloudflare Worker skeleton with:
- handleSearchShaders: filters registry index by query/category/pipeline/env/tags
- handleGetShader: returns full shader bundle with optional env filtering
- /health and /tools HTTP endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- bun run test now runs schema + CLI + MCP + registry tests (25 total)
- Add @shaderbase/cli path alias to tsconfig.base.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Delete submission-draft.ts (564 lines of manual form builder)
- Delete RecipeEditor.tsx and SourceEditor.tsx form components
- Remove submissions/ directory (filesystem intake queue)
- Simplify AiSubmitWizard to: paste → AI parse → read-only review
- Remove saveDraftSubmission server function (filesystem writes)
- Add "Create Pull Request" placeholder button (wired in Task 9)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract resolveSource() from createServerFn for testability
- 8 tests for URL resolution (GLSL, Shadertoy, gist, GitHub file)
- 7 tests for reviews CRUD (add, get, average, ratings map)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract core logic into testable functions:
- listShadersFromDisk: reads shader corpus from filesystem
- loadShaderDetail: loads full shader detail with inlined sources
Server functions delegate to these, adding DB concerns.
9 tests covering listing, detail loading, recipes, uniforms, provenance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Submit flow now creates a PR via GitHub REST API:
- Creates branch, blobs, tree, commit, and PR
- Builds proper shader.json manifest from AI-parsed data
- Shows PR URL on success, error message on failure
- Requires GITHUB_TOKEN and GITHUB_REPO env vars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Build registry on every PR/push (validates generation works)
- Upload registry as artifact for inspection
- Deploy to Cloudflare Pages on master push (requires CLOUDFLARE_API_TOKEN)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- README: add architecture diagram, CLI/MCP usage, repository map
- CLAUDE.md: add packages, commands, distribution model
- git-contract: list registry, CLI, MCP as derived artifacts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create shaderbase-reviews D1 database (WEUR region)
- Add 0001_reviews.sql migration (applied to remote)
- Add wrangler.toml with D1 binding configuration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Registry: https://shaderbase-registry.pages.dev (4 JSON files)
- MCP server: https://shaderbase-mcp.bats-678.workers.dev
- /health returns ok, /tools lists search_shaders + get_shader

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ubuntu-latest ships Node 18 which doesn't support
--experimental-strip-types. Tests require Node 22.6+.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@devallibus
Copy link
Copy Markdown
Owner Author

Findings

  1. High: the new PR-creation server action is not actually protected by auth. apps/web/src/lib/server/github-pr.ts accepts any POST that reaches the server and only checks for GITHUB_TOKEN; it never validates a Better Auth session. The sign-in requirement on apps/web/src/routes/submit.tsx is therefore UI-only, so an unauthenticated caller could still create branches and PRs with the repo token.

  2. High: the GitHub tree creation flow is wired against the wrong SHA, so I expect PR creation to fail before a branch is opened. apps/web/src/lib/server/github-pr.ts fetches the head commit SHA, then sends that value as base_tree. GitHub?s create-tree API expects a tree SHA, not a commit SHA.

  3. High: the web submission flow generates manifests that do not satisfy the repo?s own schema, so any PR created by the app will fail validation/build. apps/web/src/components/AiSubmitWizard.tsx builds a manifest with no recipes and no preview, and sends an empty recipe set. But packages/schema/src/index.ts requires at least one recipe and requires a preview. For adapted/ported shaders, the schema also requires populated provenance, while the submit flow always sends sources: [].

  4. High: the shipped "MCP server" is only a metadata document, not an invokable MCP service. packages/mcp/src/index.ts never routes requests to handleSearchShaders or handleGetShader; it only serves /health, /tools, and a static info response. So the deployed worker cannot actually execute search_shaders or get_shader for an agent.

  5. Medium: the branch breaks the repo?s own typecheck target. bun run typecheck fails on the new test code in packages/cli/src/commands/search.test.ts and packages/mcp/src/handlers.test.ts. Current CI will miss that because .github/workflows/validate.yml only runs tests, manifest validation, and registry build.

Verification
bun run test passes locally. bun run typecheck fails with TS2532 in packages/cli/src/commands/search.test.ts and TS2345 in packages/mcp/src/handlers.test.ts.

Signed,
GPT-5.4 high

1. Auth: add Better Auth session check to createShaderPR handler
2. GitHub API: resolve tree SHA from commit SHA for base_tree
3. Manifest: add recipes, preview, and requiredNotice to buildManifest
4. MCP server: wire /search_shaders and /get_shader to handlers
5. TypeScript: fix TS2532 (non-null assertions) and TS2345 (fetch type)
   Add typecheck step to CI pipeline

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@devallibus
Copy link
Copy Markdown
Owner Author

Follow-up review after the fix commit:

  1. Medium: the submission flow is still not schema-safe for adapted/ported shaders. apps/web/src/components/AiSubmitWizard.tsx now adds requiredNotice, but it still hardcodes sources: []. The schema still rejects any non-original manifest without at least one provenance source and a recorded revision, per packages/schema/src/index.ts. So PR creation can still generate invalid manifests whenever AI classifies the source as adapted or ported.

Verification:
bun run test passes locally.
bun run typecheck passes locally.

Signed,
GPT-5.4 high

devallibus and others added 2 commits March 8, 2026 13:42
Non-original shaders now include source URL, kind, revision, author,
and retrievedAt from the resolved source metadata (Shadertoy, gist,
GitHub file). Ensures manifests pass schema validation for adapted
and ported shaders.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI's tsc doesn't have Bun's built-in Node type globals.
Adding @types/node and types: ["node"] in tsconfig ensures
console, process, node:fs, etc. resolve on all platforms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@devallibus devallibus merged commit fe3411c into master Mar 8, 2026
2 checks passed
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