From 8e0f1e3a2852adc0050a20ccdbc0b28db77637d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Mon, 13 Apr 2026 09:28:59 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20add=20CONTRIBUTING.md=20=E2=80=94=20dev?= =?UTF-8?q?=20workflow,=20CI/CD,=20architecture,=20conventions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 小橘 🍊(NEKO Team) --- CONTRIBUTING.md | 215 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0623071 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,215 @@ +# Contributing to OGraph + +## Project Structure + +``` +packages/ + engine/ # CF Worker — API + Engine logic + UI + src/ + index.ts # Hono routes + middleware + engine.ts # Core engine functions (CRUD, projections, reactions) + types.ts # TypeScript interfaces + ui.html # Built UI (committed, auto-generated) + ui/ # React SPA (Vite + Tailwind + headless-ui) + src/ + App.tsx + api.ts + components/ + wrangler.toml + cli/ # CLI client (@uncaged/ograph-cli) + src/ + client.ts # HTTP client for OGraph API + commands/ # CLI commands (events, projections, reactions, etc.) + dispatcher/ # Local daemon — polls projections, notifies Agent + board/ # (experimental) Kanban board UI +``` + +## Prerequisites + +- Node.js 22+ +- npm (workspaces) +- Cloudflare account (for deployment) +- `wrangler` CLI (installed via npm) + +## Setup + +```bash +git clone https://github.com/oc-xiaoju/ograph.git +cd ograph +npm install +``` + +UI has its own dependencies: +```bash +cd packages/engine/ui +npm install +``` + +## Development Workflow + +### Engine (API + Core Logic) + +```bash +cd packages/engine +npm run dev # Local dev server (wrangler dev) +npm test # Run tests (vitest, 105+ tests) +``` + +### UI (React SPA) + +```bash +cd packages/engine/ui +npm run dev # Vite dev server (hot reload) +npm run build # Build → dist/index.html (single-file) +``` + +After building UI, copy to engine: +```bash +cp packages/engine/ui/dist/index.html packages/engine/src/ui.html +``` + +### CLI + +```bash +cd packages/cli +npm run build # TypeScript compile +npm test # Run tests (vitest, 31+ tests) +npm run dev # Watch mode +``` + +### Run All Tests + +```bash +npm test # Runs tests across all workspaces +``` + +## CI/CD + +**Pipeline:** `.github/workflows/ci.yml` + +On every push to `main`: +1. **Test** — `npm install` → `npm test` (all workspaces) +2. **Deploy** — Build UI → copy `ui.html` → `wrangler deploy` to Cloudflare Workers + +On pull requests: +1. **Test** only (no deploy) + +### Secrets (GitHub Actions) + +| Secret | Description | +|--------|-------------| +| `CLOUDFLARE_API_TOKEN` | Wrangler deploy auth | +| `CLOUDFLARE_ACCOUNT_ID` | CF account | + +### Production URL + +- API: `https://ograph.shazhou.workers.dev` +- UI: `https://ograph.shazhou.workers.dev/ui` + +## Commit Conventions + +Format: `type(scope): description` + +Types: `feat`, `fix`, `refactor`, `ci`, `docs`, `test`, `chore` + +Scopes: `engine`, `cli`, `ui`, `dispatcher`, `board` + +Examples: +``` +feat(engine): add incremental event query with ?after=N +fix(ui): Projection ref params now filter objects by matching type +ci: add CD — auto deploy to Cloudflare Workers on push to main +``` + +Sign commits: +``` +小橘 🍊(NEKO Team) +小墨 🖊️(KUMA Team) +``` + +Git config: +```bash +git config user.name "小橘" +git config user.email "xiaoju@shazhou.work" +``` + +## Architecture Notes + +### Engine (Cloudflare Worker) + +- **Runtime:** Cloudflare Workers (D1 database, Hono framework) +- **Auth:** API Key in `Authorization: Bearer ogk_xxx` header +- **UI:** Single HTML file served at `/ui`, built with Vite singlefile plugin +- **Logs:** Request logs auto-cleaned (7-day retention via `waitUntil`) + +### Key Design Decisions + +- **Snake_case everywhere** — API, DB, event names (`task_created`, not `taskCreated`) +- **Event names:** `{object}_{past_participle}` (e.g. `task_created`, `comment_added`) +- **Params use `_id` suffix** — `task_id`, `agent_id` +- **Content-addressed hashing** — defs are immutable versions identified by hash +- **Projection health:** expression errors → `errored` status, returns stale value, no reaction triggered +- **Lazy computation:** projections compute on query, not on event emit + +### UI Routing + +Hash-based routing (`#/events`, `#/reaction-logs`). No react-router dependency — hand-rolled. + +Pages: +| Route | Page | +|-------|------| +| `#/health` | Health dashboard | +| `#/object-defs` | Object type definitions | +| `#/objects` | Object instances | +| `#/event-defs` | Event type definitions | +| `#/events` | Event log | +| `#/projection-defs` | Projection definitions | +| `#/projections` | Query projections | +| `#/reactions` | Reaction definitions | +| `#/reaction-logs` | Reaction execution logs | +| `#/request-logs` | API request logs | +| `#/api-keys` | API key management | + +### D1 Storage + +- Free tier: 500 MB storage, 5M reads/writes per month +- TEXT fields: no length limit (SQLite underneath, ~1 MB per row) +- Logs: auto-pruned after 7 days +- Events: append-only, never deleted + +### Testing + +Engine tests use miniflare (local D1). Tests cover: +- CRUD for all entity types (object defs, event defs, projection defs, etc.) +- Projection computation + incremental reduce +- Reaction execution + handler sandboxing +- API key auth + permissions +- Error handling + edge cases + +To add a test, edit `packages/engine/src/index.test.ts`. + +## Manual Deploy (if needed) + +```bash +cd packages/engine +# Build UI first +cd ui && npm run build && cp dist/index.html ../src/ui.html && cd .. +# Deploy +npx wrangler deploy +``` + +Requires `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` env vars. + +## D1 Database Access + +```bash +# Query production D1 +npx wrangler d1 execute ograph --remote --command "SELECT COUNT(*) FROM events" + +# Time Travel (point-in-time recovery) +npx wrangler d1 time-travel ograph --before +``` + +--- + +*Built by 小橘 🍊 & 小墨 🖊️ — NEKO + KUMA Teams*