From 06bdc2a6e7004d9938ca25708654522b3e94f007 Mon Sep 17 00:00:00 2001 From: Leon Cheng Date: Fri, 21 Aug 2026 18:04:05 -0400 Subject: [PATCH] docs: add contributor guide --- CONTRIBUTING.md | 167 ++++++++++++++ README.md | 2 + docs/contributing/index.html | 432 +++++++++++++++++++++++++++++++++++ 3 files changed, 601 insertions(+) create mode 100644 CONTRIBUTING.md create mode 100644 docs/contributing/index.html diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..29ff0500 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,167 @@ +# Contributing + +Thank you for improving custom-dca-opencode. This guide covers the repository's +development workflow and the checks that pull requests must pass. + +Use the self-contained [visual reading index](docs/contributing/index.html) to choose a +contributor pathway, or continue here for the canonical workflow. + +## Before you start + +You need: + +- Node.js 22 or newer +- npm +- A local OpenCode server at the version pinned in + [`server/opencode/client.ts`](server/opencode/client.ts) for interactive development + +The application runs directly on the host. It does not use Docker, and the development +script does not start OpenCode for you. + +## Set up the repository + +Install the locked dependencies and create a local environment file: + +```bash +npm install +cp .env.example .env +``` + +Review [`.env.example`](.env.example) before starting the app. At minimum, +`OPENCODE_URL` must point to a reachable OpenCode server. `PROJECTS_DIR` and +`OPENCODE_WORKTREE_ROOT` define the only roots from which the BFF accepts workspace +paths. + +Start the BFF and Vite development server together: + +```bash +npm run dev +``` + +The script checks OpenCode's `/global/health` endpoint and verifies that the BFF port is +available before starting either watcher. By default, OpenCode uses port 4096, the BFF +uses port 3000, and Vite uses port 5173. You can also run the watchers separately with +`npm run dev:server` and `npm run dev:ui`. + +For deployment and macOS LaunchAgent instructions, see +[`deploy/README.md`](deploy/README.md). Those commands are not required for ordinary +development. + +## Understand the boundaries + +The request path is: + +```text +Browser -> React/Vite SPA -> Express BFF -> opencode serve +``` + +- [`client/`](client/) contains the React SPA and design-system primitives. +- [`server/`](server/) contains API routes, credentials, directory validation, SSE + fan-out, local git operations, notifications, and forge integrations. +- [`server/opencode/client.ts`](server/opencode/client.ts) is the typed fetch boundary for + the OpenCode API. Treat the live OpenCode `/doc` response as the contract when that + API changes. +- [`client/lib/events.ts`](client/lib/events.ts) maps raw OpenCode parts to the + backend-neutral transcript model. Transcript rows should not consume raw OpenCode + `Part` objects. +- [`tests/`](tests/) contains Vitest tests and fixtures. +- [`tests/e2e/`](tests/e2e/) contains Playwright tests and deterministic mock servers. + +Keep browser-facing requests same-origin through the BFF. Do not expose OpenCode or +third-party credentials to the client. Preserve directory canonicalization and preview +proxy restrictions when changing routes that touch the host filesystem or local +services. + +## Follow repository conventions + +- Keep TypeScript strict and match the surrounding module style. +- Use `.js` suffixes when tests import TypeScript modules, as required by the ESM build. +- Keep reusable primitives in [`client/ds/`](client/ds/) based on `forwardRef`, `cn()`, + and semantic `var(--color-*)` tokens. Do not add raw color values. +- Add a `data-testid` to every interactive element so deterministic UI tests can target + it. +- Keep every root theme token paired with a dark-mode value. +- Tolerate unknown OpenCode event types. The global event stream includes events outside + the local typed union. +- Use the asynchronous prompt path for UI requests; the blocking message endpoint holds + the connection for the full agent turn. +- Avoid new runtime dependencies unless the change genuinely requires one and its reason + is recorded in [`AGENTS.md`](AGENTS.md). + +There is no configured formatter or linter. Keep edits focused and follow the formatting +already used in the file you change. + +## Add and run tests + +Add focused tests with behavior changes: + +- Vitest discovers `tests/**/*.test.ts` and runs in a Node environment. +- Playwright exercises the built SPA and real BFF against the mock OpenCode and preview + servers in [`tests/e2e/`](tests/e2e/). +- End-to-end tests do not need a live agent, model credentials, or network access. + +Run the same functional checks used by CI: + +```bash +npm run typecheck +npm test +npm run build +npm run test:e2e +``` + +`npm run test:e2e` builds the production bundle automatically. A first local Playwright +run may require the Chromium binary: + +```bash +npx playwright install chromium +``` + +CI installs Chromium with its operating-system dependencies before running the suite. +Failed CI runs upload the Playwright report as an artifact. + +## Prepare a pull request + +Before opening a pull request: + +1. Rebase or merge the latest `main` without force-pushing shared work. +2. Review `git diff` and `git status` for unrelated files and secrets. +3. Run the typecheck, unit tests, build, and end-to-end tests listed above. +4. Explain the behavior changed and list the verification performed. + +Pull requests run the full verification sequence and a full-history Gitleaks scan. Do +not commit `.env`, credentials, local state, generated build output, Playwright reports, +or screenshot output. + +### Request deterministic UI screenshots + +For a UI change, add one fenced `screenshots` block to the pull request body with one +root-relative route per line: + +````markdown +```screenshots +/?directory=/tmp/mock-project +full:/sessions/ses_mock_done?directory=/tmp/mock-project +``` +```` + +The workflow accepts up to ten known application routes and captures dark-mode desktop +and mobile images against deterministic mocks. Prefix a route with `full:` to capture +its full scroll height. Reproduce the fixture request locally with: + +```bash +npm run screenshots:local +``` + +Output is written to the ignored `screenshot-output/` directory. See the +[`README.md`](README.md#pr-screenshots) for route validation, fork, publication, and +troubleshooting details. + +## Security-sensitive changes + +OpenCode tools execute on the host as the current user. Changes involving permissions, +workspace paths, credentials, the preview proxy, session sharing, or workflow privileges +need explicit tests for their security boundaries. Keep broad permission rules before +specific overrides because OpenCode permission matching is last-match-wins. + +Report a suspected vulnerability privately to the repository owner rather than opening +a public issue with exploit details. diff --git a/README.md b/README.md index 5386d0d3..43af5b94 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ paths containing spaces, and the optional OpenCode unit. The BFF installer never starts a second OpenCode server; it uses `OPENCODE_URL` from `.env`. The OpenCode 1.18.21 compatibility check is recorded in [`docs/opencode-1.18.21-api-audit.md`](docs/opencode-1.18.21-api-audit.md). +See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the development and pull request workflow. +The same contributor material has a themed [visual reading index](docs/contributing/index.html). ### Open on a phone diff --git a/docs/contributing/index.html b/docs/contributing/index.html new file mode 100644 index 00000000..92b63d28 --- /dev/null +++ b/docs/contributing/index.html @@ -0,0 +1,432 @@ + + + + + + + + Contributor Control Plane | custom-dca-opencode + + + + +
+ Contributor control plane + custom-dca-opencode + +
+ + + +
+
+ +
+
+
+
Engineering entry point / host-native agent IDE
+

Find the seam.
Prove the change.

+

A visual routing layer for contributors. Choose the path that + matches your change, follow evidence into the repository, and use the canonical + Markdown guides for complete instructions.

+
+ +
+ +
+
22+Node runtimeThe same major version used by CI.
+
3Runtime layersReact SPA, Express BFF, OpenCode server.
+
4Core checksTypes, unit tests, production build, E2E.
+
0Live keys for E2EDeterministic mocks replace external services.
+
+ +
+ + +
+
+
+ 01 / Contributor pathways +

Start where ownership lives

+

Changes are safest when they preserve the existing boundary between raw + OpenCode data, the BFF, and backend-neutral client models.

+
+
+
+ Orientation +

First contribution

+

Set up Node and the environment, learn the request path, then run the + complete local gate before proposing a pull request.

+ Open the canonical workflow +
package.json.env.example.github/workflows/ci.yml
+
+
+ Interface +

Client and transcript work

+

Keep raw OpenCode parts behind the event adapter. Reuse design-system + primitives, semantic color tokens, and deterministic test IDs.

+ Read client conventions +
client/lib/events.tsclient/ds/client/theme/
+
+
+ Control plane +

BFF and OpenCode API work

+

Preserve directory scoping, credential isolation, asynchronous prompts, + tolerant event handling, and the typed fetch seam.

+ Review the API compatibility audit +
server/opencode/client.tsserver/paths.tsserver/routes/
+
+
+ Operations +

Host and deployment work

+

The BFF and OpenCode are host processes, not containers. Follow the + LaunchAgent, Tailscale, logging, and port guidance before changing service behavior.

+ Open the deployment guide +
scripts/launchd.tsdeploy/.env.example
+
+
+
+ +
+
+ 02 / Verification gate +

Evidence before confidence

+

The Playwright suite runs the built application and real BFF against local + mocks. It does not require a running OpenCode stack, model access, or API keys.

+
+
+
npm run typecheck
+npm test
+npm run build
+npm run test:e2e
+
+ Before review +
    +
  1. Inspect the complete diff.
  2. +
  3. Check repository-relative links and paths.
  4. +
  5. Confirm no secrets or generated output are staged.
  6. +
  7. Describe behavior and verification in the PR.
  8. +
+
+
+
+ +
+
+ 03 / Canonical reading index +

Follow the evidence trail

+

These Markdown files own the detailed instructions and technical records. + All links are relative so this index works directly from a local checkout.

+
+
+
CONTRIBUTING.md

Contribution workflow

Setup, architecture boundaries, conventions, tests, pull requests, screenshots, and security-sensitive changes.

+
README.md

Project orientation

Purpose, requirements, quick start, feature behavior, architecture, safety model, and PR screenshot contract.

+
AGENTS.md

Implementation memory

Verified OpenCode API traps, accepted design decisions, client conventions, and automation constraints.

+
deploy/README.md

Deployment operations

LaunchAgent installation, logs, upgrades, Tailscale Serve, paths with spaces, and OpenCode process management.

+
docs/opencode-1.18.21-api-audit.md

API compatibility audit

Measured compatibility evidence for the pinned OpenCode server surface.

+
docs/research/README.md

Architecture research

Decision records and source material behind the migration to the host-native OpenCode architecture.

+
reminders/README.md

Reminder catalogue

Runtime reminder format, validation rules, IDs, and links to each canonical reminder skill guide.

+
+
+ +
+
+ 04 / Safety boundary +

The host is the runtime

+
+
+

OpenCode tools execute as the current host user.

+

Permission, path, preview, credential, sharing, and workflow changes need + explicit boundary tests. Permission rules are last-match-wins: broad rules + come first and specific overrides follow.

+
+
+
+
+
+ + + + + +