diff --git a/.cursor/skills/ode-custom-app-form-validation/SKILL.md b/.cursor/skills/ode-custom-app-form-validation/SKILL.md new file mode 100644 index 000000000..50f5136dc --- /dev/null +++ b/.cursor/skills/ode-custom-app-form-validation/SKILL.md @@ -0,0 +1,28 @@ +--- +name: ode-custom-app-form-validation +description: >- + Helps validate ODE custom app form definitions (JSON Schema draft-07 + UI schema) + and CI integration. Use when the user asks to validate forms, add validate-forms + scripts, or check schema/ui consistency for Synkronus bundles. Prefer official docs + at opendataensemble.org and the custom-app template repo on GitHub. +--- + +# ODE custom app — form validation + +## When to use + +- Adding or maintaining **`schema.json`** / **`ui.json`** for ODE custom apps. +- Setting up **CI** to fail on invalid forms. +- Explaining **draft-07**, `scope` references, or ODE-specific **`format`** rules. + +## What to do + +1. Point to **[Form specifications](https://opendataensemble.org/docs/reference/form-specifications)** as the normative reference for question types and UI structure. +2. Ensure **UI `scope`** paths match **JSON Schema** properties; **`required`** arrays align with product intent. +3. For automation, describe a **Node** (or other) script pattern: load each form folder, `JSON.parse`, validate schema with a draft-07 validator, and check structural rules (both files present, cross-references). Link **[custom_app](https://github.com/OpenDataEnsemble/custom_app)** for AI context, not as a code dependency. +4. Do **not** invent Synkronus-specific validation rules beyond public docs. + +## Official links + +- [Form specifications](https://opendataensemble.org/docs/reference/form-specifications) +- [Custom applications](https://opendataensemble.org/docs/guides/custom-applications) diff --git a/.cursor/skills/ode-custom-jsonforms-extension/SKILL.md b/.cursor/skills/ode-custom-jsonforms-extension/SKILL.md new file mode 100644 index 000000000..3be3da89d --- /dev/null +++ b/.cursor/skills/ode-custom-jsonforms-extension/SKILL.md @@ -0,0 +1,26 @@ +--- +name: ode-custom-jsonforms-extension +description: >- + Guides adding ODE custom JSON Forms extensions (custom renderers, testers, ext.json, + dynamic functions). Use when extending forms with non-standard controls or wiring + extension manifests. Official behavior is documented on opendataensemble.org. +--- + +# ODE custom JSON Forms extensions + +## When to use + +- Custom **control** rendering (tester + renderer pattern). +- **`ext.json`** (or app-level extension manifest) and module paths. +- **Dynamic choice lists** or helper **functions** referenced from the UI schema. + +## What to do + +1. Read **[Custom extensions](https://opendataensemble.org/docs/guides/custom-extensions)** and **[Dynamic choice lists](https://opendataensemble.org/docs/guides/dynamic-choice-lists)** on the docs site. +2. Keep **bundled JS** compatible with the Formulus WebView (no Node-only APIs in runtime code). +3. Align **`format`** in schema with the renderer contract described in docs. +4. For AI-only context summaries, **[CONTEXT_ODE_FORMS.md](https://github.com/OpenDataEnsemble/custom_app/blob/main/CONTEXT_ODE_FORMS.md)** in **custom_app** may help — still verify against **opendataensemble.org**. + +## Do not + +- Assume vanilla **jsonforms.io** examples work without checking ODE’s registered renderers and extension loading rules. diff --git a/.cursor/skills/ode-synk-bundle-publish/SKILL.md b/.cursor/skills/ode-synk-bundle-publish/SKILL.md new file mode 100644 index 000000000..2b4e1ddf9 --- /dev/null +++ b/.cursor/skills/ode-synk-bundle-publish/SKILL.md @@ -0,0 +1,27 @@ +--- +name: ode-synk-bundle-publish +description: >- + Guides publishing and managing ODE app bundles with the Synkronus CLI (synk): + config, auth, upload, versions. Use when deploying custom app zips or automating + bundle uploads. Official reference is opendataensemble.org and OpenDataEnsemble/ode docs. +--- + +# Synkronus CLI — app bundle publish + +## When to use + +- Uploading a **custom app** ZIP to Synkronus. +- Managing **bundle versions** or scripting **CI** upload steps. +- Configuring **`synk`** (`~/.synkronus.yaml`, `synk config use`, etc.). + +## What to do + +1. Use **[Synkronus CLI](https://opendataensemble.org/docs/reference/synkronus-cli)** as the primary command reference. +2. Ensure the ZIP matches **[App bundle format](https://opendataensemble.org/docs/reference/app-bundle-format)** before upload. +3. Store **API URLs and tokens** in CI secrets; never embed production credentials in source. +4. For bundle structure reminders, see **[CONTEXT_BUNDLE_AND_CI.md](https://github.com/OpenDataEnsemble/custom_app/blob/main/CONTEXT_BUNDLE_AND_CI.md)** in **custom_app** (summary only). + +## Related + +- [App bundles (using)](https://opendataensemble.org/docs/using/app-bundles) +- [Deployment](https://opendataensemble.org/docs/guides/deployment) diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..63ae952d5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,91 @@ +# Open Data Ensemble (ODE) — AI and developer guide + +This monorepo contains the core platform for **offline-first data collection** and **synchronization**. Use this file when you work across packages or need the big picture. For deep dives, open the **`AGENTS.md`** in the package you are changing. + +**Published architecture (users and external readers):** [Architecture overview](https://opendataensemble.org/docs/getting-started/architecture-overview) on [opendataensemble.org](https://opendataensemble.org/). + +--- + +## Ecosystem map + +ODE is a **clearinghouse** model: data is collected on devices, synchronized through **Synkronus**, and is intended to **flow through** the system for local analysis and stewardship—not to live only on the server. + +- **Formulus** — React Native mobile app: runs forms (JSON Forms) and **custom app bundles** in WebViews, offline-first, syncs with Synkronus. +- **Formulus Formplayer** — React web app embedded in Formulus: renders forms inside a WebView; shares the same bridge contract as custom apps. +- **Synkronus** — Go backend: auth, sync, app bundle distribution, export, shared HTTP API. +- **Synkronus Portal** — Web admin UI (React + Vite): same API as other clients; no privileged backend channel. +- **Synkronus CLI** — `synk` command-line client: automation, bundles, sync, export. + +```mermaid +flowchart LR + Formulus[Formulus_RN] + Formplayer[Formulus_Formplayer] + Synkronus[Synkronus_API] + Portal[Portal] + CLI[CLI] + Formulus -->|sync| Synkronus + Portal -->|same_API| Synkronus + CLI -->|same_API| Synkronus + Formulus -->|hosts_WebView| Formplayer +``` + +**Design principle:** [One backend, many clients](https://opendataensemble.org/docs/getting-started/architecture-overview) — prefer the public API for all user-facing tools. + +--- + +## User profiles (what to optimize for) + +| Profile | Typical focus | Where to work | +|--------|----------------|---------------| +| **Platform developer** | You are editing **this repo**: RN, Go, React, shared packages, CI. | Package `AGENTS.md` below. | +| **Custom app author** | You ship an **HTML/JS/CSS** app bundle and JSON forms for Formulus; you may **not** clone this monorepo. | [Custom app template (AI + author context)](https://github.com/OpenDataEnsemble/custom_app) and [documentation](https://opendataensemble.org/docs/). | + +Do not assume custom app authors have local checkouts of **ODE** or internal example repos. + +--- + +## Monorepo layout + +| Package | Role | Stack | Agent guide | +|---------|------|-------|-------------| +| [formulus](formulus/) | Mobile runtime, WebViews, native bridge | React Native | [formulus/AGENTS.md](formulus/AGENTS.md) | +| [formulus-formplayer](formulus-formplayer/) | Form UI in WebView | React, Vite, JSON Forms | [formulus-formplayer/AGENTS.md](formulus-formplayer/AGENTS.md) | +| [synkronus](synkronus/) | Sync API and coordination | Go | [synkronus/AGENTS.md](synkronus/AGENTS.md) | +| [synkronus-cli](synkronus-cli/) | CLI for API operations | Go | [synkronus-cli/AGENTS.md](synkronus-cli/AGENTS.md) | +| [synkronus-portal](synkronus-portal/) | Web administration | React, TypeScript, Vite | [synkronus-portal/AGENTS.md](synkronus-portal/AGENTS.md) | +| [packages/tokens](packages/tokens/) | Design tokens (`@ode/tokens`) | Style Dictionary | [packages/tokens/AGENTS.md](packages/tokens/AGENTS.md) | +| [packages/components](packages/components/) | Shared UI (`@ode/components`) | React | [packages/components/AGENTS.md](packages/components/AGENTS.md) | + +--- + +## Cross-cutting contracts + +- **Formulus ↔ WebView (custom apps + formplayer):** [`formulus/src/webview/FormulusInterfaceDefinition.ts`](formulus/src/webview/FormulusInterfaceDefinition.ts) is the **source of truth** for the injected JavaScript API. Formplayer copies a synced TypeScript snapshot via `npm run sync-interface` in `formulus-formplayer` (see [formulus-formplayer/AGENTS.md](formulus-formplayer/AGENTS.md)). +- **Shared UI tokens:** Install **tokens** before **components** / **formplayer** where the docs require it (see package READMEs and formplayer AGENTS). + +--- + +## CI and code quality + +- **Pipelines:** [.github/CICD.md](.github/CICD.md). +- **Lint/format:** Run the relevant scripts in the **package you touch** (see root [README.md](README.md) and each package). +- **Commits/PRs:** Conventional Commits and PR expectations are documented in [formulus-formplayer/AGENTS.md](formulus-formplayer/AGENTS.md) (project-wide convention). + +--- + +## Planned (not shipped here) + +Do **not** implement or assume APIs for these as if they were in-repo unless issues/specs say otherwise: + +- **ODE Custodian** — local data stewardship and correction workflows (roadmap; often CLI-first). +- **ODE Workshop** — desktop dev environment for bundles/forms (roadmap). + +See [product roadmap context](https://opendataensemble.org/docs/) and organization roadmaps on [GitHub](https://github.com/OpenDataEnsemble). + +--- + +## Custom app authors (pointer) + +Authoritative **public** documentation: [opendataensemble.org](https://opendataensemble.org/docs/). + +Optional **AI-focused** context (no ODE clone required): [custom_app](https://github.com/OpenDataEnsemble/custom_app) on GitHub (`README.md`, `AGENTS.md`, `CONTEXT_*.md`). diff --git a/formulus-formplayer/AGENTS.md b/formulus-formplayer/AGENTS.md index bbe857dd7..b37a00343 100644 --- a/formulus-formplayer/AGENTS.md +++ b/formulus-formplayer/AGENTS.md @@ -1,5 +1,7 @@ # Formulus Formplayer — AI & Developer Guide +**Monorepo:** See also [../AGENTS.md](../AGENTS.md) for the full ODE map and cross-package contracts. + This file gives AI assistants and developers enough context to work effectively in this repo. For user-facing docs, see [README.md](./README.md). ## What this project is diff --git a/formulus/AGENTS.md b/formulus/AGENTS.md new file mode 100644 index 000000000..caa9ba4eb --- /dev/null +++ b/formulus/AGENTS.md @@ -0,0 +1,46 @@ +# Formulus — AI & developer guide + +**When to use this doc:** You are changing the **React Native** mobile app: navigation, screens, WebViews, native modules, or the JavaScript bridge injected into custom apps and the formplayer. + +**See also:** [../AGENTS.md](../AGENTS.md) (monorepo overview), [../formulus-formplayer/AGENTS.md](../formulus-formplayer/AGENTS.md) (form UI bundle and WebView constraints). + +**User-facing docs:** [Formulus](https://opendataensemble.org/docs/reference/formulus) on [opendataensemble.org](https://opendataensemble.org/). + +--- + +## What this package is + +- **Formulus** is the **offline-first** mobile client for ODE: it renders **JSON Forms** via the embedded **formplayer** WebView, runs **custom application** bundles in separate WebViews, and synchronizes with **Synkronus**. +- It is **not** the admin console (that is **Portal**) and not the sync server (that is **Synkronus**). + +--- + +## Layout (where to look) + +| Area | Purpose | +|------|---------| +| `src/webview/` | **Bridge contract** — [`FormulusInterfaceDefinition.ts`](src/webview/FormulusInterfaceDefinition.ts) (source of truth for `window.formulus` / injected API). [`FormulusMessageHandlers.ts`](src/webview/FormulusMessageHandlers.ts), [`FormulusWebViewHandler.ts`](src/webview/FormulusWebViewHandler.ts). | +| `scripts/generateInjectionScript.ts` | Generates injection / loader script from the interface definition. | +| `src/screens/`, `src/navigation/` | App screens and routing. | +| Android / iOS | Native projects; **formplayer** static assets: `android/app/src/main/assets/formplayer_dist/`, `ios/formplayer_dist/` (see formplayer AGENTS for `build:rn`). | + +--- + +## Custom apps and formplayer + +- **Custom apps** are HTML/JS/CSS bundles loaded from Synkronus; they receive the **Formulus** injected API (see interface definition). Authors do not need this monorepo — public docs and [custom_app](https://github.com/OpenDataEnsemble/custom_app) describe usage. +- **Formplayer** is a sibling package; after changing `FormulusInterfaceDefinition.ts`, run **`npm run sync-interface`** (or build) in **formulus-formplayer** so its copy stays aligned. + +--- + +## Changing the bridge + +1. Edit [`FormulusInterfaceDefinition.ts`](src/webview/FormulusInterfaceDefinition.ts). +2. Implement **native** handling in the WebView message pipeline. +3. **Sync** the formplayer copy and update any consumers (see [formulus-formplayer/AGENTS.md](../formulus-formplayer/AGENTS.md)). + +--- + +## Build and run + +See [README.md](README.md): Metro, `npm run android` / `ios`, Android **Notifee** vendor step, iOS **Pods**. For CI and formatting, see root [README.md](../README.md) and [.github/CICD.md](../.github/CICD.md). diff --git a/packages/components/AGENTS.md b/packages/components/AGENTS.md new file mode 100644 index 000000000..c2c38c385 --- /dev/null +++ b/packages/components/AGENTS.md @@ -0,0 +1,26 @@ +# @ode/components — AI & developer guide + +**When to use this doc:** You are changing **shared React UI** consumed by Portal or other ODE frontends. + +**See also:** [../../AGENTS.md](../../AGENTS.md). **Tokens:** [../tokens/AGENTS.md](../tokens/AGENTS.md). + +**User-facing docs:** [Components](https://opendataensemble.org/docs/reference/components) on [opendataensemble.org](https://opendataensemble.org/). + +--- + +## What this package is + +- **`@ode/components`** is shared UI built on **React** and **@ode/tokens** (and related styling patterns). Prefer **tokens** over hard-coded colors/spacing where a token exists. + +--- + +## Scope + +- **Change here** when the component is **reusable** across apps (Portal, future web UIs). +- **Change in Portal only** when the UI is **Portal-specific** (single-app layout, admin-only flows). + +--- + +## Build / dev + +See [README.md](README.md): `npm install`, storybook or dev commands as documented. Keep **lint/format** consistent with the rest of the monorepo (see root [README.md](../../README.md)). diff --git a/packages/tokens/AGENTS.md b/packages/tokens/AGENTS.md new file mode 100644 index 000000000..c0b21a8c6 --- /dev/null +++ b/packages/tokens/AGENTS.md @@ -0,0 +1,26 @@ +# @ode/tokens — AI & developer guide + +**When to use this doc:** You are changing **design tokens** (colors, spacing, typography) built with **Style Dictionary**, or fixing build issues for downstream packages. + +**See also:** [../../AGENTS.md](../../AGENTS.md). **Consumers:** [formulus-formplayer](../../formulus-formplayer/AGENTS.md), [components](../components/README.md). + +**User-facing docs:** [Components](https://opendataensemble.org/docs/reference/components) (tokens usage appears in the broader UI system). + +--- + +## What this package is + +- **`@ode/tokens`** outputs token artifacts used by **formulus-formplayer** (theme) and **@ode/components** (shared UI). + +--- + +## Build + +- From `packages/tokens/`: `npm install`, then `npm run build` (or the `prepare` script as invoked by npm). +- **Order:** Other packages **depend on tokens built** — install tokens before formplayer/components when setting up a fresh clone (see formplayer AGENTS). + +--- + +## Changing tokens + +- Edit tokens in `src/` (see [README.md](README.md) for structure), rebuild, then verify consumers (formplayer theme, components) for visual regressions. diff --git a/synkronus-cli/AGENTS.md b/synkronus-cli/AGENTS.md new file mode 100644 index 000000000..b56309242 --- /dev/null +++ b/synkronus-cli/AGENTS.md @@ -0,0 +1,32 @@ +# Synkronus CLI — AI & developer guide + +**When to use this doc:** You are changing the **`synk`** command-line tool (Go) or its packaging. + +**See also:** [../AGENTS.md](../AGENTS.md). + +**User-facing docs:** [Synkronus CLI](https://opendataensemble.org/docs/reference/synkronus-cli) on [opendataensemble.org](https://opendataensemble.org/). + +--- + +## What this package is + +- **synkronus-cli** provides **`synk`** — scriptable access to the same Synkronus **HTTP API** as Portal and Formulus: login, sync, app bundle upload/download, export (e.g. Parquet), config. + +--- + +## Layout + +- **Entry:** `cmd/synkronus/` (or as structured in this repo — see `README.md`). +- **Config:** `~/.synkronus.yaml` by default; `synk config use` for multiple profiles (see [README.md](README.md)). + +--- + +## License note + +The CLI may be **GPL-2.0-or-later** until the QR dependency cleanup described in the root [README.md](../README.md) and [FOLLOWUP-custom-qrcode-writer.md](FOLLOWUP-custom-qrcode-writer.md). **Do not** change license without maintainer intent. + +--- + +## Install / build + +From [README.md](README.md): `go install`, or build from source. Installation scripts are linked from the root [README.md](../README.md). diff --git a/synkronus-portal/AGENTS.md b/synkronus-portal/AGENTS.md new file mode 100644 index 000000000..5c73bc394 --- /dev/null +++ b/synkronus-portal/AGENTS.md @@ -0,0 +1,27 @@ +# Synkronus Portal — AI & developer guide + +**When to use this doc:** You are changing the **React + TypeScript + Vite** web UI that administers Synkronus (users, bundles, exports, observations). + +**See also:** [../AGENTS.md](../AGENTS.md) (monorepo map). **Backend:** [../synkronus/AGENTS.md](../synkronus/AGENTS.md). + +**User-facing docs:** [Synkronus Portal](https://opendataensemble.org/docs/reference/synkronus-portal) on [opendataensemble.org](https://opendataensemble.org/). + +--- + +## What this package is + +- **Portal** is a **standard API client** of Synkronus — same REST surface as the CLI; no special server-side shortcuts. +- **Dev:** Vite dev server with hot reload; **prod:** static build served (often via Docker/nginx in this repo’s compose setup). + +--- + +## Operational details + +- **Setup, Docker vs dockerless, ports, troubleshooting:** See [README.md](README.md) — it is the canonical long-form guide (this file avoids duplicating it). +- **API proxy:** Dev typically proxies `/api` to the Go backend (see `vite.config.ts`). + +--- + +## Quick commands + +From `synkronus-portal/`: `npm install`, `npm run dev`, `npm run lint`, `npm run format` — align with root [README.md](../README.md) and CI. diff --git a/synkronus/AGENTS.md b/synkronus/AGENTS.md new file mode 100644 index 000000000..34dac6868 --- /dev/null +++ b/synkronus/AGENTS.md @@ -0,0 +1,40 @@ +# Synkronus — AI & developer guide + +**When to use this doc:** You are working on the **Go** HTTP API: sync, auth, app bundles, export, attachments, or database layer. + +**See also:** [../AGENTS.md](../AGENTS.md). + +**User-facing docs:** [Synkronus server](https://opendataensemble.org/docs/reference/synkronus-server), [REST API](https://opendataensemble.org/docs/reference/rest-api/overview), deployment guides linked from the docs site. + +--- + +## What this package is + +- **Synkronus** is the **central synchronization and coordination service** for ODE: JWT auth, pull/push sync, app bundle storage, exports, attachments. +- **Clients** (Formulus, Portal, CLI) all use the **same** public API — no hidden admin-only backdoors. + +--- + +## Layout + +``` +cmd/synkronus/ # Entry point +internal/ # api, handlers, models, repository, services +pkg/ # Shared libraries (auth, database, middleware, openapi, ...) +``` + +- **OpenAPI / Swagger:** typically served under `/openapi` (see running server and [README.md](README.md)). + +--- + +## Local development + +- **Prerequisites:** Go 1.22+, PostgreSQL, configured env (see [README.md](README.md) and [DOCKER.md](DOCKER.md)). +- **Run:** `go run cmd/synkronus/main.go` (or build from `cmd/synkronus`) with a valid `DB_CONNECTION` and secrets. +- **Docker:** [DOCKER.md](DOCKER.md); production patterns in [DEPLOYMENT.md](DEPLOYMENT.md). + +--- + +## Related repos + +- **Synkronus Portal** and **CLI** live in this monorepo as **clients** of this API — see their `AGENTS.md` files.