From a7f3a683afd6b55ad85270db58550628dc1820cd Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 28 Jul 2021 20:52:42 -0700 Subject: [PATCH 01/10] Add the decision-making process from the 2021-07-21 design meeting All content from the design document. Minor fixes to formatting and organization, and minor wording corrections, but no changes to the actual process. --- src/SUMMARY.md | 3 + src/decision_process.md | 51 +++++ src/decision_process/examples.md | 297 ++++++++++++++++++++++++++++++ src/decision_process/reference.md | 167 +++++++++++++++++ 4 files changed, 518 insertions(+) create mode 100644 src/decision_process.md create mode 100644 src/decision_process/examples.md create mode 100644 src/decision_process/reference.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index cdea982..00f0d32 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -15,6 +15,9 @@ - [Stabilized](./initiatives/process/stages/stabilized.md) - [Inactive](./initiatives/process/stages/inactive.md) - [FAQ](./initiatives/faq.md) +- [Decision process and principles](./decision_process.md) + - [Decision process examples](./decision_process/examples.md) + - [Decision process reference](./decision_process/reference.md) - [Lang team "how to" guide](./how_to.md) - [Nominate an issue](./how_to/nominate.md) - [Propose an initiative](./how_to/propose.md) diff --git a/src/decision_process.md b/src/decision_process.md new file mode 100644 index 0000000..5908ecb --- /dev/null +++ b/src/decision_process.md @@ -0,0 +1,51 @@ +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 as many decisions + reversible as possible. Even when a decision seems irreversible (e.g., + stabilization), we should strive to find a subset that still allows + addressing the use case, or a subset that will support evaluation and + data-gathering to enable making the decision in the future. If that's not + 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 new file mode 100644 index 0000000..1f94f1b --- /dev/null +++ b/src/decision_process/examples.md @@ -0,0 +1,297 @@ +# 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: + +> 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 pauses or suspends the decision. +> +> | Team member | State | +> | --- | --- | +> | @Alan | **merge** | +> | @Barbara | **hold** | +> | @Grace | | +> | @Niklaus | | + +Alan is currently busy at work, though, so by 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 pauses or suspends the decision. +> +> | 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, **abstain**, 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 her: + +> @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 pauses or suspends the +> 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 clears the state of all team members (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 pauses or suspends the decision. +> +> | 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 pauses or suspends the decision. +> +> | 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 we've now mitigated the potential risk by... + +(Notice that while Niklaus feels that the team has understood Grace's concern, +he does not use "We" in his response, and does not 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 pauses or suspends the decision. +> +> | 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 pauses or suspends the decision. +> +> | 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 mutable status (a PR can always be +reopened), rustbot can observe that everyone has set a mutable status, and will +start treating the decision as mutable; 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 new file mode 100644 index 0000000..a8396c2 --- /dev/null +++ b/src/decision_process/reference.md @@ -0,0 +1,167 @@ +# 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, `mutable` or + `immutable` with a custom identifier). + - All other team members have no initial status set. + - During a "mutable" (reversible) decision period, if later commenters + indicate the decision is immutable, the decision changes to immutable. + - During an "immutable" (irreversible) decision period, if all commenters + change their status to a mutable status (most commonly `close`), the + decision becomes mutable. +- 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 decisions are also changed back to blank, as appropriate, though the + history of their previous statuses is preserved). +- 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 mutable 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. 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 they made that changed +their status. + +- `rustbot @member* mutable ident` or `rustbot @member* mut ident` or + `rustbot @member* reversible ident` + - 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* immutable ident` or `rustbot @member* irreversible ident` + - 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 mutable, change it to immutable. 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* mutable merge` - a mutable decision with the + proposed outcome `merge`. +- `rustbot @member* close` + - Alias for `rustbot @member* mutable close` - a mutable decision with the + proposed outcome `close`. +- `rustbot @member* stabilize` + - Alias for `rustbot @member* immutable stabilize` - an immutable 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. +- `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 immutable, the + decision will continue to be treated as immutable 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 immutable (irreversible) decisions +such as stabilization, but not on very lightweight mutable (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. From 551e0c3be300a4eebe5d51c53090803c3e00f097 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 28 Jul 2021 21:06:05 -0700 Subject: [PATCH 02/10] Add a couple more FAQs based on discussions from the design meeting --- src/decision_process/reference.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/decision_process/reference.md b/src/decision_process/reference.md index a8396c2..cecb4d6 100644 --- a/src/decision_process/reference.md +++ b/src/decision_process/reference.md @@ -165,3 +165,25 @@ Because, well, it is! We can always re-open a PR or issue, after all. 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. From cedcd72edcf63eb7445b75550ad5dce21196fcc3 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 28 Jul 2021 21:06:22 -0700 Subject: [PATCH 03/10] Add clarification on when to use `rustbot dissent` --- src/decision_process/reference.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/decision_process/reference.md b/src/decision_process/reference.md index cecb4d6..99f6859 100644 --- a/src/decision_process/reference.md +++ b/src/decision_process/reference.md @@ -102,6 +102,8 @@ their status. - 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 From 76c383d73383dc1041b2d70d0e5636bdba85e963 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 13 Oct 2021 00:00:45 +0200 Subject: [PATCH 04/10] Clarify proposed rustbot text Co-authored-by: Felix S Klock II --- src/decision_process/examples.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/decision_process/examples.md b/src/decision_process/examples.md index 1f94f1b..b850793 100644 --- a/src/decision_process/examples.md +++ b/src/decision_process/examples.md @@ -42,7 +42,7 @@ At this point, rustbot updates the state: > 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 pauses or suspends the decision. +> days have passed, unless a team member places a "hold" on the decision (or cancels it). > > | Team member | State | > | --- | --- | @@ -62,7 +62,7 @@ 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 pauses or suspends the decision. +> days have passed, unless a team member places a "hold" on the decision (or cancels it). > > | Team member | State | > | --- | --- | @@ -102,7 +102,7 @@ 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 pauses or suspends the +> period" of 10 days have passed, unless a team member places a "hold" on the decision (or cancels it). > decision. > > | Team member | State | @@ -128,7 +128,7 @@ 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 pauses or suspends the decision. +> days have passed, unless a team member places a "hold" on the decision (or cancels it). > > | Team member | State | > | --- | --- | @@ -155,7 +155,7 @@ 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 pauses or suspends the decision. +> days have passed, unless a team member places a "hold" on the decision (or cancels it). > > | Team member | State | > | --- | --- | @@ -204,7 +204,7 @@ 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 pauses or suspends the decision. +> days have passed, unless a team member places a "hold" on the decision (or cancels it). > > | Team member | State | > | --- | --- | @@ -225,7 +225,7 @@ 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 pauses or suspends the decision. +> days have passed, unless a team member places a "hold" on the decision (or cancels it). > > | Team member | State | > | --- | --- | From 91fb06e5252d4a8a5567402bec503dcb79a415cf Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 13 Oct 2021 00:03:57 +0200 Subject: [PATCH 05/10] Clarifications to examples Co-authored-by: Felix S Klock II --- src/decision_process/examples.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/decision_process/examples.md b/src/decision_process/examples.md index b850793..b643a2a 100644 --- a/src/decision_process/examples.md +++ b/src/decision_process/examples.md @@ -38,7 +38,8 @@ proposal has overlooked an important consideration. She writes a comment: > > Did you consider reversing the polarity? Or the impact on the flux capacitor? -At this point, rustbot updates the state: +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 @@ -91,7 +92,7 @@ This time, Niklaus has a concern: > > 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 her: +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) From f62b1d2d45fbc849416727b77854e25884f20c93 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 14 Oct 2021 15:49:20 +0200 Subject: [PATCH 06/10] Improve example language Generalize to "does not speak for the entire team" rather than tabooing the word "we". But also, rephrase to use "I think" phrasing instead of "we have". --- src/decision_process/examples.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/decision_process/examples.md b/src/decision_process/examples.md index b643a2a..5ae88a7 100644 --- a/src/decision_process/examples.md +++ b/src/decision_process/examples.md @@ -193,12 +193,11 @@ that the updated proposal addresses Grace's concern: > > 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 we've now mitigated the potential risk by... +> 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 use "We" in his response, and does not imply that his summary -represents the entire team. Niklaus is just withdrawing his own support for the -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: From ba43dd081395565d2854533f4259dd8de0cdb0f7 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 14 Oct 2021 15:55:39 +0200 Subject: [PATCH 07/10] Simplify example by removing mention of "abstain" (since nobody abstained) --- src/decision_process/examples.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/decision_process/examples.md b/src/decision_process/examples.md index 5ae88a7..ff7ffab 100644 --- a/src/decision_process/examples.md +++ b/src/decision_process/examples.md @@ -76,9 +76,8 @@ 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, **abstain**, or **merge**, -and more than 10 days have passed since the FCP started. Therefore, it -completes immediately. +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`) From 4832402c6adbd27c0c83339d58d6c6db624b68f9 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 14 Oct 2021 16:03:08 +0200 Subject: [PATCH 08/10] Clarify how restart affects statuses --- src/decision_process/examples.md | 5 +++-- src/decision_process/reference.md | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/decision_process/examples.md b/src/decision_process/examples.md index ff7ffab..0994e06 100644 --- a/src/decision_process/examples.md +++ b/src/decision_process/examples.md @@ -119,8 +119,9 @@ writes: > @rustbot restart -This clears the state of all team members (preserving the history) and begins -the clock anew. rustbot also pings the relevant team members: +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! diff --git a/src/decision_process/reference.md b/src/decision_process/reference.md index 99f6859..6e2e41b 100644 --- a/src/decision_process/reference.md +++ b/src/decision_process/reference.md @@ -12,8 +12,8 @@ - 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 decisions are also changed back to blank, as appropriate, though the - history of their previous statuses is preserved). + (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). From 3fec059579547940a63d5cfaf2b8b4285f0903c7 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 30 Oct 2021 14:25:41 +0200 Subject: [PATCH 09/10] Clarify "Don't force an irreversible decision" to focus on dissent/concerns Try to make it clearer that we can and do still make irreversible decisions. Focus on how we handle dissent in such cases, and what we can do in those circumstances. --- src/decision_process.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/decision_process.md b/src/decision_process.md index 5908ecb..664e3cf 100644 --- a/src/decision_process.md +++ b/src/decision_process.md @@ -20,14 +20,16 @@ could apply to any Rust governance team, not just the language team. [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 as many decisions - reversible as possible. Even when a decision seems irreversible (e.g., - stabilization), we should strive to find a subset that still allows - addressing the use case, or a subset that will support evaluation and - data-gathering to enable making the decision in the future. If that's not - 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. +- **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 From 7e0eb42dfcef23a3a1098f2d33f7720592c2232a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 30 Oct 2021 23:16:30 +0200 Subject: [PATCH 10/10] Rework reference and examples to favor "reversible"/"irreversible" Keep "mutable"/"immutable" (and unambiguous prefixes) as synonyms, but favor the more self-documenting terms in documentation. --- src/decision_process/examples.md | 8 ++-- src/decision_process/reference.md | 75 ++++++++++++++++--------------- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/src/decision_process/examples.md b/src/decision_process/examples.md index 0994e06..6d0ef97 100644 --- a/src/decision_process/examples.md +++ b/src/decision_process/examples.md @@ -285,10 +285,10 @@ 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 mutable status (a PR can always be -reopened), rustbot can observe that everyone has set a mutable status, and will -start treating the decision as mutable; this means the final comment period can -end even if Barbara hasn't responded yet.) +(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 diff --git a/src/decision_process/reference.md b/src/decision_process/reference.md index 6e2e41b..44e2391 100644 --- a/src/decision_process/reference.md +++ b/src/decision_process/reference.md @@ -1,14 +1,16 @@ # 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, `mutable` or - `immutable` with a custom identifier). + 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 "mutable" (reversible) decision period, if later commenters - indicate the decision is immutable, the decision changes to immutable. - - During an "immutable" (irreversible) decision period, if all commenters - change their status to a mutable status (most commonly `close`), the - decision becomes mutable. + - 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 @@ -18,7 +20,7 @@ - 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 mutable decision only) blank. + 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. @@ -59,36 +61,38 @@ # Rustbot commands -The following commands are accepted by rustbot. 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 they made that changed -their status. - -- `rustbot @member* mutable ident` or `rustbot @member* mut ident` or - `rustbot @member* reversible ident` +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* immutable ident` or `rustbot @member* irreversible ident` +- `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 mutable, change it to immutable. The decision now - requires full team consensus. (Members may set a status of `abstain` on the - decision if they wish.) + 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* mutable merge` - a mutable decision with the - proposed outcome `merge`. + - Alias for `rustbot @member* reversible merge` - a reversible decision with + the proposed outcome `merge`. - `rustbot @member* close` - - Alias for `rustbot @member* mutable close` - a mutable decision with the - proposed outcome `close`. + - Alias for `rustbot @member* reversible close` - a reversible decision with + the proposed outcome `close`. - `rustbot @member* stabilize` - - Alias for `rustbot @member* immutable stabilize` - an immutable decision - with the proposed outcome `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 @@ -109,8 +113,8 @@ their status. - 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 immutable, the - decision will continue to be treated as immutable until all such members + - 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 @@ -132,12 +136,11 @@ 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 immutable (irreversible) decisions -such as stabilization, but not on very lightweight mutable (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. +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?