Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .c8rc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"all": true,
"include": ["src/**"],
"exclude": ["tests/**"],
"reporter": ["text", "json-summary"],
"report-dir": "coverage",
"temp-directory": "coverage/tmp",
"check-coverage": true,
"lines": 100,
"branches": 100,
"functions": 100,
"statements": 100,
"clean": true
}
23 changes: 23 additions & 0 deletions .claude/rules/code-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Coding Standards

- Keep at most a single public struct per module.
- Keep at most a single public function per module (multiple public struct methods are OK).
- Keep module names elegant and clearly readable. The name of the module, or any file, should be enough to determine its contents unambiguously.
- Keep modules structure as flat as possible, avoid logical grouping of modules, instead keep the naming consistent.
- Keep standalone, private functions and structs above the public struct or function that is exported.
- Group the modules by name prefix. For example, `client_foo`, `client_bar`, etc., wherever it makes sense to do so.
- Decide to group the modules based on software architecture, messaging hierarchy, or inheritance. Do not group modules just for the sake of it.
- Maintain a tree-like structure of modules, avoid circular dependencies at all costs. Extract common functions or structs into separate modules, or separate subprojects in the workspace.
- Name files the same way as the struct or function they contain.
- Be explicit, do not use general import statements that involve "*", prefer to import everything explicitly.
- Do not use copy-pasted or copied code in any capacity. If you have issues extracting something into a module, discuss the steps first.
- Keeping slightly different message types, or other kinds of structs that are only slightly different, because of the context they are used in, is fine.
- Each function or method should do just a single thing. The single responsibility principle is really important.
- Always use descriptive and explicit variable names, even in anonymous functions. Never use single-letter variable names.
- Instead of writing comments that explain what the code does, make the code self-documenting.
- Handle all the errors; never ignore them. Make sure the application does not panic.
- Use object-oriented style and composition. Avoid functions that take a struct as a parameter; move it to the struct implementation instead.
- Avoid unnecessary abstractions.
- Before using vendor crates or modules, make sure they are well-maintained, secure, and documented.
- Always make sure there is only one valid way to do a specific task in the codebase. Make sure everything has a single source of truth.
- Prefer using data/value objects instead of inline types
5 changes: 5 additions & 0 deletions .claude/rules/commits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Committing Changes

- Always keep the commit messages short, human-readable, and descriptive. Keep commit messages as one-liners.
- Do not add any metadata to commits.
- Describe what the changes actually do instead of listing the changed files.
9 changes: 9 additions & 0 deletions .claude/rules/github-actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
paths:
- ".github/actions/**/*"
---

# GitHub Actions Standards

- Actions must represent a single purpose and a single concern.
- Compose actions if they need to provide a more complex functionality.
14 changes: 14 additions & 0 deletions .claude/rules/github-workflows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
paths:
- ".github/workflows/**/*"
---

# GitHub Workflows Standards

- Always use Makefile targets in the workflow to avoid code duplication (if they need to run something that is already present in a Makefile).
- Never add the tests that use LLMs to GitHub workflows, because the default GitHub worker does not have the capacity to run them.
- Only add unit tests or linters to GitHub workflows.
- Keep GitHub workflows responsible for only a single concern. For example, run linter, and tests in parallel.
- Treat GitHub workflows as a coding project. Use composable actions, factor similar concerns into actions.
- Encapsulate functionalities in composable actions.
- Keep the workflows clean and purposeful.
13 changes: 13 additions & 0 deletions .claude/rules/makefile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
paths:
- "**/Makefile"
---

# Makefile Standards

- Keep variables at the top of the file. Always.
- Prefer real targets over phony targets. If something can be express as a real target, do that.
- If you see that a phony target can be expressed as a real target, you can suggest a fix.
- Keep real targets, phony targets grouped together. Keep targets alphabetically sorted within each group.
- Keep all the real targets above phony targets.
- Make sure each Makefile target has enough dependencies to be able to run from a clean state.
12 changes: 12 additions & 0 deletions .claude/rules/nix-shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
paths:
- "**/shell.nix"
---

# Nix Shell Standards

- shell.nix must follow idiomatic NixOS ways of providing packages
- shell.nix must be minimal, and only providing project dependencies that would not be able to run natively otherwise
- shell.nix must not contain any workarounds
- shell.nix must not contain any kind of ELF patching
- shell.nix must not contain any kind of monkey patching
7 changes: 7 additions & 0 deletions .claude/rules/teamwork.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Teamwork and Project Organization

Team members own one module each. The project needs to be organized around small self-contained modules.

Each class, struct, function, interface, trait, and alike needs to be named after its functionality in self-descriptive English. The goal is to name things in a way that will allow anyone to understand the project organization, and goals by just listing the directory of files.

Developers need to be able to own their own modules without stepping on another's work.
14 changes: 14 additions & 0 deletions .claude/rules/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Unit Tests and Quality Control

- Always check that the unit tests pass.
- Always test the code, make sure tests work after the changes.
- Always write tests that check the algorithms, or meaningful edge cases. Never write tests that check things that can be handled by types instead.
- If some piece of code can be handled by proper types, use types instead. Write tests as a last resort.
- In unit tests, make sure there is always just a single correct way to do a specific thing. Never accept fuzzy inputs from end users.
- When working on tests, if you notice that the tested code can be better, you can suggest changes.
- Maintain 100% test coverage across the codebase. No file, branch, or line may be excluded from coverage reports.
- Reach 100% coverage with the minimum number of tests. Each test must cover a unique code path, behavior, or edge case that no other test already covers.
- If two tests cover overlapping paths, remove the weaker one. Redundant tests waste maintenance effort without improving correctness signal.
- Tests must exercise actual functionality and observable behavior. Never write a test purely to hit lines for the sake of coverage.
- Design tests deliberately before writing them. Identify the feature or branch under test, then write the smallest test that verifies it.
- Coverage gaps signal missing tests, never permission to exclude files. Write the test instead of suppressing the gap.
20 changes: 20 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: test

on:
push:
branches:
- main
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Run tests
run: make test
20 changes: 20 additions & 0 deletions .github/workflows/typecheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: typecheck

on:
push:
branches:
- main
pull_request:

jobs:
typecheck:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Run typecheck
run: make typecheck
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/coverage
/node_modules
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/coverage
/node_modules
/package-lock.json
.claude/
CLAUDE.md
11 changes: 11 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Project Context

When working with this codebase, prioritize readability over cleverness. Ask clarifying questions before making architectural changes.

Keep it simple, be opinionated, follow best practices. Avoid using configurable parameters.

Keep the code beautiful. Always optimize the code for a great developer experience.

Codebase needs to be architected in a way to make it easy for multiple team members to work in parallel on multiple modules, so the concerns always need clear separation.

Be proactive and fix any preexisting issues you encounter.
31 changes: 31 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
COVERAGE_DIR := coverage
NODE_MODULES := node_modules
TEST_GLOB := tests/**/*.test.mjs

$(NODE_MODULES): package.json package-lock.json
npm install
touch $(NODE_MODULES)

.PHONY: clean
clean:
rm -rf $(COVERAGE_DIR)

.PHONY: coverage
coverage: $(NODE_MODULES)
node scripts/check-coverage.mjs '$(TEST_GLOB)'

.PHONY: format
format: $(NODE_MODULES)
npx prettier --write .

.PHONY: test
test: $(NODE_MODULES)
node --test '$(TEST_GLOB)'

.PHONY: type-coverage
type-coverage: $(NODE_MODULES)
npx type-coverage --at-least 100 --strict --detail

.PHONY: typecheck
typecheck: $(NODE_MODULES)
npx tsc
Loading