Most work in this repo is performed by Claude Code agents driven by an orchestrator (see AGENTS.md). Humans can contribute too — this guide tells you how.
pnpm install
pnpm dev # boots the local Murmur server (after M1 lands)
pnpm test # runs unit tests
pnpm typecheck # strict TS
pnpm lint # ESLint
pnpm grep:all # security/style grep gatesWe use lefthook:
brew install lefthook # macOS — see lefthook docs for Linux/Windows
lefthook install- Pre-commit: lint --fix on staged, prettier on staged, all grep gates (full-tree, fast).
- Pre-push: typecheck (full project), full test suite (skipped on docs-only pushes), grep gates again.
None of these are skippable; if a hook fails, the commit / push is blocked. Do not use --no-verify — fix the issue.
- Pick an open, unblocked issue from Demo readiness.
- Comment on it:
Claimed by @<your-handle> until <ISO-timestamp +2h>. If a claim's TTL elapses without a PR, anyone (including the orchestrator) can re-claim. - Add an "Implementation sketch" comment before writing code. See
AGENTS.mdfor the template. - Branch off
main:git checkout -b dev/<issue-num>-<short-slug>. - Interfaces first — types/signatures with no implementation. Commit.
- Tests next — derived from the issue's "Verification" section. Commit. Tests should fail.
- Implement until tests pass. Multiple small commits preferred.
- Run
pnpm typecheck && pnpm lint && pnpm test && pnpm grep:alllocally. Fix anything red. - Open a PR with
Closes #<issue-num>in the body. Title format:<type>(<scope>): <issue title>where<type>∈{feat, fix, refactor, docs, test, chore, build, ci, perf}from the issue'stype:*label and<scope>is the area (murmur,jobseek,auth,claim,dispatch, …). Example:feat(claim): atomic claim pickup with CAS submit. - Comment on the issue:
Implementation complete, PR #<n>, ready for review. - A reviewer (agent or human) will leave comments. Address them; reply
Fixed in <sha>and resolve threads. Push again. - When approved: orchestrator (or a human maintainer) squash-merges.
- TypeScript strict; no
any; noas <T>without a comment justifying it - ESLint clean; no
// eslint-disablewithout an inline reason - Coverage ≥85% on gated paths (
src/auth/**,src/api/**,src/dispatch/**) - Functions ≤50 lines unless an inline comment explains why
- Comments only when WHY isn't obvious from names + types
- All response envelopes use
EnvelopeResponse<T>from@murmur/contracts-types(the M0 package)
- Never log
MURMUR_TOKENor any secret. Thegrep:no-token-loggedgate will catch obvious mistakes. - Token comparisons use
crypto.timingSafeEqual(thegrep:uses-timingsafeequalgate enforces this insrc/auth/**). - URLs received from agents are SSRF-validated before any outbound fetch (publisher side; see DESIGN.md §3.6).
- Bugs → open an issue with
type:feature(ortype:infra) and the relevantarea:*label - Spec disagreements → open a PR against
DESIGN.mdseparately; do not bundle with code PRs
DESIGN.md— protocol spec, demo plan, ws coverage matrixAGENTS.md— agent process (the human-readable version of what the orchestrator enforces).claude/agents/— agent role definitions (orchestrator, developer, reviewer).claude/settings.json— Claude Code permissions.github/workflows/ci.yml— CI pipelinelefthook.yml— local hook configscripts/grep-*.sh— quality gates