Thank you for contributing to Bear — the commerce layer for AI agent payments on Stellar. This guide ensures quality, consistency, and traceability across the project.
- Commit Message Format
- Test-Driven Development (TDD)
- Running Tests
- CLAUDE.md Update Protocol
- Self-Audit Checklist
- Workflow
- Pre-Commit Hooks
- WASM Size Budgets
Bear uses Conventional Commits for clarity and automation. All commits must follow this format:
<type>(<scope>): <subject>
<body>
<footer>
Must be one of:
feat:A new feature or capabilityfix:A bug fixtest:Adding or updating tests (no production code changes)docs:Documentation only (READMEs, comments, guides)chore:Tooling, dependency updates, build scripts (no feature or fix)style:Code formatting, linting, or aesthetics (no logic changes)refactor:Code reorganization (no feature or bug fix)
Narrow scope to a specific component:
identity→agent-identitycontractcommerce→agentic-commercecontractsdk→ TypeScript SDK (marc-stellar-sdk)dashboard→ Web dashboarddemo→ Demo agents or orchestrationlanding→ Landing pageinfra→ CI/CD, deployment, scripts
- Imperative mood: "add register() entry point" not "adds" or "added"
- No period at the end
- Max 50 characters
- Lowercase (except proper nouns like "USDC", "Stellar")
Provide context and rationale:
- Wrap at 72 characters
- Explain why, not what (code explains what)
- Reference issues:
Resolves #123orFixes #456 - Call out breaking changes with a
BREAKING CHANGE:prefix
For issue tracking:
Resolves #123
Co-authored-by: Name <email>
feat(identity): add update_uri entry point
Allow agents to update their metadata URI without re-registering.
Validates owner via require_auth() and emits UriUpdated event.
Resolves #45
test(commerce): add event payload assertions for JobCompleted
Events now include payout and fee amounts. Assert exact struct
fields using to_xdr() comparison to catch payload regressions.
Resolves #362
fix(commerce): guard create_job against double-init
create_job() silently succeeded before init() was called,
bypassing fee bps and admin validation. Now panics with
"not initialized" until admin calls init().
Resolves #363
Quality over speed. Every feature and fix follows this cycle:
Before touching production code, write a test that fails:
#[test]
fn test_register_new_agent_increments_id() {
let env = Env::default();
let contract_id = env.register_contract(None, AgentIdentityContract);
let client = AgentIdentityContractClient::new(&env, &contract_id);
let alice = Address::generate(&env);
let metadata_uri = "https://ipfs.example/agent1.json";
// This test should fail until register() is implemented
let id1 = client.register(&alice, metadata_uri);
assert_eq!(id1, 1);
}cargo test test_register_new_agent_increments_idYou should see:
error[E0425]: cannot find function `register` in this scope
or similar. The test must fail before you implement the feature.
Write only what's needed to pass the test. Don't add extra features or error handling yet:
#[contractimpl]
impl AgentIdentityContract {
pub fn register(env: Env, agent: Address, metadata_uri: String) -> u64 {
let next_id: u64 = env.storage().instance().get(&Symbol::new(&env, "next_id")).unwrap_or(1);
env.storage().instance().set(&Symbol::new(&env, "next_id"), &(next_id + 1));
next_id
}
}cargo test test_register_new_agent_increments_idYou should see:
test test_register_new_agent_increments_id ... ok
Now add tests for rejection and validation:
#[test]
#[should_panic(expected = "already registered")]
fn test_register_rejects_duplicate_agent() {
// ...
}
#[test]
fn test_register_requires_auth() {
// ...
}Once all tests pass, refactor for clarity and maintainability. Re-run tests after each change:
cargo testRun all tests in the workspace:
cargo testRun tests for a specific contract:
cargo test --package agent-identity
cargo test --package agentic-commerceRun a single test:
cargo test test_register_new_agent_increments_id -- --exactRun tests with output (even on success):
cargo test -- --nocapturePer workspace:
# SDK
npm test --workspace ./sdk
# Dashboard
npm test --workspace ./dashboard
# Demo
npm test --workspace ./demoIf a package doesn't have tests defined yet, add a placeholder:
{
"scripts": {
"test": "echo 'No tests defined'"
}
}For Rust contracts, use cargo tarpaulin (requires cargo install cargo-tarpaulin):
cargo tarpaulin --workspace --out Html --output-dir coverageFor TypeScript:
npm test --workspace ./sdk -- --coverageBefore pushing, verify both Rust and TypeScript checks pass locally:
cargo test
cargo clippy -- -D warnings
cargo fmt --checkCLAUDE.md is the project memory for AI-assisted work. After every task, update it so future sessions don't re-learn the same lessons. This is mandatory.
Update it at the end of:
- Every feature/fix/refactor that touches code
- Every time you discover a gotcha or learn something about the toolchain
- After every deployment or environment change
- After every incident or blocker you resolve
Add a row to the table with:
- Date: Today's date (YYYY-MM-DD format)
- Task: Brief name of the work (e.g., "Phase 1.2: register + get_agent")
- Outcome: ✅ if complete,
⚠️ if blocked, 🔄 if ongoing - Notes: Key learnings, gotchas, decisions, plan deviations
Example:
| 2026-07-29 | docs: add CONTRIBUTING.md | ✅ | Covers TDD, commit format, CLAUDE.md protocol. All sections tested against current toolchain. |Append any new gotcha (surprise or lesson) you discovered:
- `soroban-sdk` 27.x removes `Vec` from the auto-glob — must `use soroban_sdk::Vec;` explicitly in lib.rs.If you've verified a risk is now closed, mark it CLOSED with its resolution.
If you hit a new risk, add it under "Open risks" so future work knows to investigate.
Use the self-audit checklist (below) before updating CLAUDE.md. Once you pass audit, update it immediately — do NOT defer.
Before committing ANY task, verify all of the following:
-
Does the diff only touch files listed in the current task's scope? If you touched unrelated files, either remove those changes or document why they're necessary in CLAUDE.md notes.
-
Did I write the test FIRST and see it fail? (TDD requirement.) If this is a docs/chore task, skip this, but still run tests to verify nothing broke.
-
Did I run the test after implementing and see it pass? Run the full test suite (
cargo testornpm test) to confirm no regressions. -
Are there any
panic!()messages without matching#[should_panic]tests? Every panic path must have a test that verifies the panic happens with the expected message. -
Are there any unused imports? Run
cargo clippyornpx eslintto catch them. -
Did I cross-check the API against the docs? For new Soroban SDK usage, verify against official docs or the source (
~/.cargo/registry/src/.../soroban-sdk-27.x.x/src/). -
Is the commit message conventional and accurate? Follow the format above. If you're unsure, it's probably not descriptive enough — add more detail to the body.
-
Did I update CLAUDE.md's "What's done" section? Record the outcome, date, and any gotchas. This is mandatory.
Run npm install at the repository root to install Husky hooks; rerun
npm run prepare if hook installation was skipped. The pre-commit
hook checks Rust formatting and clippy, then runs Prettier on staged supported
files through lint-staged. The commit-message hook checks Conventional Commit
format and prints examples when a message is rejected. These shell hooks run
through Git's POSIX-compatible shell on macOS/Linux and Git for Windows; Rust
must be available on PATH.
To check a message manually, run npm exec -- commitlint --from HEAD~1 --to HEAD.
CI optimizes Soroban WASM artifacts before checking their sizes. The default
budgets are 8,192 bytes for agent_identity.wasm and 16,384 bytes for
agentic_commerce.wasm. Configure repository Actions variables
IDENTITY_WASM_BUDGET_BYTES and COMMERCE_WASM_BUDGET_BYTES to change these
limits. Every CI run reports both exact sizes and configured limits.
The size check uses the workspace's wasm32v1-none target and the Stellar CLI
optimizer, matching the artifacts produced by scripts/build.sh.
- Create a branch:
git checkout -b feat/my-feature - Write a test that fails
- Implement the feature to make it pass
- Add edge case / error tests
- Run full test suite:
cargo test - Update CLAUDE.md: add a row to "What's done" with outcome ✅
- Commit:
git commit -m "feat(scope): description"(conventional format) - Create a pull request (do NOT push directly to main)
- Create a branch:
git checkout -b fix/my-bug - Write a test that reproduces the bug (and fails)
- Fix the bug to make the test pass
- Run full test suite:
cargo test - Update CLAUDE.md: add a row with outcome ✅, link the issue
- Commit:
git commit -m "fix(scope): description\n\nResolves #123" - Create a pull request
- Create a branch:
git checkout -b docs/my-docorgit checkout -b chore/my-task - Make the changes
- Run
cargo fmtandcargo clippyto catch style issues - Update CLAUDE.md (if applicable)
- Commit:
git commit -m "docs(scope): description"orgit commit -m "chore(scope): description" - Create a pull request
- Title: Keep under 70 characters, use conventional format. Example:
feat(identity): add update_uri entry point - Description: Include a summary of changes, what was tested, and any blocked features or follow-ups.
- Do NOT push to main directly. All work goes through pull requests.
- Avoid force pushes (
git push --force). Prefer normal commits to preserve history. - Do NOT amend or rebase published commits. If you need to fix a commit, make a new commit instead.
Before pushing any branch, run:
# Rust
cargo test
cargo clippy -- -D warnings
cargo fmt --check
# TypeScript (if modified)
npm test --workspace ./sdk
npm run lint --workspace ./sdk
npm run format --workspace ./sdk- Toolchain issues? Check
CLAUDE.md"Gotchas learned" section — your issue is probably documented there. - Stellar/Soroban questions? See the Emergency Contacts in
CLAUDE.mdor visit https://developers.stellar.org/docs/build - Design questions? Read
ROADMAP.mdanddocs/superpowers/specs/for architecture context. - Stuck on a test? Check the test examples in
contracts/*/src/test.rs— they follow the pattern this guide describes.
- Be respectful and collaborative
- Assume good intent
- Ask for help early and often
- Share what you learn with the team
- Update CLAUDE.md for future contributors
Thank you for making Bear better! 🐻