Skip to main content

Collective Code Construction Contract (C4) - Mbin

  • Status: final
  • Editor: Melroy van den Berg (melroy at melroy dot org)

The Collective Code Construction Contract (C4) is an evolution of the github.com Fork + Pull Model, aimed at providing an optimal collaboration model for free software projects. This is our Mbin revision of the upstream C4 specification, built on the lessons learned from the experience of many other projects and the original C4 specification itself.

License

Copyright (c) 2009-2016 Pieter Hintjens. Copyright (c) 2016-2018 The ZeroMQ developers. Copyright (c) 2023-2024 Melroy van den Berg & Mbin developers.

This Specification is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This Specification is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, see http://www.gnu.org/licenses.

Abstract

C4 provides a standard process for contributing, evaluating and discussing improvements on software projects. It defines specific technical requirements for projects like a style guide, unit tests, git and similar platforms. It also establishes different personas for projects, with clear and distinct duties. C4 specifies a process for documenting and discussing issues including seeking consensus and clear descriptions, use of “pull requests” and systematic reviews.

Language

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

1. Goals

C4 is meant to provide a reusable optimal collaboration model for open source software projects. It has these specific goals:

  1. To maximize the scale and diversity of the community around a project, by reducing the friction for new Contributors and creating a scaled participation model with strong positive feedbacks;
  2. To relieve dependencies on key individuals by separating different skill sets so that there is a larger pool of competence in any required domain;
  3. To allow the project to develop faster and more accurately, by increasing the diversity of the decision making process;
  4. To support the natural life cycle of project versions from experimental through to stable, by allowing safe experimentation, rapid failure, and isolation of stable code;
  5. To reduce the internal complexity of project repositories, thus making it easier for Contributors to participate and reducing the scope for error;
  6. To enforce collective ownership of the project, which increases economic incentive to Contributors and reduces the risk of hijack by hostile entities.

2. Design

2.1. Preliminaries

  1. The project SHALL use the git distributed revision control system.
  2. The project SHALL be hosted on github.com or equivalent, herein called the “Platform”.
  3. The project SHALL use the Platform issue tracker.
  4. The project SHOULD have clearly documented guidelines for code style.
  5. A code change is refer to as a “patch” or “PR” on the Platform.
  6. A “Contributor” is a person who wishes to provide a patch/PR, being a set of commits that solve some clearly identified problem.
  7. A “Maintainer” is a person who merges patches/PRs to the project. Maintainers can also be developers / contributors at the same time.
  8. Maintainers are owners of the project. There is no single “founder” or “creator” of the project.
  9. Contributors SHALL NOT have commit access to the repository unless they are also Maintainers.
  10. Maintainers SHALL have commit access to the repository.
  11. Administrators SHALL have administration rights on the Platform.
  12. Everyone, without distinction or discrimination, SHALL have an equal right to become a Contributor under the terms of this contract.

2.2. Licensing and Ownership

  1. The project SHALL use the share-alike license: AGPL.
  2. All contributions (patches/PRs) to the project source code SHALL use the same license as the project.
  3. All patches / PRs are owned by their authors. There SHALL NOT be any copyright assignment process.

2.3. Patch / PR Requirements

  1. A patch / PR SHOULD be a minimal and accurate answer to exactly one identified and agreed problem.
  2. A patch / PR MUST adhere to the code style guidelines of the project if these are defined.
  3. A patch / PR MUST adhere to the “Evolution of Public Contracts” guidelines defined below.
  4. A patch / PR SHALL NOT include non-trivial code from other projects unless the Contributor is the original author of that code.
  5. A patch / PR SHALL NOT include libraries that are incompliant with the project license.
  6. A patch / PR MUST compile cleanly and pass project self-tests (for example unit tests or linting) before a Maintainer can merge it. Also known as the “All-green policy”.
  7. A commit message MUST consist of a single short (less than 100 characters) line stating the problem and/or solution that is being solved.
  8. A commit message MAY be prefixed with a addenum “FIX:”, “FEAT:”, “DOCS:”, “TEST:”, “REFACTOR:” or "IMPROVEMENT:" to indicate the type of commit. Also known as “semantic commit messages”.
  9. A commit type MAY be part of the PR title as well however using Labels on the Platform PR is usually preferred way of classifying the type of the Patch / PR.
  10. A “Correct Patch / PR” is one that satisfies the above requirements.

2.4. Development Process

  1. Change on the project SHALL be governed by the pattern of accurately identifying problems and applying minimal, accurate solutions to these problems.
  2. To request changes, a user SHOULD log an issue on the project Platform issue tracker.
  3. The user or Contributor SHOULD write the issue by describing the problem they face or observe.
  4. The user or Contributor SHOULD seek consensus on the accuracy of their observation, and the value of solving the problem.
  5. Users SHALL NOT log feature requests, ideas, suggestions, or any solutions to problems that are not explicitly documented and provable.
  6. Thus, the release history of the project SHALL be a list of meaningful issues logged and solved.
  7. To work on an issue, a Contributor SHOULD fork the project repository and then work on their forked repository. Unless the Contributor is also a Maintainer then a fork is NOT required, creating a new git branch SHOULD be sufficient.
  8. To submit a patch, a Contributor SHALL create a Platform pull request back to the project.
  9. Maintainers or Contributors SHOULD NOT directly push changes to the default branch (main), instead they SHOULD use the Platform Pull requests functionality. (See also branch protection rules of the Platform)
  10. Contributors or Maintainers SHALL mark their PRs as “Draft” on the Platform, whenever the patch/PR is not yet ready for review / not finished.
  11. If the Platform implements pull requests as issues, a Contributor MAY directly send a pull request without logging a separate issue.
  12. To discuss a patch (PR), people SHOULD comment on the Platform pull request, on the commit, or on Matrix Space (chat). We have various Matrix Rooms (also a dedicated Matrix room for Pull Requests/Reviews).
  13. Contributors MAY want to discuss very large / complex changes (PRs) in the Matrix Space first, since the effort might be all for nothing if the patch is rejected by the Maintainers in advance.
  14. To request changes, accept or reject a patch / PR, a Maintainer SHALL use the Platform interface.
  15. Maintainers SHOULD NOT merge patches (PRs), even their own, unless there is at least one (1) other Maintainer approval. Or in exceptional cases, such as non-responsiveness from other Maintainers for an extended period (more than 3-4 days), and the patch / PR has a high criticality level and cannot be waited on for more than 4 days before being merged.
  16. Maintainers SHALL merge their own patches (PRs). Maintainers SHALL NOT merge patches from other Maintainers without their consent.
  17. Maintainers SHOULD merge patches (PRs) from other Contributors, since Contributors do NOT have the rights to merge Pull Requests.
  18. Maintainers SHALL NOT make value judgments on correct patches (PRs).
  19. Maintainers SHALL merge correct patches (PRs) from other Contributors rapidly.
  20. Maintainers MAY merge incorrect patches (PRs) from other Contributors with the goals of (a) ending fruitless discussions, (b) capturing toxic patches (PRs) in the historical record, (c) engaging with the Contributor on improving their patch (PR) quality.
  21. The user who created an issue SHOULD close the issue after checking the patch (PR) is successful. Using “Closing keywords” in the description with a reference to the issue on the Platform will close the issue automatically. For example: “Fixes #251”.
  22. Any Contributor who has value judgments on a patch / PR SHOULD express these via their own patches (PRs). Ideally after the correct patch / PR has been merged, avoiding file conflicts.
  23. Maintainers SHALL use the “Squash and merge” option on the Platform pull request interface to merge a patch (PR).
  24. Stale Platform Action is used to automatically mark an issue or a PR as “stale” and close the issue over time. PRs will NOT be closed automatically.

2.5. Branches and Releases

  1. The project SHALL have one branch (“main”) that always holds the latest in-progress version and SHOULD always build.
  2. The project MAY use topic / feature branches for new functionality.
  3. To make a stable release a Maintainer SHALL tag the repository. Stable releases SHALL always be released from the repository main.
  4. A Maintainer SHOULD create a release from the Platform Release page. The release description SHOULD contain our template table (“DB migrations”, “Cache clearning”, etc.) as well as releases notes (changes made in the release) in all cases.

2.6. Evolution of Public Contracts

  1. All Public Contracts (APIs or protocols and their behaviour and side effects) SHALL be documented.
  2. All Public Contracts SHOULD have space for extensibility and experimentation.
  3. A patch (PR) that modifies a stable Public Contract SHOULD not break existing applications unless there is overriding consensus on the value of doing this.
  4. A patch (PR) that introduces new features SHOULD do so using new names (a new contract).
  5. New contracts SHOULD be marked as “draft” until they are stable and used by real users.
  6. Old contracts SHOULD be deprecated in a systematic fashion by marking them as “deprecated” and replacing them with new contracts as needed.
  7. When sufficient time has passed, old deprecated contracts SHOULD be removed.
  8. Old names SHALL NOT be reused by new contracts.
  9. A new contract marked as “draft” MUST NOT be changed to “stable” until all the following conditions are met:
    1. Documentation has been written and is as comprehensive as that of comparable contracts.
    2. Self-tests exercising the functionality are passing.
    3. No changes in the contract have happened for at least one public release.
    4. No changes in the contract have happened for at least 6 months.
    5. No veto from the Contributor(s) of the new contract and its implementation on the change of status.
  10. A new contract marked as “draft” SHOULD be changed to “stable” when the above conditions are met.
  11. The “draft” to “stable” transition status for new contracts SHOULD be tracked using the Platform issue tracker.

2.7. Project Administration

  1. The project's existing Maintainers SHALL act as Administrators to manage the set of project Maintainers.
  2. The Administrators SHALL ensure their own succession over time by promoting the most effective Maintainers.
  3. A new Contributor who makes correct patches (PRs), who clearly understands the project goals. After a discussion with existing Maintainers whether we SHOULD be invite a new Contributor, the new Contributor SHOULD be invited to become a Maintainer. But only after the new Contributor has demonstrated the above for a period of time (multiple correct PRs and more than 2-3 months).
  4. Administrators MAY remove Maintainers that are long inactive (~1-2 years). Mainly due to security reasons. The Maintainer can always return back, if the person wants to become Maintainer again.
  5. Administrators SHOULD remove Maintainers who repeatedly fail to apply this process accurately.
  6. Administrators SHOULD block or ban “bad actors” who cause stress and pain to others in the project. This should be done after public discussion, with a chance for all parties to speak. A bad actor is someone who repeatedly ignores the rules and culture of the project, who is needlessly argumentative or hostile, or who is offensive, and who is unable to self-correct their behavior when asked to do so by others. If the majority of the currently active Maintainers agrees (or neutral) on the removal of the “bad actor” (after giving the “bad actor” time to self-improve), it can then be the final agreement on the decision to proceed with removal.

Further Reading

  • Original C4 rev. 3 - C4 by Pieter Hintjens

  • Argyris’ Models 1 and 2 - the goals of C4 are consistent with Argyris’ Model 2.

  • Toyota Kata - covering the Improvement Kata (fixing problems one at a time) and the Coaching Kata (helping others to learn the Improvement Kata).