Capxul Docs
Contributing

Conventions

The load-bearing repo conventions a contributor must know, each with a pointer to its canon file.

These are the conventions that PR review actually enforces. Each section is a summary; the linked canon file is the authority.

Vocabulary discipline

Two distinct rules share this name:

The leak rule. The consumer surface is Stripe-shaped: money is just money, and crypto is the substrate, never the vocabulary. A custody term ("Safe", "address", "Zodiac", "UserOp", "wei", "chain") appearing in the consumer-facing surface is a leak, and leaks are defects. CONTEXT.md at the repo root is the vocabulary authority — check it before naming anything a consumer will see.

Identifier discipline. Build-cycle metadata never appears in production identifiers or test helper type aliases: Stage1, Phase2, M1_1-style names fail review. Stage and phase words are fine in markdown narrative; code identifiers must name durable architecture concepts. Canon: canon/conventions/vocabulary-discipline.md and canon/rules/vocabulary-discipline.md.

Branded types

Every domain primitive at a port surface is branded in @capxul/types (AccountId, Email, PublishableKey, EpochMs, …). Constructors like toAccountId are the only way to create branded values — manual casts (raw as Address) are banned outside the constructor implementations. Non-wire seams (DB hydration, env reads, fixtures) use the to* constructors; wire seams (HTTP/JSON crossing into the SDK) use schemas from @capxul/wire, which must validate exactly as strictly as their to* counterparts — shape-only brand schemas are not permitted. Canon: canon/conventions/branded-types.md and canon/rules/branded-types.md.

Error handling and the error catalog

CapxulError is the public error type. Internal code may model errors as Effect channel variants, but every public SDK method maps them to CapxulError and returns CapxulResult<T> — internal variants never cross the boundary, and adapters translate external failures at the edge. The canonical public catalog contains 21 codes (NOT_AUTHENTICATED, INVALID_INPUT, INSUFFICIENT_BALANCE, WRONG_STATE, …); every Errors.* factory must return one of them. Raw provider cause payloads may live on the native Error.cause chain but do not belong in public message or details fields. Canon: canon/conventions/error-handling.md and canon/conventions/error-catalog.md.

Test contract & RED test contract

Every slice owns tests at the layer it changes: L1 (pure functions, types, schemas), L2 (port and adapter behavior — exactly one <port>.conformance.test.ts matrix file per port), L3 (package integration without external services), L4 (the real reachable runtime/service subset for the slice).

Work starts RED: a test that fails because required production behavior is absent or wrong — not because a file doesn't exist. GREEN means that same test passes without being skipped, stubbed, weakened, or rewritten. .skip and .todo after the RED phase, existence checks, and mocking the unit under test are all rejected; mock only at system boundaries. Every child issue declares its RED test up front (path, what it proves, mock boundary, why it fails). Canon: canon/conventions/test-contract.md, canon/conventions/red-test-contract.md, and canon/conventions/red-green-classifier.md.

Public-surface rule

Public SDK methods return Promise<CapxulResult<T>> — never raw values, thrown exceptions, actors, state machines, or Effect programs. Consumers import @capxul/sdk and @capxul/sdk-react only; the backend, @capxul/wire, and Convex APIs are private. See Architecture for the layer picture. Canon: canon/rules/public-surface.md.

Commit convention

Commit messages follow type(scope): summary — e.g. feat(sandbox): add canonical operator CLI, fix(sdk): keep private packages out of runtime manifests, chore(release): version packages. This is repo practice throughout the history and the release tooling (the automated version PR commits as chore(release): version packages); there is no separate canon file for it. PRs that change a publishable package's consumer-facing behavior must also include a changeset — see Release flow.

On this page