First off, thank you for considering contributing to Corbat-Coco! It's people like you that make Corbat-Coco such a great tool.
- Code of Conduct
- Getting Started
- Development Setup
- Project Structure
- Making Changes
- Testing
- Code Style
- Commit Messages
- Pull Request Process
- Architecture Guidelines
This project and everyone participating in it is governed by our commitment to creating a welcoming and inclusive environment. Please be respectful and constructive in all interactions.
- Node.js: Version 22.0.0 or higher
- pnpm: Version 10.0.0 (enforced via
packageManagerfield) - Git: For version control
- Anthropic API Key: For running integration tests (optional)
# Clone the repository
git clone https://github.com/corbat-tech/coco.git
cd corbat-coco
# Install dependencies
pnpm install
# Run the CLI in development mode
pnpm dev --help
# Run tests
pnpm test
# Run all checks (typecheck + lint + test)
pnpm checkCreate a .env file for local development (never commit this):
# Required for integration tests with real LLM
ANTHROPIC_API_KEY=sk-ant-...
# Optional: Custom config path
COCO_CONFIG_PATH=/path/to/config.json| Script | Description |
|---|---|
pnpm dev |
Run CLI with tsx (development mode) |
pnpm build |
Build with tsup |
pnpm build:watch |
Build in watch mode |
pnpm typecheck |
TypeScript type checking |
pnpm lint |
Run oxlint |
pnpm lint:fix |
Run oxlint with auto-fix |
pnpm format |
Check formatting with oxfmt |
pnpm format:fix |
Fix formatting |
pnpm test |
Run tests with Vitest |
pnpm test:watch |
Run tests in watch mode |
pnpm test:coverage |
Run tests with coverage report |
pnpm check |
Run all checks (typecheck + lint + test) |
corbat-coco/
├── src/
│ ├── cli/ # CLI commands (Commander.js)
│ │ ├── commands/ # Individual command implementations
│ │ └── index.ts # CLI entry point
│ │
│ ├── config/ # Configuration system (Zod schemas)
│ │ ├── schema.ts # Configuration schema definitions
│ │ └── loader.ts # Config loading and validation
│ │
│ ├── orchestrator/ # Central coordinator
│ │ └── index.ts # State machine and session management
│ │
│ ├── phases/ # COCO methodology phases
│ │ ├── converge/ # Requirements discovery
│ │ ├── orchestrate/ # Architecture planning
│ │ ├── complete/ # Code generation & iteration
│ │ └── output/ # Deployment preparation
│ │
│ ├── providers/ # LLM provider integrations
│ │ ├── anthropic.ts # Anthropic Claude implementation
│ │ └── types.ts # Provider interfaces
│ │
│ ├── quality/ # Quality scoring system
│ │ └── types.ts # Quality dimensions & thresholds
│ │
│ ├── tools/ # Tool implementations
│ │ ├── file.ts # File operations
│ │ ├── bash.ts # Command execution
│ │ ├── git.ts # Git operations
│ │ ├── test.ts # Test running
│ │ ├── quality.ts # Quality analysis
│ │ └── registry.ts # Tool registry
│ │
│ ├── types/ # Shared type definitions
│ │ └── task.ts # Task, Story, Epic, Sprint types
│ │
│ └── utils/ # Utility functions
│ ├── errors.ts # Custom error classes
│ ├── logger.ts # Logging (tslog)
│ └── validation.ts # Input validation helpers
│
├── test/
│ ├── e2e/ # End-to-end tests
│ ├── mocks/ # Mock implementations
│ └── fixtures/ # Test fixtures
│
├── docs/
│ ├── architecture/ # Architecture documentation
│ │ ├── ARCHITECTURE.md # C4 diagrams
│ │ └── adrs/ # Architecture Decision Records
│ └── guides/ # User guides
│
└── examples/ # Example projects
Use descriptive branch names:
feat/add-openai-provider
fix/checkpoint-recovery-issue
docs/improve-readme
refactor/simplify-quality-scorer
test/add-converge-phase-tests
-
Create a branch from
main:git checkout -b feat/your-feature
-
Make your changes following the code style guidelines
-
Write tests for your changes (minimum 80% coverage)
-
Run checks:
pnpm check
-
Commit with a conventional commit message
-
Push and open a Pull Request
Tests should be colocated with source files:
src/
├── utils/
│ ├── errors.ts
│ └── errors.test.ts # ← Test file next to source
├── phases/
│ └── converge/
│ ├── discovery.ts
│ └── discovery.test.ts
import { describe, it, expect, vi, beforeEach } from "vitest";
import { YourModule } from "./your-module.js";
describe("YourModule", () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe("methodName", () => {
it("should do something specific", () => {
// Arrange
const input = "test";
// Act
const result = YourModule.methodName(input);
// Assert
expect(result).toBe("expected");
});
it("should handle edge cases", () => {
expect(() => YourModule.methodName(null)).toThrow();
});
});
});import { vi } from "vitest";
vi.mock("@anthropic-ai/sdk", () => ({
default: class MockAnthropic {
messages = {
create: vi.fn().mockResolvedValue({
id: "msg_123",
type: "message",
role: "assistant",
content: [{ type: "text", text: "Mocked response" }],
stop_reason: "end_turn",
usage: { input_tokens: 10, output_tokens: 20 },
}),
};
},
}));- Lines: 80% minimum
- Functions: 80% minimum
- Branches: 80% minimum
- Statements: 80% minimum
Run coverage report:
pnpm test:coverage- Strict mode: Always enabled
- ESM only: No CommonJS (
require,module.exports) - Imports: Use
.jsextension in imports - Types: Prefer explicit types, avoid
any - Async: Always use
async/await(no raw Promises)
// ✅ Good
import { something } from "./module.js";
export async function doSomething(input: string): Promise<Result> {
const data = await fetchData(input);
return processData(data);
}
// ❌ Bad
const { something } = require("./module");
export function doSomething(input) {
return fetchData(input).then((data) => processData(data));
}- Keep files under 500 lines when possible
- One export per file for main modules
- Group related utilities together
- Document public APIs with JSDoc
/**
* Calculates the quality score for a set of files.
*
* @param files - Array of file paths to analyze
* @param options - Scoring options
* @returns Quality scores with individual dimensions
*
* @example
* ```typescript
* const scores = await calculateQuality(["src/index.ts"], {
* includeTests: true,
* });
* console.log(scores.overall); // 85
* ```
*/
export async function calculateQuality(
files: string[],
options?: QualityOptions
): Promise<QualityScores> {
// Implementation
}We use oxlint for linting and oxfmt for formatting:
# Check
pnpm lint
pnpm format
# Fix
pnpm lint:fix
pnpm format:fixWe follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
| Type | Description |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation only |
style |
Formatting, no code change |
refactor |
Code change that neither fixes a bug nor adds a feature |
perf |
Performance improvement |
test |
Adding or updating tests |
chore |
Build process or auxiliary tool changes |
| Scope | Description |
|---|---|
cli |
CLI commands |
converge |
CONVERGE phase |
orchestrate |
ORCHESTRATE phase |
complete |
COMPLETE phase |
output |
OUTPUT phase |
quality |
Quality system |
tools |
Tool implementations |
provider |
LLM providers |
config |
Configuration |
feat(cli): add --verbose flag to build command
fix(complete): handle empty test results gracefully
docs(readme): add troubleshooting section
test(converge): add discovery engine tests
refactor(quality): simplify score calculation-
Ensure all checks pass:
pnpm check
-
Update documentation if needed
-
Add tests for new functionality
-
Fill out the PR template completely
-
Request review from maintainers
-
Address feedback promptly
- Code follows the style guidelines
- Self-reviewed the code
- Added tests (80%+ coverage)
- Updated documentation
- All checks pass (
pnpm check) - No new warnings
When contributing to a specific phase, understand its responsibilities:
| Phase | Responsibility | Key Files |
|---|---|---|
| CONVERGE | Requirements discovery | src/phases/converge/ |
| ORCHESTRATE | Architecture planning | src/phases/orchestrate/ |
| COMPLETE | Code generation & iteration | src/phases/complete/ |
| OUTPUT | Deployment preparation | src/phases/output/ |
-
Create tool in
src/tools/:export const myNewTool: ToolDefinition<MyInput, MyOutput> = { name: "myNewTool", description: "Does something useful", category: "utility", parameters: MyInputSchema, execute: async (params) => { // Implementation }, };
-
Register in
src/tools/registry.ts -
Add tests in
src/tools/my-new-tool.test.ts
- Implement the
LLMProviderinterface insrc/providers/ - Add configuration schema in
src/config/schema.ts - Register in provider factory
- Add tests with mocked API calls
If you have questions, feel free to:
- Open a Discussion
- Check existing Issues
Thank you for contributing! 🎉