Skip to main content

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

  1. Create the packagepackages/provider-<name>/ with package.json, tsconfig.json, src/adapter.ts, src/capabilities.ts
  2. Define capabilities — Create a fixture in fixtures/providers/<name>-*.json describing the provider's file locations, scopes, trust gates, and phase status
  3. Implement the adapter — The adapter implements the RendererAdapter interface from @workloom/renderer
  4. Add fixtures — Create test fixtures showing expected rendered output
  5. Write tests — Snapshot tests comparing adapter output against fixtures
  6. Update the CLI — Register the provider in apps/cli/
  7. 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, not test3.json)
  • Valid JSON that passes schema validation (unless it's a negative test)
  • A corresponding test case in the relevant test suite

Code Style

ConventionRule
LanguageTypeScript, strict mode, ESM modules
FormattingPrettier with default settings
LintingESLint 9 with TypeScript plugin
TestingVitest
Node importsnode: prefix (node:fs/promises, node:path)
NamingcamelCase (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

  1. Fork and branch — Create a feature branch from main
  2. Make your changes — Follow the code style, add tests
  3. Verify locallypnpm build && pnpm typecheck && pnpm lint && pnpm test
  4. Open a PR — Describe what you changed and why
  5. 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