Contributing to Terranoetis
Development Setup
Prerequisites
- Node.js 20+
- Redis 7+ (optional for dev — the server falls back to SQLite automatically)
- A
.envfile with your API keys (copy from.env.example)
Quick Start
# Install dependencies
npm install
# Copy and configure environment
cp .env.example .env
# Edit .env with your API keys (see .env.example for documentation)
# Start all services (client + server + Redis)
npm run dev
The client runs on http://localhost:3000 and the server on http://localhost:3001.
Running Tests
# Unit + integration tests
npm test # vitest — 1,702 tests (1,653 unit + 49 integration)
# TypeScript type checking
npx tsc -p tsconfig.server.json --noEmit
npx tsc -p tsconfig.app.json --noEmit
# Lint
npm run lint # eslint — 0 errors required
# E2E browser tests
npx playwright test # 7 spec files, headless Chromium
# Build
npm run build # tsc + vite build
Code Style
- TypeScript — strict mode enabled. No
anyunless explicitly justified. - Imports — prefer
import typefor type-only imports. Use path aliases (@/forsrc/, direct paths forserver/). - No fabricated data — every API response must be computed from real data or honestly labeled. No mocks, stubs, or hardcoded values in production code.
- Error handling — never throw from analytical equations. Return
NaNwith a clear warning. UseAppErrorsubclasses for HTTP errors. - Naming —
camelCasefor variables and functions,PascalCasefor types and components,UPPER_SNAKEfor constants.
Adding a New Analytical Model
- Add the equation function to the appropriate
server/analytical-models/equationParts/PART{n}.tsfile (or create a new part if adding a new domain). - The function receives typed inputs
Record<string, number>and must return{ result: number, unit: string, steps: string[] }. - Add the ID to the
EQUATION_ENGINEobject (it's composed from the parts automatically). - Register the model's metadata in
src/data/analyticalModels.ts(name, equation, description, reference, etc.). - Add the search keyword mapping in
server/index.ts(tryAnalyticalModelRunInner'sMODEL_KEYWORDSarray). - Wire the model's inputs in
server/analytical-models/contextEngine.ts(mapInputsswitch-case). - Add a unit test in
server/__tests__/unit/and an E2E test ine2e/.
Adding a New Data Layer
- Add the fetch function in
server/data/dataFetchers.ts. - Add the route in
server/index.tsand register it in the public/authenticated bypass list if needed. - Add the API metadata in
server/apiMetadata.ts. - Add the endpoint to the OpenAPI spec in
server/routes/openapi.ts. - Add the layer to the catalog in
src/lib/layerConfig.ts. - Verify the route returns real data:
curl http://localhost:3001/api/your-endpoint.
Documentation
Docs prose lives in Markdown (README.md, docs/site/markdown/*.md, docs/site/capabilities/*.md); the Pages site under docs/site/ is generated from scripts/docs/ page specs — edit the spec, run node scripts/docs/build.mjs, and keep node scripts/docs/quality-gate.mjs green. Every factual claim needs a file:line citation; executed evidence is labelled MEASURED, code-read evidence is labelled inspection-only. The writing rules are at docs/governance/style-guide.html.
Pull Request Process
- Run the full test suite before submitting:
npm test && npx playwright test && npm run build. - Ensure eslint is clean:
npm run lint. - No
.envfiles in commits — they are gitignored. - No third-party API keys in source code.
- Every new feature must have a corresponding E2E test.
- All analytical model outputs must be computed from real data — no fabricated results.
Architecture
See README.md for the full architecture diagram and request flow.
License & Contributions
Terranoetis is licensed under the Business Source License 1.1 (BUSL-1.1) (see LICENSE). Each version converts to the MIT License four years after publication.
By submitting a contribution (pull request, patch, or code), you agree that:
- Your contribution is licensed to the project under the same BUSL-1.1 terms.
- The maintainer may relicense and use your contribution for any purpose, including commercial licensing of the project (e.g. offering it under a paid commercial license). This is required so the project can stay sustainable.
- You confirm you have the right to grant these permissions and that your contribution is original or properly attributed.
Third-party components you reference (models, data sources, libraries) must keep their own licenses — do not relicense someone else's work as ours.