Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ For the full legal text, please refer to the included files:
- [`COPYING`](COPYING) (GPLv3)
- [`COPYING.LESSER`](COPYING.LESSER) (LGPLv3)

The licenses above govern permissions granted to recipients. They do not
restrict a copyright holder from separately reusing, relicensing, or
incorporating material for which that copyright holder owns all necessary
rights into another work under different terms. This clarification does not
grant any right to relicense third-party material or contributions for which
the necessary rights are not held.

---

Copyright (c) 2012-2026 Automatic Ruby Developers.
Expand Down
220 changes: 166 additions & 54 deletions doc/POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ responsibilities of the parts and the direction of dependency between them, the
handling of settings and credentials, the approach to tests and documentation,
the versioning scheme, and the criteria a change is judged by.

It stands on its own. No rule here is completed by a document kept in another
repository, and a subject it does not cover is a gap in this document, to be
filled here rather than looked up elsewhere.
This document stands on its own. It is the whole implementation policy of this
repository, and no rule here is completed by a document kept somewhere else. A
subject it does not cover is a gap in this document, to be filled here rather
than looked up elsewhere.

What the system is for belongs to [`REQUIREMENTS.md`](REQUIREMENTS.md). How it
is composed belongs to [`BASIC_DESIGN.md`](BASIC_DESIGN.md). The Recipe format
Expand All @@ -22,9 +23,25 @@ The Invariants below decide over the rest of it.

**Simplicity is robustness.**

This principle governs the following implementation and maintenance rules. It
does not permit dropping required behavior, security, compatibility, or
validation. Satisfy those obligations without unnecessary complexity.
This is the governing principle for every rule below. It does not authorize
dropping required behavior, compatibility, security, safety, documentation, or
validation. It requires satisfying those requirements with no more complexity
than the actual problem justifies.

Complexity is itself a source of failure, compatibility risk, operational risk,
security risk, and maintenance cost. Do not add a branch, state variable,
helper, abstraction, dependency, network boundary, retry, fallback, validation,
configuration state, or framework unless the specification requires it or it
addresses a realistic failure mode with meaningful consequence.

Do not re-check a condition already guaranteed by a preceding successful
operation or an established invariant. Do not create a layer merely to resemble
a possible future architecture.

When two designs satisfy the same requirements, choose the one with less
control flow, less state, fewer dependencies, fewer side effects, fewer moving
parts, and fewer operational assumptions. Simplicity is judged by the number of
necessary concepts and behaviors, not by line count alone.

## 1. General Policy

Expand Down Expand Up @@ -124,18 +141,22 @@ degree of conservatism.
- Understand why something exists before replacing it. A constant that looks
arbitrary usually encodes an operational fact.
- A capability that can live in a plugin lives in a plugin.
- Where a decision looks odd, a comment gives the reason, so that a later change
does not quietly undo it.
- A comment preserves a reason, constraint, non-obvious intent, or decision that
a later change could otherwise undo. Do not use comments merely to restate code
whose operation is already evident.
- Old is not a defect. Neither is unfashionable. A defect is something that does
not work, is not understood, or cannot be tested.
- Use `must`, `always`, and `never` only for invariants that admit no
reasonable exception. Express preferences and situational decisions with
`prefer`, `should`, or other qualified wording. Do not apply a rule literally
where doing so would defeat the repository's stated purpose, intended
behavior, compatibility, safety, or approved change scope. Where the
applicable specifications and policy leave a legitimate choice open, an
explicit maintainer decision governs that choice, and general conventions do
not override it.
- Use `must`, `always`, and `never` only for invariants that admit no reasonable
exception. Express preferences and situational decisions with `prefer`,
`should`, or other qualified wording.

Do not apply a rule literally where doing so would defeat the repository's
stated purpose, intended behavior, compatibility, safety, or approved change
scope.

Where the applicable specifications and policy leave a legitimate choice
open, an explicit maintainer decision governs that choice. General
conventions do not override it.

### 1.4 Change discipline and maintenance boundary

Expand All @@ -144,10 +165,28 @@ for long-lived host infrastructure. Its core contracts deserve comparable
caution because external Recipes and plugins depend on them, but the whole
repository is not treated as immutable infrastructure.

Finding a possible safety, portability, maintainability, cleanup,
modernization or refactoring improvement does not by itself authorize an
implementation change. A change is made when that change is part of the stated
work, not merely because an opportunity was noticed while editing nearby code.
Documentation work, policy work, review, diagnostics, cleanup, or another
task whose stated scope does not include an implementation change must not
expand into one merely because an improvement opportunity is discovered.

Before changing established behavior, weigh the probability and impact of the
failure being prevented against the added complexity, new failure modes,
compatibility risk, operational cost, maintenance cost, and rollback cost.

A safety-motivated change is not automatically justified by Safety having
priority over Efficiency. Added complexity can itself create new failure
modes, compatibility risk, operational risk, and maintenance cost. Evaluate
the proposed change as a whole.

Behavior that has operated reliably over time is evidence and has value of
its own. Do not refactor established infrastructure merely because another
design appears cleaner, more modern, or more defensive.

An implementation change is made only when that change has been explicitly
chosen as part of the work being performed. Before deployment, validate it in
the supported and representative environments affected by the change. A
successful check in one convenient environment is not sufficient evidence for
a change whose compatibility risk extends to other supported environments.

Established behaviour is evaluated by layer. A Recipe or plugin contract that
has been used for years has strong compatibility value. A framework internal
Expand Down Expand Up @@ -348,12 +387,16 @@ Dependency points one way and there is no edge back up:

### 1.13 Judging a change

Before accepting a change, ask whether it is the smallest coherent change that
serves its purpose, whether it alters behavior outside that purpose, whether it
adds an unnecessary dependency or side effect, whether it exposes private
information, and whether directly affected documentation remains correct.

- Does it keep the Recipe format and the plugin contract, and if not, is that
deliberate and recorded?
- Does it respect the direction of dependency?
- Does it leave the framework the small part?
- Does it keep a plugin's dependency out of everyone else's installation?
- Is it the smallest change that does the job?
- Does a test say it works, and does the default suite still need no network?
- Do the documents still match the code, in the same commit?
- Which layer is changing: a core contract, framework implementation or a
Expand All @@ -369,19 +412,35 @@ Dependency points one way and there is no edge back up:
### 1.14 Pull Request Scope and History

A pull request carries one coherent higher-level purpose, which may require
coordinated changes across several files or responsibilities. Do not split one
approved purpose mechanically by individual finding, file, or review comment,
and do not include unrelated cleanup, formatting, or feature work. Represent
one coherent change as one commit and amend review corrections instead of
accumulating follow-up commits. Use `--force-with-lease` only on the branch
under review when a safe history rewrite is required. Check the final branch
against its base to remove abandoned intermediate wording and work. Merge only
with explicit maintainer approval.

An automated agent must not commit or push directly to `master`.
It must commit authorized changes to a work branch and submit them through
a pull request targeting the approved base branch. This paragraph does not
change a human maintainer's authority or the existing merge approval rule.
coordinated changes across several files or responsibilities.

Do not split one approved purpose mechanically by individual finding, file,
or review comment, and do not include unrelated cleanup, formatting, or
feature work.

Represent one coherent change as one commit and amend review corrections
instead of accumulating follow-up commits.

Rewriting the history of a branch under review requires an explicit
instruction from the maintainer. When such a rewrite is authorized, use
`--force-with-lease` and limit the operation to the branch under review.

Check the final branch against its base to remove abandoned intermediate
wording and work. Merge only with explicit maintainer approval.

Unless explicitly instructed otherwise by the maintainer, an automated agent
must commit authorized changes to a work branch and submit them through a
pull request targeting the approved base branch.

An automated agent must not commit or push directly to `master` without
explicit instructions from the maintainer authorizing that operation.

Creating or updating a pull request does not authorize the agent to merge it
or enable auto-merge. Either action requires an explicit instruction from
the maintainer.

Authorization for one operation does not imply authorization for another.
These rules do not change a human maintainer's authority.

---

Expand All @@ -406,13 +465,28 @@ makes a diff harder to read than the style saves.
- Prefer a guard clause to a wrapping `unless`, in new code.
- Write English explanatory prose in clear, natural sentences. Do not replace a
sentence with a label and a colon, a status prefix such as `Implement:` or
`Incompatible:`, a symbol, or an unexplained abbreviation. Apply this to
English prose in comments, docstrings, documentation, version histories,
release notes, commit messages, and pull request descriptions. This rule does
not alter the established forms of headings, list labels, tables, code,
configuration syntax, machine-readable fields, literal interface strings, or
non-English content required by the repository's purpose. Do not rewrite
historical entries or unrelated text merely to align their style.
`Incompatible:`, a symbol, or an unexplained abbreviation.

Apply this to English prose in comments, docstrings, documentation, version
histories, release notes, commit messages, and pull request descriptions.

This rule does not alter the established forms of headings, list labels,
tables, code, configuration syntax, machine-readable fields, literal
interface strings, or non-English content required by the repository's
purpose.

Wrap ordinary prose at approximately 80 columns where practical. Preserve
the logical structure of paragraphs, lists, and other document elements.
Do not break URLs, code, tables, identifiers, or other elements whose
structure requires a longer line.

Shared boilerplate must retain its common wording, line breaks, blank lines,
and formatting. Do not reformat it independently in individual repositories.
Its established common form takes precedence over the ordinary line-wrapping
guideline.

Do not rewrite historical entries or unrelated text merely to align their
style.

### 2.2 Scope of a change

Expand Down Expand Up @@ -468,8 +542,8 @@ appear in the order shown below. An executable uses this canonical form:
place in existing files, because removing it across existing files is a diff with
no benefit, and it is not required in a new file.

Files do not carry a per-file version history. This repository versions at the
repository level only. See section 10.
Ruby files do not carry a per-file version history. Ruby source is versioned
at the repository level. See Section 10.

### 2.4 Ruby version compatibility

Expand Down Expand Up @@ -701,7 +775,11 @@ behaviour breaks nothing.

- **Documentation is updated in the same change as the behaviour it describes.**
A behaviour change with no documentation change has not been finished.
- The documents divide as follows, and one fact has one home:
- A concrete specification has exactly one authoritative home appropriate to the
responsibility that owns it. Other documents may link to or summarize that
specification for navigation, but they do not create a competing normative
copy.
- The documents divide as follows:

| Document | Holds |
| --- | --- |
Expand All @@ -715,6 +793,17 @@ behaviour breaks nothing.
| `doc/LICENSE.md`, `doc/COPYING`, `doc/COPYING.LESSER` | The licence |
| `doc/AUTHORS` | Contributors |

- The implementation is the primary evidence of what currently happens. It is
not, by itself, proof that the current behavior is the intended specification.

When implementation and documentation disagree, compare the implementation,
documented interface, component header, history, existing design, and
maintenance intent. If the implementation contains a regression, do not adopt
that regression as the specification merely because it is present in the
current code.
- Content adapted from an external article, answer, documentation example, source
file, dataset, or other third-party material credits its source and respects
the license or redistribution terms that apply to it.
- **No cross-repository reference.** These documents never say "see the policy
of another repository", or "as in *X*". Everything needed to understand,
build, run and change this repository is here. Another repository may be a
Expand Down Expand Up @@ -925,16 +1014,16 @@ the version history records what it amounts to.
- Each entry opens with `vX.YY (YYYY-MM-DD)`, or `vX.YY (Release Date: TBD)`
while unreleased, underlined with `-`, followed by one `-` bullet per change.
Newest first. UTF-8.
- **One coherent change is one bullet, at most two physical lines.** A single
line at or under 80 columns is preferred whenever practical. This is an
explicit limit, not a prompt to reread: a bullet that runs past two lines,
or a single line that runs past 80 columns without necessity, must be
shortened. The entry is a list meant to be scanned, and a bullet that grows
past this limit costs it that: the eye no longer finds the changes by
counting lines, and a diff no longer shows a small, bounded edit.
- A bullet carrying file names, module names, setting names or plugin names
may pass 80 columns on its one or two lines when those names cannot be
shortened without losing meaning. The two-line ceiling still applies.
- Write one coherent change per bullet, at most two physical lines.
- A single line at or under 80 columns is preferred whenever practical.
Names and identifiers necessary to describe the change may pass 80 columns
on the bullet's one or two lines when they cannot be shortened without
losing meaning.
- When a version history already exists, balance a new entry against the
length of the existing lines, so that the whole file stays consistent.
Holding to the form this file has settled on comes before the two-line,
80-column limit above, and leaves that limit standing wherever no such
form exists.
- **When a bullet runs long, abstract it first.** Drop the implementation
detail, the example, the reason and the secondary effect, and state what
the change is. Wrap onto the second line only when the abstracted bullet
Expand Down Expand Up @@ -969,6 +1058,29 @@ the version history records what it amounts to.
- Where the record is incomplete — releases with no tag, or a version bumped
with no entry — `VERSIONS` says so rather than inventing an entry.

### 10.6 Source File Version Numbering

The Ruby file-header convention in Section 2.3 remains unchanged. The
following rules apply to the existing versioned shell build script, not to
Ruby files that carry no individual version history.

These rules apply to individual source files that carry their own version
history. Repository release versions are governed separately.

- Source file versions use a two-level `major.minor` scheme.
- When incrementing `minor` would reach `10`, roll over instead: increment
`major` by 1 and reset `minor` to `0` (for example `v0.9` -> `v1.0`,
`v1.9` -> `v2.0`, `v2.9` -> `v3.0`).
- Do not continue `minor` past `9` as in standard semantic versioning
(do not use `v1.10`, `v1.11`, ...).
- Raising `major` for a reason other than the rollover is a decision the
maintainer makes, not one this document derives from the change.
- Removing or renaming an option, changing what an existing argument means,
changing a default so that an unchanged invocation does something else, and
changing how a path or a configuration value is resolved are all incompatible
changes. Say so in the `Version History` entry, so that the number the change
is released under can be chosen knowing that.

---

## 11. Continuous integration
Expand Down
Loading
Loading