The Canvas template palette was empty on a fresh clone because
`workspace-configs-templates/`, `org-templates/`, and `plugins/` are
gitignored and nothing populated them. The registry already exists —
`manifest.json` at repo root lists every curated
`workspace-template-*`, `org-template-*`, and `plugin-*` repo, and
`scripts/clone-manifest.sh` clones them — but the step was absent
from the README and setup.sh, so new users never ran it.
### What this commit does
**1. `setup.sh` runs `clone-manifest.sh` automatically** (once).
After starting the Docker network but before booting infra, iterate
`manifest.json` and clone any workspace_templates / org_templates /
plugins that aren't already populated. Idempotent — subsequent
runs skip dirs that have content. Requires `jq`; when jq is missing
the step prints a clear install hint and skips (doesn't fail).
**2. `clone-manifest.sh` is idempotent.** Before running `git clone`,
check whether the target directory already exists and is non-empty —
skip if so. Lets `setup.sh` rerun safely without forcing the operator
to delete already-cloned template repos.
**3. `ListTemplates` logs the reason it skips a template.** The
handler previously swallowed `resolveYAMLIncludes` errors with
`continue`, so a broken template showed up as an empty palette with
no log trail. Now the include-expansion and yaml.Unmarshal failure
paths both emit a descriptive `log.Printf` — the exact message that
made the stale `org-templates/molecule-dev/` snapshot debuggable:
ListTemplates: skipping molecule-dev — !include expansion failed:
!include "core-platform.yaml" at line 25: open .../teams/
core-platform.yaml: no such file or directory
**4. Remove the in-tree `org-templates/molecule-dev/` snapshot** (170
files). Matches the explicit intent of prior commit
`bfec9e53` — "remove org-templates/molecule-dev/ — standalone repo
is source of truth". A later "full staging snapshot" re-added a
partial copy that had `!include` references to 7 role files that
never existed in the snapshot (`core-platform.yaml`,
`controlplane.yaml`, `app-docs.yaml`, `infra.yaml`, `sdk.yaml`,
`release-manager/workspace.yaml`, `integration-tester/workspace.yaml`).
`clone-manifest.sh` repopulates it fresh from
`Molecule-AI/molecule-ai-org-template-molecule-dev`.
.gitignore exception for `molecule-dev/` is dropped accordingly
— the whole `/org-templates/*` tree is now gitignored, symmetric
with `/plugins/` and `/workspace-configs-templates/`.
**5. Doc updates** (README, README.zh-CN, CONTRIBUTING) mention `jq`
as a prerequisite and describe what setup.sh now does.
### Verification
On a fresh-nuked DB with the updated branch:
1. `bash infra/scripts/setup.sh` — cleanly clones 33/33 manifest
repos (20 plugins, 8 workspace_templates, 5 org_templates), then
boots infra. Second run skips all 33 (idempotent).
2. `go run ./cmd/server` — "Applied 41 migrations", :8080 healthy.
3. `curl http://localhost:8080/org/templates` returns 4 templates
(was `[]`):
- Free Beats All
- MeDo Smoke Test
- Molecule AI Worker Team (Gemini)
- Reno Stars Agent Team
4. `bash tests/e2e/test_api.sh` — 61/61 pass.
5. `npx vitest run` in canvas — 902/902 pass.
6. `shellcheck infra/scripts/setup.sh` — clean.
### SaaS parity
All changes are local-dev surface. `setup.sh`, `clone-manifest.sh`,
and the local `org-templates/` directory aren't part of the CP
provisioner path — SaaS tenant machines get their templates via
Dockerfile layers or CP-side provisioning, not `clone-manifest.sh`.
The `ListTemplates` log addition is harmless either way (replaces a
silent `continue` with a `log.Printf + continue`).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.3 KiB
Contributing to Molecule AI
Thanks for your interest in contributing to Molecule AI! This guide covers the development workflow, conventions, and how to get your changes merged.
Getting Started
Prerequisites
- Go 1.25+ — platform backend
- Node.js 20+ — canvas frontend
- Python 3.11+ — workspace runtime
- Docker — infrastructure services (Postgres, Redis)
- Git — with hooks path set to
.githooks - jq — parses
manifest.jsonduringsetup.shto clone the template/plugin registry. Install viabrew install jq(macOS) orapt install jq(Debian). Without it, setup.sh prints a note and leaves the registry dirs empty (recoverable by installing jq and re-running).
Setup
# Clone the repo
git clone https://github.com/Molecule-AI/molecule-core.git
cd molecule-core
# Install git hooks
git config core.hooksPath .githooks
# Copy and edit .env (generate ADMIN_TOKEN + SECRETS_ENCRYPTION_KEY)
cp .env.example .env
# Start infrastructure (Postgres, Redis, Langfuse, Temporal)
./infra/scripts/setup.sh
# Build and run the platform — applies pending migrations on first boot
cd workspace-server
go run ./cmd/server
# In a separate terminal, run the canvas
cd canvas
npm install
npm run dev
Environment Variables
Copy .env.example to .env and fill in your values:
cp .env.example .env
See CLAUDE.md for a full list of environment variables and their purposes.
Development Workflow
Branch Naming
Use prefixed branches:
feat/— new featuresfix/— bug fixeschore/— maintenance, deps, CIdocs/— documentation only
Never push directly to main. All changes go through pull requests.
Commits
Write concise commit messages that focus on the "why":
fix(canvas): prevent infinite re-render on WebSocket reconnect
The useEffect dependency array included the entire nodes object,
causing a render loop when any node position changed.
Pull Requests
- Keep PRs focused — one concern per PR
- Include a test plan in the PR description
- PRs are merged with merge commits (not squash or rebase)
Running Tests
# Go (platform)
cd workspace-server && go test -race ./...
# Canvas (Next.js)
cd canvas && npm test
# Workspace runtime (Python)
cd workspace && python -m pytest -v
# E2E API tests (requires running platform)
bash tests/e2e/test_api.sh
Pre-commit Hooks
The .githooks/pre-commit hook enforces:
'use client'directive on React hook files- Dark theme only (no white/light CSS classes)
- No SQL injection patterns (
fmt.Sprintfwith SQL) - No leaked secrets (
sk-ant-,ghp_,AKIA)
Fix violations before committing — the hook will reject the commit.
CI Pipeline
CI runs on GitHub Actions with a self-hosted runner. External contributors: PRs from forks will not trigger CI automatically. A maintainer will review and run CI manually.
| Job | What it checks |
|---|---|
| platform-build | Go build + vet + go test -race |
| canvas-build | npm build + vitest |
| python-lint | pytest with coverage |
| e2e-api | Full API test suite (62 tests) |
| shellcheck | Shell script linting |
Code Style
Go (Platform)
- Standard
gofmtformatting go vetmust pass- No
fmt.Sprintfin SQL queries (use parameterized queries) - Prefer function injection over import cycles
TypeScript (Canvas)
- Strict mode enabled
- No
anytypes (useunknownor proper types) - Use
ConfirmDialogcomponent, never nativeconfirm/alert/prompt - Dark theme only — no white/light CSS classes
Python (Workspace Runtime)
- Type hints on public functions
- pytest for all tests
Architecture Overview
See CLAUDE.md for detailed architecture documentation, including:
- Component diagram (Platform, Canvas, Workspace Runtime)
- Key architectural patterns
- Database schema and migrations
- API route reference
Reporting Issues
Use GitHub Issues with a clear title and reproduction steps. Include:
- What you expected
- What actually happened
- Platform/OS version
- Relevant logs or screenshots
Security
If you discover a security vulnerability, please report it privately via GitHub Security Advisories rather than opening a public issue.
License
By contributing, you agree that your contributions will be licensed under the same Business Source License 1.1 that covers this project.