Skip to content

12.1 Contributing

Nikolay Vyahhi edited this page Feb 19, 2026 · 2 revisions

Contributing

Relevant source files

The following files were used as context for generating this wiki page:

This document explains how to contribute code to ZeroClaw through pull requests (PRs). It covers the PR lifecycle, readiness requirements, review process, and merge criteria. ZeroClaw uses a high-volume, risk-based PR workflow that balances fast throughput with security and stability.

For CI workflow details and troubleshooting, see CI/CD Workflows. For testing requirements, see Testing. For subsystem ownership, see Code Ownership.


Overview

ZeroClaw's contribution workflow is designed for high PR volume while maintaining:

  • Deterministic validation: Merge gates depend on reproducible checks, not subjective review comments
  • Risk-based routing: High-risk paths (security, runtime, gateway, workflows) receive deep review; low-risk paths stay fast
  • Automated triage: Labels route PRs to appropriate review depth automatically
  • Rollback-first contracts: Every merge includes concrete recovery steps

The workflow uses automation to assist with intake classification and queue management, but final merge decisions remain with human maintainers and PR authors.

Sources: docs/pr-workflow.md:1-91


PR Lifecycle

Lifecycle Overview

stateDiagram-v2
    [*] --> Intake: "PR opened"
    Intake --> Validation: "Template complete"
    Validation --> Failed: "CI Required Gate fails"
    Failed --> Validation: "Fix committed"
    Validation --> Review: "CI Required Gate passes"
    Review --> NeedsWork: "Review feedback"
    NeedsWork --> Validation: "Changes committed"
    Review --> MergeReady: "All approvals received"
    MergeReady --> Merged: "Squash merge"
    Merged --> [*]
    
    note right of Intake
        - PR Labeler applies labels
        - PR Auto Responder posts guidance
        - Template completeness checked
    end note
    
    note right of Validation
        - CI Required Gate is merge gate
        - Lint, test, build checks
        - Docs quality for doc changes
    end note
    
    note right of Review
        - Fast lane: template + CI + risk check
        - Deep lane: security + failure modes
        - CODEOWNERS approval required
    end note
    
    note right of MergeReady
        - DoD checklist complete
        - Rollback plan documented
        - Conventional Commit title
    end note
Loading

Sources: docs/pr-workflow.md:109-138

Step-by-Step Process

Step System Component Actions Automation
Intake .github/pull_request_template.md Contributor completes template PR Labeler applies scope, size, risk, module labels
PR Auto Responder posts first-time guidance
Validation .github/workflows/ci-run.yml CI runs lint, test, build CI Required Gate status check blocks merge until green
Review CODEOWNERS + maintainers Reviewers prioritize by risk/size labels PR Hygiene nudges stale PRs every 12 hours
Merge Maintainer Squash merge with Conventional Commit title Stale approvals dismissed on new commits

Sources: docs/pr-workflow.md:110-138, docs/ci-map.md:11-23


Definition of Ready (DoR)

Before requesting review, PRs must satisfy these requirements:

Required Template Sections

Section Requirement Enforcement
Summary Explicit scope boundary (what changed, what didn't) Manual review
Validation Evidence Attached proof (logs, screenshots, test output) Manual review
Security Impact Completed for risky paths (src/security, src/runtime, src/gateway, src/tools) Manual review
Rollback Plan Concrete, fast recovery steps Manual review
Privacy/Data Hygiene Neutral/project-scoped test language, no personal data PR Intake Checks blocks PII patterns

Common DoR Failures

flowchart TD
    PR["PR Opened"] --> CheckTemplate{"Template<br/>complete?"}
    CheckTemplate -->|No| IntakeBlock["BLOCKED: Request completion"]
    CheckTemplate -->|Yes| CheckEvidence{"Validation<br/>evidence<br/>attached?"}
    CheckEvidence -->|No| IntakeBlock
    CheckEvidence -->|Yes| CheckSecurity{"High-risk<br/>paths touched?"}
    CheckSecurity -->|Yes| CheckSecFields{"Security/rollback<br/>sections complete?"}
    CheckSecFields -->|No| IntakeBlock
    CheckSecFields -->|Yes| ReadyForReview["Ready for Review"]
    CheckSecurity -->|No| ReadyForReview
    
    IntakeBlock -.-> StopReview["Stop deep review<br/>until blockers resolved"]
Loading

Sources: docs/pr-workflow.md:143-159, docs/ci-map.md:21-22

Template Location and Structure

The PR template is defined in .github/pull_request_template.md. Contributors must complete all sections relevant to their change. The PR Intake Checks workflow (.github/workflows/pr-intake-checks.yml) validates template completeness and safe content patterns before CI runs.

Sources: docs/pr-workflow.md:143-151, docs/ci-map.md:21-22


Definition of Done (DoD)

PRs are merge-ready when all these criteria are satisfied:

Merge Gate Checklist

Criterion Validation Method Blocker
CI Required Gate green CI Required Gate status check Yes
Required reviews approved CODEOWNERS + maintainer approval Yes
Risk labels match touched paths PR Labeler automation + manual verification No (automation corrects)
Migration/compatibility impact documented Template section review Yes for breaking changes
Rollback path is concrete and fast Template section review Yes for risky paths
Conventional Commit title Squash merge commit message Yes (enforced at merge)

DoD Validation Flow

flowchart LR
    Review["Review Approved"] --> CheckCI{"CI Required<br/>Gate green?"}
    CheckCI -->|No| WaitCI["Wait for CI fix"]
    CheckCI -->|Yes| CheckCodeowners{"CODEOWNERS<br/>approved?"}
    CheckCodeowners -->|No| WaitApproval["Request owner review"]
    CheckCodeowners -->|Yes| CheckRisk{"Risk labels<br/>correct?"}
    CheckRisk -->|No| CorrectLabels["Automation auto-corrects<br/>or apply 'risk: manual'"]
    CheckRisk -->|Yes| CheckRollback{"Rollback plan<br/>documented?"}
    CheckRollback -->|No| BlockMerge["BLOCKED: Document rollback"]
    CheckRollback -->|Yes| ReadyToMerge["Ready to Merge"]
    
    CorrectLabels --> CheckRollback
Loading

Sources: docs/pr-workflow.md:152-159, docs/ci-map.md:13-17

CI Required Gate Components

The CI Required Gate check (.github/workflows/ci-run.yml) aggregates these validation steps:

  1. Rust quality gates (blocks merge):

    • cargo fmt --all -- --check
    • cargo clippy --locked --all-targets -- -D clippy::correctness
    • Strict delta lint on changed Rust lines (./scripts/ci/rust_strict_delta_gate.sh)
    • cargo test
    • Release build smoke check
  2. Docs quality gates (blocks merge when docs changed):

  3. Workflow approval gate (blocks merge when workflows changed):

    • Requires approving review from WORKFLOW_OWNER_LOGINS for .github/workflows/** changes

Sources: docs/ci-map.md:13-17, docs/pr-workflow.md:122-126


PR Size Policy

Size Tiers

Label Changed Lines Policy
size: XS ≤ 80 Fast track, minimal review depth
size: S ≤ 250 Standard review
size: M ≤ 500 Standard review, justify scope
size: L ≤ 1000 Requires explicit justification + tighter test evidence
size: XL > 1000 Split into stacked PRs unless justified

Size-Based Routing

flowchart TD
    PR["PR Opened"] --> CalcSize["PR Labeler calculates<br/>effective changed lines"]
    CalcSize --> NormSize["Normalize for docs-only<br/>and lockfile changes"]
    NormSize --> ApplyLabel{"Effective<br/>size?"}
    
    ApplyLabel -->|"≤ 80"| XS["size: XS<br/>Fast track"]
    ApplyLabel -->|"≤ 250"| S["size: S<br/>Standard"]
    ApplyLabel -->|"≤ 500"| M["size: M<br/>Standard + justification"]
    ApplyLabel -->|"≤ 1000"| L["size: L<br/>Requires tighter evidence"]
    ApplyLabel -->|"> 1000"| XL["size: XL<br/>Request split or justify"]
    
    XS --> FastReview["Prioritize in review queue"]
    S --> StandardReview["Standard review depth"]
    M --> StandardReview
    L --> DeepReview["Deep review + split discussion"]
    XL --> DeepReview
Loading

Sources: docs/pr-workflow.md:163-183

Batching Best Practices

  • Target: XS/S/M by default for faster review cycles
  • Large features: Split into stacked PRs with explicit Depends on #... links
  • Unavoidable large PRs: Must include comprehensive test evidence and failure-mode analysis

Sources: docs/pr-workflow.md:163-183


Risk Classification

Risk Tiers

PRs are automatically classified by touched paths and can be manually overridden:

Label Paths Review Depth Required Evidence
risk: high src/security/**, src/runtime/**, src/gateway/**, src/tools/**, .github/workflows/** Deep review + security check Threat model, mitigation notes, rollback steps, failure-mode scenario
risk: medium Core subsystems, provider implementations, channel implementations Standard review Rollback steps, compatibility notes
risk: low Docs, tests, examples, minor refactors Fast triage Template completeness

Risk-Based Review Routing

flowchart TD
    PR["PR Ready"] --> CheckPaths{"Touched<br/>paths?"}
    
    CheckPaths -->|"Security/Runtime/<br/>Gateway/Tools/Workflows"| HighRisk["risk: high"]
    CheckPaths -->|"Core subsystems/<br/>Providers/Channels"| MedRisk["risk: medium"]
    CheckPaths -->|"Docs/Tests/<br/>Examples"| LowRisk["risk: low"]
    
    HighRisk --> ManualOverride{"Maintainer<br/>applies<br/>'risk: manual'?"}
    ManualOverride -->|Yes| FreezeRisk["Risk label frozen"]
    ManualOverride -->|No| DeepReview["Deep Review Lane"]
    
    MedRisk --> StandardReview["Standard Review Lane"]
    LowRisk --> FastTriage["Fast Triage Lane"]
    
    DeepReview --> RequireEvidence["Require:<br/>- Threat model<br/>- Mitigation notes<br/>- Rollback steps<br/>- Failure scenario"]
    StandardReview --> RequireBasic["Require:<br/>- Rollback steps<br/>- Compatibility notes"]
    FastTriage --> RequireTemplate["Require:<br/>- Template complete"]
Loading

Sources: docs/pr-workflow.md:243-266, docs/ci-map.md:52

Manual Risk Override

Maintainers can apply risk: manual to freeze automated risk recalculation when context requires human judgment. This prevents the PR Labeler from auto-correcting the risk label on subsequent edits.

Sources: docs/pr-workflow.md:238, docs/ci-map.md:51


Review Process

Two-Lane Review Model

ZeroClaw uses a two-lane review model to handle high PR volume efficiently:

Lane A: Fast Triage (Agent-Friendly)

Applicable to risk: low PRs:

Check Purpose Automation Support
Template completeness Ensure scope is documented PR Intake Checks validates
CI gate signal Confirm tests pass CI Required Gate status
Risk class verification Confirm labels match paths PR Labeler applies
Rollback statement Verify recovery plan exists Manual review
Privacy/data hygiene Confirm neutral test language PR Intake Checks validates

Lane B: Deep Review (Risk-Based)

Required for risk: high PRs:

Check Purpose Review Focus
Threat model validation Ensure security assumptions are sound Security boundaries, attack vectors
Failure mode analysis Verify degradation behavior Error handling, fallback paths
Backward compatibility Check migration impact Breaking changes, version skew
Observability impact Verify logging/metrics Debugging capability

Sources: docs/pr-workflow.md:294-316

Review Priority Queue

flowchart TD
    Queue["Open PRs"] --> Priority{"Triage<br/>order"}
    
    Priority -->|"1. High"| P1["size: XS/S<br/>+<br/>Bug/Security fixes"]
    Priority -->|"2. Medium"| P2["size: M<br/>Focused changes"]
    Priority -->|"3. Low"| P3["size: L/XL<br/>Split request or<br/>staged review"]
    
    P1 --> FastLane["Fast Triage Lane"]
    P2 --> CheckRisk{"Risk<br/>class?"}
    CheckRisk -->|High| DeepLane["Deep Review Lane"]
    CheckRisk -->|Low/Medium| FastLane
    P3 --> SplitDiscussion["Discuss split strategy"]
    
    FastLane --> Target48h["Target: 48h first triage"]
    DeepLane --> Target48h
Loading

Sources: docs/pr-workflow.md:319-335

Queue Discipline

  • First triage target: Within 48 hours of PR opening
  • Blocked PRs: Maintainer leaves one actionable checklist of blockers
  • Stale automation: pr-check-stale.yml marks dormant PRs; maintainers can apply no-stale for accepted work
  • Hygiene automation: pr-check-status.yml nudges PRs every 12 hours when behind main or missing CI Required Gate

Sources: docs/pr-workflow.md:212-217, docs/ci-map.md:59-64


AI-Assisted Contributions

AI-assisted and agent-generated PRs are welcome. Review can also be agent-assisted.

Required for AI-Heavy PRs

Requirement Purpose
Clear PR summary with scope boundary Enable fast context acquisition
Explicit test/validation evidence Prove correctness without full manual verification
Security impact and rollback notes Document risk for risky changes

Recommended Practices

  • Brief tool/workflow notes when automation materially influenced the change
  • Optional prompt/plan snippets for reproducibility
  • Not required: Quantifying AI-vs-human line ownership

Review Emphasis

For agent-assisted PRs, reviewers should verify:

  1. Contract compatibility: Does the change honor existing trait contracts and API boundaries?
  2. Security boundaries: Are path checks, allowlists, and sandboxing preserved?
  3. Error handling: Are failure modes handled gracefully with fallback behavior?
  4. Performance: Are there memory leaks, N+1 queries, or hot-loop regressions?

Sources: docs/pr-workflow.md:185-208

Agent Handoff Contract

When one agent hands off review to another (or to a maintainer), include:

  1. Scope boundary (what changed, what didn't)
  2. Validation evidence
  3. Open risks and unknowns
  4. Suggested next action

Sources: docs/pr-workflow.md:337-348


Label Automation

Label Application Flow

flowchart TD
    PROpen["PR Opened/Updated"] --> Labeler["PR Labeler Workflow<br/>.github/workflows/pr-labeler.yml"]
    
    Labeler --> CalcScope["Calculate scope labels<br/>from changed paths"]
    CalcScope --> CalcSize["Calculate size label<br/>from effective lines"]
    CalcSize --> CalcRisk["Calculate risk label<br/>from touched paths"]
    CalcRisk --> CalcModule["Extract module labels<br/>from keywords"]
    CalcModule --> CalcTier["Apply contributor tier<br/>by merged PR count"]
    
    CalcTier --> Dedupe["De-duplicate less-specific<br/>scope labels"]
    Dedupe --> Compact["Compact module namespaces<br/>to reduce noise"]
    Compact --> Priority["Priority-sort labels:<br/>risk → size → tier → module"]
    Priority --> Apply["Apply to PR"]
    
    Apply --> Colors["Set label colors for<br/>smooth gradient"]
    Colors --> Tooltips["Update label descriptions<br/>with rule summaries"]
Loading

Sources: docs/pr-workflow.md:110-120, docs/ci-map.md:41-53

Label Categories and Examples

Category Example Labels Auto-Applied? Manual Override
Risk risk: low, risk: medium, risk: high Yes Apply risk: manual to freeze
Size size: XS, size: S, size: M, size: L, size: XL Yes Auto-corrected on edits
Contributor Tier trusted (≥5 merged), experienced (≥10), principal (≥20), distinguished (≥50) Yes Auto-corrected on edits
Module channel:telegram, provider:kimi, tool:shell, memory:sqlite Yes Can add manually
Scope scope:agent, scope:gateway, scope:scheduler, scope:ci Yes Can add manually
Route r:needs-repro, r:support, stale-candidate, superseded No Apply manually for triage

Sources: docs/pr-workflow.md:113-119, docs/ci-map.md:41-53

Label Hygiene Rules

  • Hierarchical de-duplication: More specific scope labels suppress less specific ones (e.g., tool:composio suppresses tool:core and tool)
  • Module compaction: One specific module keeps prefix:component, but multiple collapse to base prefix
  • Color gradient: Managed labels are colored to produce a smooth visual gradient when many labels are present
  • Tooltip descriptions: Hovering a label shows its auto-managed description explaining the rule/threshold

Sources: docs/pr-workflow.md:113-119, docs/ci-map.md:43-49


Merge Process

Merge Method

ZeroClaw uses squash merge exclusively to keep main history compact and bisectable.

Commit Message Format

Squash merge commit titles must follow Conventional Commits:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Examples:

  • feat(channels): add WhatsApp signature verification
  • fix(security): prevent symlink escape in workspace_only mode
  • docs: update onboarding wizard screenshots
  • chore(deps): update rust crate tokio to 1.42.0

Pre-Merge Checklist

Before clicking "Squash and merge", maintainers verify:

Check Purpose
Scope is focused and understandable Ensure change is reviewable and revertible
CI Required Gate is green Confirm all merge gates pass
Docs quality checks green (if docs changed) Ensure documentation standards are met
Security impact fields complete Document security boundary changes
Privacy/data hygiene complete Prevent PII/sensitive data leakage
Rollback plan explicit Enable fast recovery if issues arise
Commit title follows Conventional Commits Maintain clean history for changelog generation

Sources: docs/pr-workflow.md:281-291

Merge Timing

  • Fast path: risk: low + size: XS/S PRs with clean CI can merge same-day
  • Standard path: risk: medium + size: M PRs typically merge within 48-72 hours
  • Deep review path: risk: high or size: L/XL PRs may take 3-5 days depending on review queue depth

Sources: docs/pr-workflow.md:212-217


Failure Recovery Protocol

If a merged PR causes regressions or incidents:

Immediate Response

flowchart LR
    Incident["Regression Detected"] --> Revert["1. Revert PR immediately<br/>on main branch"]
    Revert --> Issue["2. Open follow-up issue<br/>with root cause analysis"]
    Issue --> RegressionTest["3. Write regression test<br/>proving failure"]
    RegressionTest --> Fix["4. Re-introduce fix<br/>with test"]
    Fix --> Verify["5. Verify fix resolves<br/>original issue"]
Loading

Recovery Steps

  1. Revert immediately: Use git revert to restore main to working state
  2. Root cause analysis: Open issue documenting what failed, why, and blast radius
  3. Regression test: Write test that would have caught the failure
  4. Re-introduce fix: New PR with regression test + original fix
  5. Verify: Confirm both original issue and regression are resolved

Recovery Priority

Prefer fast restore of service quality over delayed perfect fixes.

If a revert causes temporary feature loss but restores stability, revert immediately and re-introduce the feature properly in a follow-up PR.

Sources: docs/pr-workflow.md:270-277


Backlog Management

Superseded PRs

When a new PR replaces an older open PR:

  1. Add Supersedes #<old-pr-number> to new PR description
  2. Maintainer confirms superseding PR is superior
  3. Close old PR with comment linking to new PR
  4. Apply superseded label to old PR

Stale PRs

The pr-check-stale.yml workflow marks PRs stale after inactivity:

  • Stale threshold: 60 days no activity
  • Close threshold: 7 days after stale label applied
  • Exceptions: Apply no-stale label for accepted-but-blocked work

Queue Budget Controls

Maintainers use queue budget controls to prevent review overload:

  • Limit concurrent deep-review PRs per maintainer
  • Keep remaining PRs in triage state
  • For stacked work, require explicit Depends on #... for deterministic review order

Sources: docs/pr-workflow.md:219-240


Issue Triage

While this page focuses on PR workflow, related issue triage labels help keep the bug backlog healthy:

Label Purpose Action
r:needs-repro Bug report lacks deterministic reproduction Request concrete repro steps
r:support Usage/help question better suited for discussions Route to support channels
invalid Not a bug or request Close with explanation
duplicate Already tracked elsewhere Close with link to original

Note: Automated close routes apply to issues only, never PRs. Maintainers own PR close/merge decisions.

Sources: docs/pr-workflow.md:228-233


Related Documentation

Sources: docs/pr-workflow.md:350-356


Clone this wiki locally