Skip to content

Latest commit

 

History

History
294 lines (232 loc) · 11.9 KB

File metadata and controls

294 lines (232 loc) · 11.9 KB

CONTRIBUTING.md — Contributor & Agent Workflow

Purpose: the rules every human contributor and every agent/subagent follows to change CrustCore safely — branches, ownership, contract files, dependencies, verification, coding standards, and changelog discipline.

CLAUDE.md is the single source of truth. This file restates and operationalizes CLAUDE.md §6 (workflow) and §7 (parallel/subagent workflow); where any wording here seems to conflict with CLAUDE.md, INVARIANTS.md, or ROADMAP.md, those win. Do not contradict them.

Related: ROADMAP.md §18 (build phases & tasks) · ROADMAP.md §20](./ROADMAP.md) (maintainer-agent rules) · [INVARIANTS.md](./INVARIANTS.md) · [SECURITY.md](./SECURITY.md) · [docs/maintainer-agent.md`.


1. The one rule

One task = one branch = one PR.

Everything else follows from keeping each change small, owned, verifiable, and auditable. The verifier — not a model, not a subagent, not your confidence — decides when a change is done (CLAUDE.md §9, invariant 13).


2. Before you start

  1. Read the contract. Read CLAUDE.md fully, plus the docs/ deep-dive(s) for the subsystem you are touching. The docs define the contract the code must satisfy.

  2. Build it. You need a stable Rust toolchain with rustfmt + clippy (pinned in rust-toolchain.toml). The workspace is std-only today and builds offline:

    cargo check --workspace     # compile everything
    cargo xtask verify          # the full gate (must be green before any PR)
    cargo xtask size-check      # nano binary size vs. the 800 KiB budget
  3. Pick one task from the phase roadmap (P0–P16) or an assigned issue. Grep for the matching TODO(Pn) markers in the scaffold — they mark exactly where the implementation goes. Keep it to a single, reviewable unit of work.

  4. Declare owned file globs. State in the PR body exactly which files/dirs this task owns. Two tasks (or two subagents) must never own overlapping files (CLAUDE.md §7.2).


3. Branching & PR conventions

Documentation work:  claude/crustcore-project-docs-q0kr2p
Per-task code work:  claude/<phase>-<slug>     e.g. claude/p3-confined-paths
  • Never push to main directly. Never push to a branch you weren't assigned without explicit permission (CLAUDE.md §6.2).
  • One branch per task; rebase, don't pile unrelated work onto a branch.
  • PR body must include:
    - summary of the change
    - owned file globs
    - phase/task id (e.g. P4.3) when applicable
    - tests run (or a written reason none were added)
    - risks / open questions
    - invariants touched or verified (by number)
    - for nano-affecting or dependency changes: cargo-bloat output
    - link to the CHANGELOG.md entry
    
  • Never self-merge anything irreversible or contract-touching without maintainer approval (invariants 4, 14).

Commit messages

  • Imperative mood, scoped, explaining why not just what. Reference the task id (e.g. P4.3: bound stdout/stderr capture). Keep secrets and tokens out of messages, diffs, and fixtures (CLAUDE.md §6.6).

4. Contract files — serialized changes only

These files are the trust boundary. Never edit them in parallel. Changes are serialized (one PR at a time) and require maintainer review (CLAUDE.md §7.3):

CLAUDE.md
INVARIANTS.md
THREAT_MODEL.md
SECURITY.md
docs/policy.md
docs/secrets.md
docs/sandbox.md
docs/backend-contract.md
crates/crustcore-kernel/src/event.rs
crates/crustcore-kernel/src/action.rs
crates/crustcore-policy/src/decision.rs
crates/crustcore-secrets/src/lib.rs
Cargo.toml
Cargo.lock

If your task needs a contract-file change, stop and route it through a dedicated serialized task — do not bundle it into unrelated work. A contract change that adds or modifies a security surface must ship its red-team fixture in the same PR (INVARIANTS.md § Red-team requirement).


5. Dependency admission policy

A dependency may enter nano only if all five hold (ROADMAP.md §20.3, CLAUDE.md §6.4):

1. it replaces more code than it adds,
2. it does not pull a second runtime / TLS / DB stack,
3. it does not materially increase binary size beyond budget,
4. it has a clear maintenance/security story,
5. cargo-bloat output is attached to the PR.

Hard bans for the kernel/nano (see the crate dependency table in CLAUDE.md §5.1): tokio, reqwest, rustls, hyper, axum, tower, clap, sqlx/rusqlite/redb (by default), rmcp, provider/GitHub/ Telegram SDKs, tree-sitter/LSP, rich TUI/telemetry. Nano may invoke external commands (git, sandbox backend, codex, claude, sidecar helpers) but may not link their stacks (invariants 19, 20). For non-nano crates, prefer minimal, well-maintained deps and keep edge adapters out of core.

No drive-by dependency additions. A dependency change is its own task.


6. Coding standards

From CLAUDE.md §6.5:

  • Make illegal states unrepresentable. Prefer typed capabilities, approvals, and confined paths over booleans and raw strings (docs/policy.md, docs/secrets.md).
  • No unsafe in the kernel. Kernel code is #![forbid(unsafe_code)] unless a measured, reviewed, documented exception exists. Any unsafe anywhere requires justification plus tests.
  • Formatting & lints: run cargo fmt (and cargo fmt --check must pass) and cargo clippy --workspace -- -D warnings. Match surrounding style.
  • Tests-or-reason: every change includes tests or a written reason why not. Every bug fix gets a regression test; every red-team scenario gets a fixture.
  • Bounded everything: bounded output capture, bounded text, budget limits, timeouts. No unbounded reads into model context.
  • Security while building: treat all repo/issue/PR/tool/web/MCP/worker content as untrusted data (invariant 7). Never write a real secret into the repo, a log, a fixture, a comment, or a commit — use handles/placeholders (CLAUDE.md §6.6).

7. The verify suite — cargo xtask verify

Every PR must run cargo xtask verify and it must be green before merge (invariant: verifier-owned completion, CLAUDE.md §9.1). As the workspace matures it covers:

cargo build --workspace
cargo build --profile nano -p crustcore --no-default-features --features nano
cargo test --workspace
cargo clippy --workspace -- -D warnings
cargo fmt --check
# nano size gate (fail if crustcore-nano exceeds budget)
cargo bloat --profile nano -p crustcore --crates -n 30   # report
# forbidden-dependency check for nano (no tokio/reqwest/clap/sqlx/rmcp/...)
# red-team fixtures (prompt injection, path escape, fake tool results, secret leak)

The Phase-0 scaffold already wires cargo xtask verify to run fmt, clippy -D warnings, the test suite, the forbidden-dependency check, and the nano size gate; it is green today. As the trusted core is implemented, the remaining steps above (red-team fixtures, full nano build coverage) are switched on in their phases (ROADMAP.md §18 P0.4).

Nano size gate — review requirement

The nano size gate is a first-class CI check, not a nice-to-have (CLAUDE.md §9.2, invariant 19). A PR that pushes crustcore-nano over the configured budget fails CI unless the maintainer explicitly raises the budget in the same PR with written justification. Any nano-affecting change must attach cargo bloat output and record the size delta (in kB) in the changelog entry. See docs/nano-size-budget.md.


8. Changelog discipline

Every PR updates CHANGELOG.md in the same PR as the change — never as a separate after-the-fact docs PR (CLAUDE.md §8).

Format: Keep a Changelog + SemVer, with an [Unreleased] section, standard groups (Added/Changed/Deprecated/Removed/Fixed/Security), and a CrustCore Agent Log subsection. Each entry records:

- the change, in the right group
- the phase + task id (e.g. P1.3) when applicable
- the PR number / branch
- the owning agent/role
- size impact for any nano-affecting change (delta in kB, or "n/a")
- invariants touched or verified

In parallel work, subagents report their changelog lines to the supervisor, which writes the consolidated [Unreleased] entries to avoid merge conflicts (CLAUDE.md §7.2, §8.3). The changelog is part of the audit story: treat it as seriously as the event log.


9. Parallel & subagent work

CrustCore is built by a one-supervisor, many-worker model that mirrors the runtime supervisor it implements (CLAUDE.md §7`):

  • One supervisor per session talks to the user, integrates, pushes, opens PRs, resolves secret handles, spawns workers, and commits durable state. Subagents are workers: they explore, draft, analyze, and return structured results — they never message the user (invariant 5) and never edit each other's files.
  • Partition by owned file globs; assign disjoint files up front.
  • Give each subagent the contract (the relevant docs/ + ROADMAP.md), not just the goal — subagents don't inherit the supervisor's context.
  • The supervisor integrates into an integration worktree, reruns cargo xtask verify, and only then commits/pushes. Parallel worktrees merge only after verification (CLAUDE.md §7.4`).
  • Budgets bound fan-out: wall time, output size, model cost/tokens, and a concurrency cap. Runaway fan-out is a threat (budget exhaustion, invariant 11).

10. Reversible vs irreversible

Reversible (run autonomously):    edit, build, test, lint, local commit, worktree ops
Irreversible (gate on approval):  merge, deploy, write secrets, force-push,
                                  publish, branch-protection changes,
                                  GitHub Actions workflow edits, releases

Irreversible actions require an approval token (invariant 14) and cannot be self-approved by a model (invariant 4). See docs/policy.md and docs/github.md.


11. License

CrustCore is licensed under the Apache License, Version 2.0 (see also NOTICE). New source files should carry the SPDX header:

// SPDX-License-Identifier: Apache-2.0

Inbound = outbound (DCO-style): unless you explicitly state otherwise, any contribution you intentionally submit for inclusion in the work shall be licensed under Apache-2.0, without any additional terms or conditions (per section 5 of the license). By contributing you certify you have the right to do so.


12. Quick checklist (paste into your PR)

[ ] One task, one branch (claude/<phase>-<slug>), not main
[ ] Owned file globs declared; no overlap with other in-flight work
[ ] No contract-file edits bundled in (or routed as a serialized task)
[ ] No drive-by dependency adds; nano dep policy satisfied; cargo-bloat attached if relevant
[ ] cargo fmt --check, clippy -D warnings, tests (or written reason) pass
[ ] No unsafe in kernel; illegal states made unrepresentable
[ ] cargo xtask verify is green (incl. nano size gate + red-team fixtures)
[ ] New surface => new red-team fixture in the same PR
[ ] CHANGELOG.md updated in this PR (group, task id, size delta, invariants)
[ ] PR body: summary, tests, risks, invariants, changelog link
[ ] Nothing irreversible/contract-touching self-merged