Contributing to Workloom
We welcome contributions! Whether you're fixing a bug, adding a feature, improving documentation, or building a new provider renderer, this guide will help you get set up.
Development Setup
Prerequisites
- Node.js 20 or later
- pnpm 9.15 or later
- Git
Clone and Install
git clone https://github.com/workloom/workloom.git
cd workloom
pnpm install
Build and Verify
pnpm build # Build all packages (Turborepo cached)
pnpm typecheck # Type-check all packages
pnpm lint # Lint all packages
pnpm test # Run all tests
All four commands should exit 0 before you start making changes.
Project Structure
workloom/
├── apps/
│ ├── cli/ # `wl` CLI entry point
│ └── web/ # Web dashboard (Phase 2+)
├── packages/
│ ├── core/ # Domain types, hashing, error model
│ ├── manifest/ # Zod schemas for all manifest types
│ ├── renderer/ # Abstract render engine
│ ├── config/ # TOML parsing, config discovery
│ ├── drift/ # Drift detection engine
│ ├── telemetry/ # Privacy-safe event emission
│ ├── provider-claude/ # Claude renderer
│ ├── provider-codex/ # Codex renderer
│ ├── provider-gemini/ # Gemini (Phase 5)
│ ├── provider-copilot/ # Copilot (Phase 5)
│ └── provider-cursor/ # Cursor (Phase 5)
├── fixtures/ # Test fixtures for all schema types
├── website/ # Docusaurus documentation site
└── docs/ # Architecture decision records
Package Dependency Direction
Dependencies flow one way — no cycles:
core → manifest → renderer → provider-*
→ drift
→ telemetry
→ cli (imports all)
When adding new code, respect this direction. If you find yourself needing a dependency that goes "backwards," it's a design smell — talk to the team.
How to Add a New Provider Renderer
- Create the package —
packages/provider-<name>/withpackage.json,tsconfig.json,src/adapter.ts,src/capabilities.ts - Define capabilities — Create a fixture in
fixtures/providers/<name>-*.jsondescribing the provider's file locations, scopes, trust gates, and phase status - Implement the adapter — The adapter implements the
RendererAdapterinterface from@workloom/renderer - Add fixtures — Create test fixtures showing expected rendered output
- Write tests — Snapshot tests comparing adapter output against fixtures
- Update the CLI — Register the provider in
apps/cli/ - Update docs — Add a guide in
website/docs/guides/<name>-setup.md
Key Principle: Renderer Determinism
Given the same inputs, a renderer must produce byte-identical outputs. This is contract-tested against fixtures. If your renderer uses timestamps, random values, or system-dependent paths, the tests will fail.
How to Add Fixtures
Fixtures live in fixtures/ and are organized by type:
fixtures/
├── packages/ # Package manifest fixtures
├── workspaces/ # Workspace manifest fixtures
├── drift/ # Drift detection scenario fixtures
├── providers/ # Provider capability fixtures
└── telemetry/ # Telemetry event fixtures (valid and invalid)
Every fixture should have:
- A descriptive filename (
policy-denied-hooks.json, nottest3.json) - Valid JSON that passes schema validation (unless it's a negative test)
- A corresponding test case in the relevant test suite
Code Style
| Convention | Rule |
|---|---|
| Language | TypeScript, strict mode, ESM modules |
| Formatting | Prettier with default settings |
| Linting | ESLint 9 with TypeScript plugin |
| Testing | Vitest |
| Node imports | node: prefix (node:fs/promises, node:path) |
| Naming | camelCase (vars/functions), PascalCase (types), UPPER_SNAKE (constants) |
Testing
Run the full test suite:
pnpm test
Run tests for a specific package:
cd packages/manifest
pnpm test
Writing Tests
- Use Vitest (
describe,it,expect) - Schema validation tests should cover both valid and invalid inputs
- Renderer tests should use snapshot testing against fixtures
- Negative tests are important — verify that invalid inputs are correctly rejected
Pull Request Process
- Fork and branch — Create a feature branch from
main - Make your changes — Follow the code style, add tests
- Verify locally —
pnpm build && pnpm typecheck && pnpm lint && pnpm test - Open a PR — Describe what you changed and why
- CI must pass — All checks must be green before merge
Commit Messages
Use conventional commit format:
feat: add Gemini extension manifest renderer
fix: handle nested AGENTS.md merge ordering
docs: add monorepo configuration guide
test: add drift detection fixtures for policy changes
chore: update Zod to 3.25.1
Architecture Decisions
Significant decisions are documented as ADRs in docs/adr/. If your change involves a significant architectural choice, consider adding an ADR.
Getting Help
- Open an issue on GitHub for bugs or feature requests
- Check existing issues before opening a new one
- Read the Architecture Overview for design context