From f1af0ef593f5132ca8663bc88d42653229fba119 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 6 Dec 2025 09:40:35 -0500 Subject: [PATCH 1/3] Revise decision process: champion vs FCP decisions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the previous "reversible/consensus" framing with "champion/FCP" decisions based on PR feedback. Key changes: - Champion decisions: triage nomination instead of rfcbot poll, any team member can request FCP escalation at any time - FCP decisions: new concern resolution process with dedicated issues and resolution template, original concern-raiser cannot block resolution - Two-pizza team (4-8 members): removes ratio formulas - Updated how_to pages to use new terminology 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- book.toml | 3 + src/SUMMARY.md | 6 +- src/champion-decisions.md | 41 +++++ src/decision-making.md | 35 ++++ src/decision_process.md | 53 ------ src/decision_process/examples.md | 297 ------------------------------ src/decision_process/reference.md | 194 ------------------- src/fcp-decisions.md | 76 ++++++++ src/how_to/experiment.md | 6 +- src/how_to/propose.md | 9 +- src/how_to/stabilize.md | 2 +- 11 files changed, 166 insertions(+), 556 deletions(-) create mode 100644 src/champion-decisions.md create mode 100644 src/decision-making.md delete mode 100644 src/decision_process.md delete mode 100644 src/decision_process/examples.md delete mode 100644 src/decision_process/reference.md create mode 100644 src/fcp-decisions.md diff --git a/book.toml b/book.toml index 8efc422..7c32c55 100644 --- a/book.toml +++ b/book.toml @@ -39,3 +39,6 @@ command = "mdbook-mermaid" "/initiatives/process/stages.html" = "how_to/propose.html" "/initiatives/process.html" = "how_to/propose.html" "/initiatives/stable.html" = "how_to/propose.html" +"./decision_process.md" = "decision-making.md" +"./decision_process/examples.md" = "decision-making.md" +"./decision_process/reference.md" = "decision-making.md" diff --git a/src/SUMMARY.md b/src/SUMMARY.md index b1b6a9e..7e46795 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -8,9 +8,9 @@ - [Propose or extend a new lint?](./how_to/new_lint.md) - [Add an experimental feature gate](./how_to/experiment.md) - [Stabilize a feature](./how_to/stabilize.md) -- [Decision process and principles](./decision_process.md) - - [Decision process examples](./decision_process/examples.md) - - [Decision process reference](./decision_process/reference.md) +- [Decision making](./decision-making.md) + - [Champion decisions](./champion-decisions.md) + - [FCP decisions](./fcp-decisions.md) - [Becoming and being a lang-team member](./membership.md) - [Lang-team leads](./leads.md) - [Chat platform](./chat_platform.md) diff --git a/src/champion-decisions.md b/src/champion-decisions.md new file mode 100644 index 0000000..5fa0a84 --- /dev/null +++ b/src/champion-decisions.md @@ -0,0 +1,41 @@ +# Champion decisions + +Champion decisions do not represent team consensus. Rather, they indicate that *somebody* on the team is willing to champion an idea. We use them to begin experiments and for other decisions where we want to move quickly and iterate. + +## When to use champion decisions + +* Starting a [lang-team experiment](./how_to/experiment.md) +* Closing an RFC or issue that is clearly not going to be accepted +* Other lightweight decisions that don't make a durable commitment + +## Process + +### For the champion (lang team member or advisor) + +1. Write up your proposal on a GitHub issue or PR, explaining the decision and context. +2. [Nominate](./how_to/nominate.md) it for discussion at a lang-team triage meeting. +3. At the triage meeting, the team will discuss and raise any concerns. +4. If no one requests FCP escalation, you can proceed. + +### Handling concerns + +When people raise concerns: + +* **Treasure dissent.** Engage with them and make sure you understand the concern. +* Note concerns on the tracking issue as "unresolved questions" or things to explore—they shouldn't be forgotten. +* Concerns don't *block* you from proceeding, but they may give you pause, particularly if they are shared by multiple team members. + +### FCP escalation + +Any team member can request FCP escalation at any time—during the triage meeting or later. This converts the decision to an [FCP decision](./fcp-decisions.md), which follows the full FCP process. + +Once a champion decision has been escalated and FCP'd, it becomes durable: reversing it would require another FCP. + +No justification is required to request escalation. The request itself signals "I think this matters enough to need the full FCP process." + +## For other team members + +* Your approval is not required for champion decisions. +* If you disagree with the decision or think it's a bad idea, say so (constructively)! +* For experiments, ask yourself: What are the "weak spots" that the experiment ought to probe? What information can we gather? +* If you feel strongly that this should not proceed without team consensus, request FCP escalation. diff --git a/src/decision-making.md b/src/decision-making.md new file mode 100644 index 0000000..ab343b4 --- /dev/null +++ b/src/decision-making.md @@ -0,0 +1,35 @@ +# Decision making + +This page documents our decision making process. + +## Our goal + +We want the ability to make designs that feel fresh, bold, and innovative. We do not want Rust to feel like it has been "designed by committee", with all the interesting bits smoothed down. + +We also want designs that meet Rust users' needs and live up to Rust's ethos of reliable, performant, accessible code. + +These two goals can be in tension. The former pushes us to empower individuals. The latter pushes us to validate designs broadly. We use this decision making process to guide us in balancing those tensions. + +## Design axioms + +Our decision making axioms are rules that we follow to help us achieve our goal. We try to satisfy them all, but if they come into tension, we prefer items that appear first in the list. + +* **No new rationale**. We make decisions only after the rationale has been presented publicly and all relevant stakeholders have had a chance to present counterarguments. +* **Not afraid to do the right thing**. At the end of the day, we have to do what we feel is *right*. Sometimes this means breaking with tradition and precedent set by other languages. Sometimes it means taking a socially uncomfortable stance (but always with respect). +* **Find common ground**. When there is disagreement, look for solutions that address everyone's concerns. Break up designs into smaller pieces if needed. But be sure that each piece solves an end-to-end problem on its own. +* **Trust each other**. Lang team members are expected to have demonstrated sharp instincts, humility, and the ability to hear and understand others. Sometimes you have to put your doubts aside and trust the others on the team. +* **Treasure dissent**. When someone raises a concern, we take it as an opportunity to improve the design, not an obstacle to be overcome. We invite people to elaborate and make sure we understand what's motivating them before we decide how to respond. + +## Two kinds of decisions + +We divide decisions into two categories: + +* **[Champion decisions](./champion-decisions.md)** are the preferred default. They are used for [starting experiments](./how_to/experiment.md) and other decisions where we want to move quickly. A single lang-team member or advisor can champion a decision; others can raise concerns, but cannot block. A champion decision does *not* represent team consensus—it represents only the champion's point of view. Any team member can request FCP escalation at any point—during the initial triage meeting or later—which converts it to an FCP decision. Once a champion decision has been escalated and FCP'd, it becomes durable in the same way as any other FCP decision. + +* **[FCP decisions](./fcp-decisions.md)** represent a significant commitment from the team. They are used for [stabilization](./how_to/stabilize.md), RFC approval, and other cases where we are making a promise to our users or taking a position we don't want to reverse lightly. FCP decisions require broader team sign-off and follow a formal process for resolving concerns. + +**When to use which:** Prefer champion decisions when possible—they have lower overhead and enable faster iteration. Use FCP decisions when the decision is significant enough that reversing it should require another FCP. The expectation is that an FCP'd decision cannot be reversed without some change in circumstances: new experience, new information, or a reasoned change of mind. + +## Team size + +The lang team operates as a "two-pizza team" of 4-8 members. This keeps the team small enough for high-bandwidth communication and trust, while large enough for diverse perspectives. diff --git a/src/decision_process.md b/src/decision_process.md deleted file mode 100644 index 664e3cf..0000000 --- a/src/decision_process.md +++ /dev/null @@ -1,53 +0,0 @@ -This section documents the work-in-progress Rust language team decision -process. This process, and the `rustbot` tooling to support it, does not yet -have a finished implementation. This document serves to explain the intended -process, for the purposes of ongoing implementation. - -## Prioritized principles of Rust team consensus decision-making - -These are in order of priority. They're intended to be general enough that they -could apply to any Rust governance team, not just the language team. - -- **Treasure dissent.** When someone raises a concern, that's a chance to - improve the design, and to discover and explore underlying values. Dissent - should be an amicable, cooperative process. -- **Understand and cooperatively resolve concerns.** We cannot resolve a - concern without first understanding it, including the underlying values - motivating it. We should demonstrate that understanding by documenting the - concern. We should consider the tradeoffs and the impacts on users, through - the Rust design principles. We should seek out and favor satisfying solutions - (those that satisfy everyone's values) over - [satisficing](https://en.wikipedia.org/wiki/Satisficing) solutions (those - that are just good enough for people to accept them as a compromise among - conflicting values, without actually being happy with the outcome). -- **Don't force an irreversible decision.** We should make decisions - reversible whenever we can. When making a necessarily irreversible decision - (e.g. stabilizing a feature), we should pay close attention to dissent, and - hesitate before overriding objections. If possible, we should seek a better - alternative, or seek common ground we can find consensus on, or seek an - intermediate step that addresses the same use case and supports evaluation - for a more informed decision in the future. If none of those are possible, - consider the null alternative; not making a change should always be the - easier path, and the burden of proof to override a concern on an irreversible - decision should be high. -- **Value expertise.** When cooperatively resolving a concern, or when - considering overriding a concern, carefully weigh the advice and - recommendations of experts. This includes team advisors, domain experts, and - the owners or members of relevant initiatives. -- **Recording reasoning helps ensure good, consistent decisions over time.** - Even if we decide not to sustain an objection, we should always record the - objection and the reasons for our decision as a "dissent", as well as any - unresolved questions for evaluation later in the process. The team member who - raised the objection has the perogative to author that dissent and frame the - unresolved questions (within reason). -- **Consensus doesn't mean unanimity.** Consensus means everyone is heard and - understood, and all concerns are addressed (even those not treated as - blocking), and the team finds the outcome reasonable. Consensus does not mean - everyone agrees completely. - -## Consensus decision-making process - -First, see [some examples of the decision-making process in -action](./decision_process/examples.md). Then, read the [decision process -reference](./decision_process/reference.md) for the full process and the -`rustbot` tooling to support it. diff --git a/src/decision_process/examples.md b/src/decision_process/examples.md deleted file mode 100644 index d09bd61..0000000 --- a/src/decision_process/examples.md +++ /dev/null @@ -1,297 +0,0 @@ -# Examples of the decision-making process in action - -## Reversible decision: merging a proposal - -The process is best described by example. Suppose that there is a pending lang -team proposal, and a lang team member would like to serve as the liaison. They -contact the team leads and receive the go-ahead. They can then write: - -> @rustbot merge -> -> I propose to merge this proposal. I think it will be a great addition to -> Rust! - -This indicates that they would like to merge the proposal. At the moment, there -is no decision pending, so rustbot would add a comment that looks like the -following: - -> Hello! @Alan has proposed to merge this. This is a **reversible decision**, -> which means that it will be affirmed once the "final comment period" of 10 -> days have passed, unless a team member places a "hold" on the decision (or -> cancels it). -> -> | Team member | State | -> | --- | --- | -> | @Alan | **merge** | -> | @Barbara | | -> | @Grace | | -> | @Niklaus | | - -As the comment says, the PR is now in "pending decision" state, with Alan -having kicked off the process with a proposal to merge. Alan's status of -**merge** will link to his comment. - -Now, for this particular proposal, Barbara has a concern. She thinks that the -proposal has overlooked an important consideration. She writes a comment: - -> @rustbot hold -> -> Did you consider reversing the polarity? Or the impact on the flux capacitor? - -At this point, rustbot updates the state; Barbara's status of -**hold** will link to her comment: - -> Hello! @Alan has proposed to merge this. This is a **reversible decision**, -> which means that it will be affirmed once the "final comment period" of 10 -> days have passed, unless a team member places a "hold" on the decision (or cancels it). -> -> | Team member | State | -> | --- | --- | -> | @Alan | **merge** | -> | @Barbara | **hold** | -> | @Grace | | -> | @Niklaus | | - -Alan is currently busy at work, though, so by the time that he and Barbara -get a chance to talk, 11 days have passed. (Alan and Barbara receive a ping -from rustbot after a week or so.) Once they get a chance to talk, Alan -fully addresses Barbara's concern, so Barbara posts: - -> @rustbot merge - -The comment is updated: - -> Hello! @Alan has proposed to merge this. This is a **reversible decision**, -> which means that it will be affirmed once the "final comment period" of 10 -> days have passed, unless a team member places a "hold" on the decision (or cancels it). -> -> | Team member | State | -> | --- | --- | -> | @Alan | **merge** | -> | @Barbara | ~~hold~~ **merge** | -> | @Grace | | -> | @Niklaus | | - -Barbara's previous ~~hold~~ status links to her previous comment setting her -status to `hold`, and her current **merge** status links to her more recent -comment setting her status to `merge`. - -At this point, all the statuses are either empty or **merge**, and more than 10 -days have passed since the FCP started. Therefore, it completes immediately. - -## Authoring an RFC (illustration of `rustbot restart`) - -After some time, the proposal is completed and an RFC is proposed. This is a -reversible decision. Alan, as the liaison, proposes to merge the RFC with -`@rustbot merge`, and the decision making process proceeds as above. - -This time, Niklaus has a concern: - -> @rustbot hold -> -> I have not had time to read this yet! Give me a bit of time to write it up. - -After 7 days have passed, rustbot writes to him: - -> @Niklaus, I see you have placed a hold but 7 days have passed. Are you any -> closer to reaching a decision? (cc @Alan) - -This continues for a week or two while Alan and Niklaus play "email tag". In -the interim, Barbara decides she agrees with the RFC, so she uses `@rustbot -merge` as well. The status now looks like this: - -> Hello! @Alan has proposed to merge this PR. This is a **reversible -> decision**, which means that it will be affirmed once the "final comment -> period" of 10 days have passed, unless a team member places a "hold" on the decision (or cancels it). -> decision. -> -> | Team member | State | -> | --- | --- | -> | @Alan | **merge** | -> | @Barbara | **merge** | -> | @Grace | | -> | @Niklaus | **hold** | - -Eventually, Alan and Niklaus find a time to discuss, and Alan agrees that -Niklaus's concerns are valid, so he makes some major edits to the RFC. Given -that the RFC is completely different, he decides to restart the clock and -writes: - -> @rustbot restart - -This strikes through the state of all team members (setting their current -status to blank, while preserving the history) and begins the clock anew. -rustbot also pings the relevant team members: - -> Dear @rust-lang/team, @Alan has restarted the clock! - -The status now looks like this: - -> Hello! @Alan has proposed to merge this. This is a **reversible decision**, -> which means that it will be affirmed once the "final comment period" of 10 -> days have passed, unless a team member places a "hold" on the decision (or cancels it). -> -> | Team member | State | -> | --- | --- | -> | @Alan | **merge** | -> | @Barbara | ~~merge~~ | -> | @Grace | | -> | @Niklaus | ~~hold~~ | - -Barbara can use `@rustbot merge` to re-affirm her **merge** status, and Niklaus -can use `@rustbot merge` to set his own status to **merge** since he agrees -with the resolution of his concern. - -## Authoring an RFC continued (Overriding a concern) - -At this point, Grace has a concern, and explains that concern in detail: - -> @rustbot hold -> -> I've thought about this a lot, and I don't think we should do this. Now that -> I see the syntax used in practice, I feel like if we do this it'll have an -> adverse effect on the ecosystem... - -The status now looks like this: - -> Hello! @Alan has proposed to merge this. This is a **reversible decision**, -> which means that it will be affirmed once the "final comment period" of 10 -> days have passed, unless a team member places a "hold" on the decision (or cancels it). -> -> | Team member | State | -> | --- | --- | -> | @Alan | **merge** | -> | @Barbara | ~~merge~~ **merge** | -> | @Grace | **hold** | -> | @Niklaus | ~~hold~~ **merge** | - -Niklaus reads this message. He feels he understands the concern well, and -agrees that this point hasn't yet been considered: - -> @rustbot hold -> -> I agree. I think we should take more time to evaluate alternative syntaxes. -> What about... - -Over the course of a few subsequent meetings and side conversations, Grace and -other team members discuss the concern further; the initiative owner also -considers the concern, and raises it with others working on the initiative. - -The owner of the initiative updates the RFC to include a discussion of a couple -of alternative syntax proposals. The owner recommends a slightly modified -version of the originally proposed syntax, and outlines criteria that they feel -the syntax should meet in order to support the use case. - -Grace agrees that her concern has been understood, but does not agree with the -proposed syntax. Grace feels the new proposal is an improvement, but her -concern remains. - -Niklaus feels that the team has understood Grace's concern, and furthermore, -that the updated proposal addresses Grace's concern: - -> @rustbot merge -> -> I appreciate the potential impact this may have on the ecosystem. However, I -> feel that as now described in section XYZ of the RFC, the value of A -> outweighs the risk of B, and I think C mitigates the potential risk by... - -(Notice that while Niklaus feels that the team has understood Grace's concern, -he does not speak for the entire team or imply that his summary represents the -entire team. Niklaus is just withdrawing his own support for the concern.) - -At this point, the entire team other than Grace agrees that the proposal should -move forward: - -> Hello! @Alan has proposed to merge this. This is a **reversible decision**, -> which means that it will be affirmed once the "final comment period" of 10 -> days have passed, unless a team member places a "hold" on the decision (or cancels it). -> -> | Team member | State | -> | --- | --- | -> | @Alan | **merge** | -> | @Barbara | ~~merge~~ **merge** | -> | @Grace | **hold** | -> | @Niklaus | ~~hold~~ ~~merge~~ ~~hold~~ **merge**| - -(We'll assume, for this example, that Grace does not manage to convince anyone -else.) - -Grace takes some time, working with the RFC author, to add a dissent, including -a specific unresolved question. - -Grace then writes a comment containing `@rustbot dissent`. (If necessary, or if -Grace would prefer, another team member may issue `@rustbot @grace dissent` on -her behalf.) The status now looks like this: - -> Hello! @Alan has proposed to merge this. This is a **reversible decision**, -> which means that it will be affirmed once the "final comment period" of 10 -> days have passed, unless a team member places a "hold" on the decision (or cancels it). -> -> | Team member | State | -> | --- | --- | -> | @Alan | **merge** | -> | @Barbara | ~~merge~~ **merge** | -> | @Grace | ~~hold~~ **dissent** | -> | @Niklaus | ~~hold~~ ~~merge~~ ~~hold~~ **merge**| - -Since all statuses are now either **merge** or **dissent** rustbot also posts a -comment: - -> The final comment period has resolved, with a decision to **merge**. -> -> Note that this decision has dissents; please ensure these dissents have been -> recorded for subsequent consideration. - -## Stabilizing a feature - -The feature has been implemented and is now eligible for stabilization. Alan -writes a stabilization report and posts it, and then issues the command - -> @rustbot stabilize - -Rustbot recognizes that a "stabilization" decision is irreversible, so the -template is a bit different: - -> Hello! @Alan has proposed to stabilize this. This is a **irreversible -> decision**, which means that it will be affirmed once all members come to a -> consensus and the "final comment period" of 10 days has passed. -> -> | Team member | State | -> | --- | --- | -> | @Alan | stabilize | -> | @Barbara | | -> | @Grace | | -> | @Niklaus | | - -This time, Barbara, Grace, and Niklaus must all explicitly provide a status -before the decision can proceed. One by one, they join the PR. They must -individually set their state using one of the rustbot commands. - -Niklaus reads this and comments with `@rustbot merge`. But then, Niklaus uses -the feature and discovers a crucial flaw. He posts a comment: - -> @rustbot close -> -> After more testing, I believe this is not ready for stabilization. I have -> found that it doesn't work at all like the specification in the case of foo! -> This seems closely related to Grace's concern on the RFC; I think if we -> stabilize at this point we may indeed harm the ecosystem... - -Other team members test as well, and find that Niklaus is right. Alan changes -his status using `@rustbot close`, and Grace (with some relief) sets the same -status. - -Once everyone has changed their status, rustbot posts a comment: - -> The final comment period has resolved, with a decision to **close**. - -(Note: Since `close` is an inherently reversible status (a PR can always be -reopened), rustbot can observe that everyone has set a reversible status, and -will start treating the decision as reversible; this means the final comment -period can end even if Barbara hasn't responded yet.) - -This may not be the end of this feature's consideration, and the concern might -get resolved in many different ways. The initiative owner might need to do some -additional design work on how to solve the original use case and address the -concern; implementers may find a way to address the concern by improving the -implementation; or the team may change their mind. diff --git a/src/decision_process/reference.md b/src/decision_process/reference.md deleted file mode 100644 index 44e2391..0000000 --- a/src/decision_process/reference.md +++ /dev/null @@ -1,194 +0,0 @@ -# Decision-making process, detailed description - -- Entering a "decision period" can be done by having a team member tell rustbot - an initial status (`merge`, `stabilize`, or `close`; or, `reversible` or - `irreversible` with a custom identifier). - - All other team members have no initial status set. - - During a reversible decision period, if later commenters indicate the - decision is irreversible, the decision changes to irreversible. - - During an irreversible decision period, if all commenters change their - status to a reversible status (most commonly `close`), the decision becomes - reversible. - - Bot commands accept `mut`/`mutable`/`rev` as synonyms for `reversible`, and - `immut`/`immutable`/`irrev` as synonyms for `irreversible`. -- Once the "decision period" has begun, a clock of 10 days starts. The clock is - never paused unless an explicit `@rustbot restart` command is given. -- The `restart` command sets the decision period back to its initial state - (members' current statuses are also set back to blank, though the history of - their previous statuses is preserved as with any other status change). -- A decision is reached when the following conditions are met: - - At least 10 days have elapsed since the decision period began (or when it - was last `restart`ed). - - Everyone is set to the same status, or to `abstain`, or to `dissent` (with - at most one `dissent` status), or (for a reversible decision only) blank. -- Member may place a *hold* (raise a concern) at any phase of the process: - proposal, experimentation, testing, stabilization. Ideally, concerns should - be raised as early as possible. - - In general, one of the liaison's jobs is to anticipate concerns that may - arise and reach out proactively to the members of the team. If we find that - team members regularly need to place serious holds for similar reasons, - that may indicate we need to work harder at team calibration. -- "Holding" a decision is simple. If you have a potential concern that you - haven't had a chance to fully articulate yet, you get periodic pings. -- In order to proceed after a concern is raised, whether sustaining the concern - or overriding the concern, the team must understand the concern. This - understanding should be expressed in writing rather than just verbally. - Commonly, the owner of an initiative/proposal may incorporate the concern - into the proposal and address it there (whether via their own words or those - of a team member). - - Ideally, a concern is only considered "understood" if the objector agrees - it has been. If that is not possible, then everyone on the team other than - the objector must unanimously agree that there is no further understanding - to be gained. (In practice, this agreement is determined by whether anyone - on the team is willing to support the objection.) -- If the owner feels that the concern has been adequately addressed, they can - produce a write-up that describes the concern and request a poll of the team - members to see where everyone stands. - - Sustaining an objection requires one team member other than the objector. A - team member should sustain an objection if either they believe the - objection has been understood and they agree that it must be addressed, or - if they believe the objection has not been fully understood (whether they - personally agree with it or not). - - If everyone else agrees that the concern has been understood *and* that the - current design is sufficient, then the concern is *overridden*. - - Team members are encouraged to regularly sustain objections they don't - personally agree with, if they believe the objection has not yet been fully - understood; this is a normal and valuable part of the process. -- Whenever a concern is overridden, team members are encouraged to add a - **dissent** into the document to describe their concern and why they don't - agree with the decision. They (or another team member) should then set their - status to `dissent`. - -# Rustbot commands - -The following commands are accepted by rustbot. (Commands written below omit -the required `@` on rustbot to avoid invoking rustbot when quoting the -documentation.) A number of comments take one or more optional `@member` -arguments, denoted `@member*`; if supplied, the command is issued on behalf of -those member(s), instead of the person writing the command. (The `@` for each -member is required.) It is also permitted to write `@rust-lang/team` to select -all members of the team. rustbot will always link from each member's row in the -table to each comment changing their status. - -- `rustbot @member* reversible ident` or `rustbot @member* mutable ident` - (unambiguous prefixes such as `mut` or `rev` also work) - - If not in a decision period: begin a reversible ("mutable") decision, - proposing the outcome `ident`; all other members are set to a blank status. - - If in a decision period: set yourself to `ident`. (Decisions do not proceed - unless all members have the same status or `abstain`.) -- `rustbot @member* irreversible ident` or `rustbot @member* immutable ident` - (unambiguous prefixes such as `immut` or `irrev` also work) - - If not in a decision period: begin an irreversible ("immutable") decision, - proposing the outcome `ident`; all other members are set to a blank status. - - If in a decision period: set yourself to `ident`. If the decision was - previously considered reversible, change it to irreversible. The decision - now requires full team consensus. (Members may set a status of `abstain` on - the decision if they wish.) -- `rustbot @member* merge` - - Alias for `rustbot @member* reversible merge` - a reversible decision with - the proposed outcome `merge`. -- `rustbot @member* close` - - Alias for `rustbot @member* reversible close` - a reversible decision with - the proposed outcome `close`. -- `rustbot @member* stabilize` - - Alias for `rustbot @member* irreversible stabilize` - an irreversible - decision with the proposed outcome `stabilize`. -- `rustbot @member* abstain` - - If not in a decision period: error - - If in a decision period: set your status to `abstain`. This status does not - block a decision. -- `rustbot @member* hold` - - If not in a decision period: error - - If in a decision period: set your status to `hold` - - Every N days while a hold persists, rustbot will ping all members who - have status `hold` (and potentially other involved team members as well) -- `rustbot @member* dissent` - - Equivalent to `abstain`, except that it sets a status of `dissent`. This - status on one team member does not block a decision. A status of `dissent` - on two or more team members will block a decision. - - Note that `dissent` should not be set when first raising a concern, only - after attempts to resolve the concern have been unsuccessful. -- `rustbot restart` - - If not in a decision period: error - - If in a decision period: set all members other than the one issuing the - command to have a blank status. Preserve the last set status of the person - issuing the `restart`. - - Note: if the last set status of any team members were irreversible, the - decision will continue to be treated as irreversible until all such members - set an explicit status otherwise. -- `rustbot cancel` - - If not in a decision period: error - - If in a decision period: cancel the decision period. - - Note that if a subsequent decision is started in the same issue, rustbot - should link to the previous decision summary table. - -# Frequently asked questions - -## Why can members override other members positions? - -It's quite common to want to check boxes and similar on behalf of all the -people in a meeting. It's also annoying to have to restart a decision process -(e.g. closing and reopening with rfcbot) just to be able to close concerns on -someone else's behalf (e.g. people who have left the team, or people who raised -a concern on behalf of someone else not on the team, or similar). We can trust -each other on the team. If people abuse `rustbot` to disrupt the process, that -isn't a problem to be solved with tooling. - -## Do we want to require "all but N" people to affirm a decision, as `rfcbot` does? - -We opted to require 100% participation on irreversible decisions such as -stabilization, but not on very lightweight reversible decisions such as -starting an initiative. We believe that lang team members can be expected to at -least leave a comment (even if just `rustbot abstain`), but in the limit we -also have the option to set a status on another member's behalf. - -## Why does the timer start when the decision period *starts*, and not when a consensus is reached? - -The current `rfcbot` starts the 10 day FCP timer once a consensus is reached. -However, we have observed that, in practice, the "holdouts" on consensus are -typically the lang team members. Further, this seems to assume a "two-phased" -decision making model where folks outside the team are commenting only after -the lang team has reached a consensus. In practice, both decision-making and -commenting tend to be more fluid, and hence we would prefer not to have a long -delay after we reach consensus. - -## Why not use checkboxes? - -This process recognizes that sometimes, in the flow of conversation, the -decision to merge can transmute into a decision to close, or there may be -multiple potential outcomes. - -The presentation of statuses also makes it easy for `rustbot` to present the -history of status changes, with links to team members' messages. - -## Why is `close` always reversible? - -Because, well, it is! We can always re-open a PR or issue, after all. - -## What about "postpone"? - -Just write it in the comment for a `@rustbot close`. In practice, a "close" -does not preclude reopening later, and a "postpone" does not guarantee -reopening later. - -## Is "Don't force an irreversible decision?" absolute? - -No; it's a strongly held principle, but not an absolute one. Sometimes we may -have to make an irreversible decision, even in the face of dissent. However, we -should be *extraordinarily* careful when doing so, and in particular, we should -consider very carefully whether we could make a reversible decision, or find a -better consensus, or whether the consequences of *not* making the decision -outweigh the consequences of making it. This should be an extremely rare event. - -The previous decision-making process based on `rfcbot` allowed indefinitely -blocking concerns. This new process introduces a means of carefully resolving -such concerns, and a very careful means of proceeding *despite* such concerns -while ensuring those concerns are understood and recorded and considered. - -## What purpose does `restart` serve? - -Sometimes, a proposal has changed enough to warrant re-checking people's -positions, but has not changed enough to warrant closing it and starting the -process over. `restart` clears people's statuses to ensure that they have the -opportunity to re-confirm (or raise a hold or concern) before the decision -proceeds. diff --git a/src/fcp-decisions.md b/src/fcp-decisions.md new file mode 100644 index 0000000..00ef9bd --- /dev/null +++ b/src/fcp-decisions.md @@ -0,0 +1,76 @@ +# FCP decisions + +FCP decisions represent a significant commitment from the team. They require sign-off from team members and follow a formal process for resolving concerns. An FCP decision cannot be reversed without another FCP—the expectation is that reversal requires some change in circumstances: new experience, new information, or a reasoned change of mind. + +FCP decisions are used for stabilization, RFC approval, and other cases where we are making a promise to our users or taking a position we don't want to reverse lightly. + +## Definitions + +* **Lang team**: The [Language Design Team](https://github.com/rust-lang/team/blob/master/teams/lang.toml). +* **Lang team member**: A member of the lang team. Lang team members are the ones who approve the final decision. +* **Advisor**: A member of the [lang team advisors](https://github.com/rust-lang/team/blob/master/teams/lang-advisors.toml). Advisors can propose a decision and can raise concerns, but their approval is not required. +* **Decision document**: The RFC, issue text, or other document describing the decision being made. +* **Document author**: The person who authored the decision document. They ultimately decide what changes they wish to make in response to concerns. + +## The process + +FCP decisions use rfcbot. They always begin with a decision document authored by the document author, who can be anyone—they do not have to be a member of a Rust team. + +To start an FCP, a lang team member or advisor issues `@rfcbot fcp merge` (or `fcp close` for closing). This creates checkboxes. Once enough boxes have been checked (per rfcbot's standard rules), the decision enters final-comment-period. Assuming no concerns are raised, the decision is finalized once the FCP has expired. + +Before finalizing the decision, the team should engage with any **new** points raised during the FCP period, particularly from people not able to raise formal concerns. + +## Raising concerns + +Lang team members or advisors can raise a **formal concern** during the discussion process using `@rfcbot concern concern-name`. The decision cannot be finalized until the concern is resolved. + +### Expectations when raising a concern + +The person who raises a concern is expected to: + +* Write a constructive comment explaining the concern +* Make themselves available for discussion in a reasonable fashion +* Be prepared to write a summary document if requested + +## Resolving concerns + +There are two ways to resolve a concern: + +### 1. Withdrawn by the person who raised it + +If the person who raised the concern is satisfied—whether because of changes made or because they've decided not to block progress—they resolve the concern themselves with `@rfcbot resolve`. This is the preferred outcome. + +### 2. Resolution proposed + +If the concern is not withdrawn, someone (typically the document author) can propose a **resolution**. This is a more formal process that ensures concerns are genuinely engaged with. + +#### Creating a concern issue + +For concerns that require discussion (judgment calls rather than simple technical corrections), create a GitHub issue to track the concern. The issue can be on rust-lang/lang-team if there is no other suitable repository. + +*Note:* We recommend that rfcbot be updated to create these issues automatically. Until then, create them manually. + +#### The resolution template + +A resolution must include: + +1. **Summary of the concern**: Demonstrate that you understand the concern by summarizing its key points. The person who raised the concern should be able to confirm "yes, you understood me." + +2. **Proposed changes**: What changes (if any) are being made to the original proposal, and how they address specific points of the concern. This may be empty if no changes are being made. + +3. **Rationale**: Explain the reasoning behind the resolution. If any aspects of the concern are *not* being addressed, explain why (typically because they conflict with other goals or constraints). Referencing the [design axioms](./decision-making.md#design-axioms) and their ordering can be a useful way to document this rationale. + +#### FCP on the resolution + +Post the resolution to the concern issue and start an FCP with `@rfcbot fcp merge`. + +**Important:** The person who raised the original concern cannot block this FCP. They can (and should) comment on whether the summary accurately represents their concern, but their only path to blocking is convincing another team member that the resolution is inadequate. + +Other team members can raise new concerns on the resolution, or request a design meeting for deeper discussion. + +#### After the resolution + +If the resolution FCP completes successfully: + +* If the resolution included changes to the original proposal, **restart the original FCP** to give people a chance to review the updated proposal. +* If no changes were made, the original FCP can continue. diff --git a/src/how_to/experiment.md b/src/how_to/experiment.md index c2839b9..3e03551 100644 --- a/src/how_to/experiment.md +++ b/src/how_to/experiment.md @@ -11,11 +11,11 @@ If you are an experienced Rust contributor who would like to start an experiment * Write-up a description of the problem you are trying to solve and the general shape of the solution you want to work on. Discuss it on Zulip or elsewhere to find a **lang-team liaison**: * The liaison is the connection to the lang-team. They can check in with you from time to time to see how the work is going and relay those updates to the lang-team (of course, you're always welcome to join meetings yourself too!). They can also help to discuss problems that arise. * Once you've found a liaison, open a PR adding a new feature gate to the compiler and create an associated tracking issue. - * The PR and tracking issue should include a write-up documenting the motivation and outline of what they are trying to achieve. + * The PR and tracking issue should include a write-up documenting the motivation and outline of what they are trying to achieve. * The feature gate should be marked as 'experimental', so that users get warnings if they try to use it. This flag has to stay until an RFC is accepted, even if the implementation is in good shape. -* The lang-team liaison will "second" the PR, starting an FCP. Once the FCP completes, the PR can land and implementation work begins (always gated under the new feature gate). +* The lang-team liaison will [nominate](./nominate.md) the PR for discussion at a triage meeting. This is a [champion decision](../champion-decisions.md)—if no one requests FCP escalation, the experiment can proceed. * **Approving a new feature gate does not imply support for the feature.** It implies only that the lang team thinks it is worth doing the experiment to see what results. - * Note to lang team members: If you have concerns about the feasibility or wisdom of the feature, the right course of action is usually to allow experimentation to continue, but ensure that your concerns are noted on the tracking issue. This allows the experimentors to try and gather data and address your concern. + * Note to lang team members: If you have concerns about the feasibility or wisdom of the feature, the right course of action is usually to allow experimentation to continue, but ensure that your concerns are noted on the tracking issue. This allows the experimenters to try and gather data and address your concern. * When you feel the design is ready, you write an RFC as normal with your proposal. The goal of the experimentation period is simply to gain experience and information so that a better RFC can be authored. [members]: https://www.rust-lang.org/governance/teams/lang diff --git a/src/how_to/propose.md b/src/how_to/propose.md index b15d8e9..7ec1177 100644 --- a/src/how_to/propose.md +++ b/src/how_to/propose.md @@ -84,14 +84,13 @@ click NeedToExperiment "./experiment.html" "Read about experimental feature gate ## Frequently asked questions -### What do the labels "lang-team second" and "lang-team consensus" mean? +### What's the difference between "champion decisions" and "FCP decisions"? -These refer to our [decision process](./decision_process.md): +These refer to our [decision process](../decision-making.md): -* A **second** means that some [lang team member] must liaison the idea, but it doesn't require full checkboxes. Instead, the idea goes immediately into "final comment period" (which lasts for 10 days), giving other lang team members a chance to comment on it and raise concerns. We use seconding for *reversible decisions* that don't commit the language to anything in particular. -* A **consensus** means that every [lang team member] must check their box and actively approve. +* A **[champion decision](../champion-decisions.md)** means a lang team member or advisor is championing the idea. It does not represent team consensus—only the champion's point of view. The champion nominates the issue for a triage meeting; if no one requests FCP escalation, the champion can proceed. We use champion decisions for experiments and other cases where we want to move quickly. -In both cases, we currently handle consensus with rfcbot (`@rfcbot fcp`). For a second, however, the lang team member who initiatives FCP can go ahead and check the boxes of other lang-team members, they can raise concerns if needed. This is a temporary measure until we have first-class support for seconding. +* An **[FCP decision](../fcp-decisions.md)** represents a significant commitment from the team. It requires sign-off from team members via rfcbot and follows a formal process for resolving concerns. We use FCP decisions for stabilization, RFC approval, and other cases where we are making a promise to our users. [lang team member]: https://www.rust-lang.org/governance/teams/lang diff --git a/src/how_to/stabilize.md b/src/how_to/stabilize.md index 3f13de9..8b773f3 100644 --- a/src/how_to/stabilize.md +++ b/src/how_to/stabilize.md @@ -13,7 +13,7 @@ The final step in the [language-change process](./propose.md) is to **stabilize* * An open PR editing the reference to describe the change is required. (You don't personally have to author it, but there needs to be an open PR, and ideally one that has been edited and is approved modulo actual stabilization by one of the repo maintainers.) * If the feature affects the type system, you should nominate for @rust-lang/types to check for their approval. * If the feature adds new syntax, you should should nominate for the style team to get their approval. -* The lang team will read the report and eventually move to FCP. Per our [decision process](../decision_process.md), full consensus is required, as this is an irreversible change. +* The lang team will read the report and eventually move to FCP. Per our [decision process](../decision-making.md), this is an [FCP decision](../fcp-decisions.md), as stabilization is a significant commitment to our users. See also the rustc-dev-guide's [stabilization guide][sg]. From db1e02e3f39f99d897fe0f8904104eae03663b74 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Dec 2025 14:58:11 -0500 Subject: [PATCH 2/3] Update src/fcp-decisions.md Co-authored-by: Travis Cross --- src/fcp-decisions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fcp-decisions.md b/src/fcp-decisions.md index 00ef9bd..5567c16 100644 --- a/src/fcp-decisions.md +++ b/src/fcp-decisions.md @@ -46,7 +46,7 @@ If the concern is not withdrawn, someone (typically the document author) can pro #### Creating a concern issue -For concerns that require discussion (judgment calls rather than simple technical corrections), create a GitHub issue to track the concern. The issue can be on rust-lang/lang-team if there is no other suitable repository. +For concerns that require discussion (judgment calls rather than simple technical corrections), create a GitHub issue to track the concern. In most cases --- when the concern involves a change to the language --- the issue will be filed in `rust-lang/rust`. Otherwise, if there is no other suitable repository, the issue can be filed on `rust-lang/lang-team`. *Note:* We recommend that rfcbot be updated to create these issues automatically. Until then, create them manually. From 3fceeea77a2da1aaa657888e0c7e63bbd889d1e1 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Dec 2025 20:22:25 -0500 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Travis Cross --- src/fcp-decisions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fcp-decisions.md b/src/fcp-decisions.md index 5567c16..e5f01ef 100644 --- a/src/fcp-decisions.md +++ b/src/fcp-decisions.md @@ -42,7 +42,7 @@ If the person who raised the concern is satisfied—whether because of changes m ### 2. Resolution proposed -If the concern is not withdrawn, someone (typically the document author) can propose a **resolution**. This is a more formal process that ensures concerns are genuinely engaged with. +If the concern is not withdrawn, someone (e.g. the document author) can propose a **resolution**. This is a more formal process that ensures concerns are genuinely engaged with. #### Creating a concern issue