From a85a7c346c0a349dd972da929978fda540b0f50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 15:17:22 +0100 Subject: [PATCH 01/17] start rfc for unstable features --- rfcs/unstable_features.md | 65 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 rfcs/unstable_features.md diff --git a/rfcs/unstable_features.md b/rfcs/unstable_features.md new file mode 100644 index 00000000..5d6500b7 --- /dev/null +++ b/rfcs/unstable_features.md @@ -0,0 +1,65 @@ +# Feature Name: `unstable_features` + +## Summary + +Accepting PRs for new features that may not have reach the high bar we set for Bevy, and disable their changes with a feature gate. + +## Motivation + +Some features would benefit from iterative work in Bevy, but that may be hard to do when a PRs need a high level of quality to be merged in. + +In this RFC, "feature" means the new feature or change under development, and "feature gate" the conditional compilation flag. "unstable" means a feature that is subject to change, not something that will break Bevy. + +## User-facing explanation + +So you want to contribute a new feature to Bevy! You have a few paths available to you, depending on the scope of the feature: +- A small feature with a clear implementation? Go ahead and open that PR! +- A large feature with an open design space that could use some discution about how to implement it? A RFC would be good. +- Something in between that would benefit from iterative work? Here come the unstable feature workflow for you! + +You will need to open a tracking issue to explain the new feature you want to add. If it looks good, you'll be ready to open that PR with a feature gate for your changes! + +## Implementation strategy + +The new workflow for this kind of feature would be: +- Submit an issue explaining the feature you want to add under a feature gate. This will be the tracking issue for stabilization once approved. This issue gets a new label `S-Stabilization`. +- If approved, submit a PR with the new feature and the feature gate +- This PR can be merged by someone with the merge rights on the related part of Bevy as soon as it's `S-Ready-For-Final-Review`, without an approval by the main Bevy maintainers. +- Subsequent PRs on the feature must be linked to the tracking issue and follow the same process. +- Once the feature is finished, enter the stabilization period. Open a PR that will remove the feature gate. This PR need to be approved by the main Bevy maintainers. + +An existing PR can be retroffited in this process on the suggestion of Bevy community members, and if the PR author agrees. + +The RFCs and the unstable features are closely related. An RFC can be implemented as an unstable feature to help resolve issues that need more experimentation. An unstable feature could require an RFC to reach stabilization. + +Each PR will still need to be approved by Bevy community members, and would still need to have the same level of quality as other PRs merged. + +The PRs for the initial feature, various changes during its finalization and for the stabilization can be opened by different persons. + +The feature gate should not be exposed on the main `bevy` crate, but only on the subcrates where it is relevant. It can be enabled as a user by adding dependencies directly on the subcrates and enabling the feature. + +## Drawbacks + +This will increase complexity in Bevy code. + +It will also increase complexity of a contribution that would like to use this process, but it is opt in and not mandatory. Think of it as a fast track for unstable features. + +## Rationale and alternatives + +- Improve the process to get new features in Bevy that would benefir from iterative work. +- Alternatives: + - Continue as it is now, with semi large PRs that bitrot and RFCs that don't often move forward + - Work harder to implement a new feature as a third party crate (this is not always possible) + - Fork Bevy to merge unnaproved PRs and check how they work / interact + + +## Prior art + +[The Rust process](https://rustc-dev-guide.rust-lang.org/implementing_new_features.html) + +## Unresolved questions + +- Do we want to limit the number of feature gates in Bevy to reduce complexity? + - this could help control the increased complexity in Bevy +- Do we want to limit the maximum age of a unstabilized feature? + - this could help control the increased complexity in Bevy, and requires being ready to cut a feature off if it's not getting the use / stabilization expected From b532dc5b92f2bb853a96677e6a3922adbb824d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 15:24:32 +0100 Subject: [PATCH 02/17] add pr number --- rfcs/{unstable_features.md => 52-unstable_features.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rfcs/{unstable_features.md => 52-unstable_features.md} (100%) diff --git a/rfcs/unstable_features.md b/rfcs/52-unstable_features.md similarity index 100% rename from rfcs/unstable_features.md rename to rfcs/52-unstable_features.md From 2eaad9adf0d771071e726ab9e9e6d60836b30c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 16:01:33 +0100 Subject: [PATCH 03/17] Update rfcs/52-unstable_features.md Co-authored-by: James Liu --- rfcs/52-unstable_features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index 5d6500b7..23894609 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -14,7 +14,7 @@ In this RFC, "feature" means the new feature or change under development, and "f So you want to contribute a new feature to Bevy! You have a few paths available to you, depending on the scope of the feature: - A small feature with a clear implementation? Go ahead and open that PR! -- A large feature with an open design space that could use some discution about how to implement it? A RFC would be good. +- A large feature with an open design space that could use some discussion about how to implement it? A RFC would be good. - Something in between that would benefit from iterative work? Here come the unstable feature workflow for you! You will need to open a tracking issue to explain the new feature you want to add. If it looks good, you'll be ready to open that PR with a feature gate for your changes! From 59342dbe1ff672b54fc34f54c88d898c678668da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 16:18:31 +0100 Subject: [PATCH 04/17] propose a convention for feature gate name --- rfcs/52-unstable_features.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index 23894609..c98239bb 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -27,6 +27,8 @@ The new workflow for this kind of feature would be: - This PR can be merged by someone with the merge rights on the related part of Bevy as soon as it's `S-Ready-For-Final-Review`, without an approval by the main Bevy maintainers. - Subsequent PRs on the feature must be linked to the tracking issue and follow the same process. - Once the feature is finished, enter the stabilization period. Open a PR that will remove the feature gate. This PR need to be approved by the main Bevy maintainers. +The feature gate should follow the following convention for its name: `unstable-<#tracking-issue-number>-feature-name`. + An existing PR can be retroffited in this process on the suggestion of Bevy community members, and if the PR author agrees. From 2f37437b788b22e8cc76e67b425ea6522ff34680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 16:18:42 +0100 Subject: [PATCH 05/17] small nits --- rfcs/52-unstable_features.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index c98239bb..00af0b91 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -26,7 +26,8 @@ The new workflow for this kind of feature would be: - If approved, submit a PR with the new feature and the feature gate - This PR can be merged by someone with the merge rights on the related part of Bevy as soon as it's `S-Ready-For-Final-Review`, without an approval by the main Bevy maintainers. - Subsequent PRs on the feature must be linked to the tracking issue and follow the same process. -- Once the feature is finished, enter the stabilization period. Open a PR that will remove the feature gate. This PR need to be approved by the main Bevy maintainers. +- Once the feature is finished, enter the stabilization period. Open a PR that will remove the feature gate. This PR needs to be approved by the main Bevy maintainers. + The feature gate should follow the following convention for its name: `unstable-<#tracking-issue-number>-feature-name`. @@ -38,7 +39,7 @@ Each PR will still need to be approved by Bevy community members, and would stil The PRs for the initial feature, various changes during its finalization and for the stabilization can be opened by different persons. -The feature gate should not be exposed on the main `bevy` crate, but only on the subcrates where it is relevant. It can be enabled as a user by adding dependencies directly on the subcrates and enabling the feature. +The feature gate should not be exposed on the main `bevy` crate, but only on the subcrates where it is relevant. It can be enabled as a user by adding dependencies directly on the subcrates and enabling the feature. The tracking issue should list the subcrates impacted. ## Drawbacks @@ -61,7 +62,7 @@ It will also increase complexity of a contribution that would like to use this p ## Unresolved questions -- Do we want to limit the number of feature gates in Bevy to reduce complexity? +- Do we want to limit the number of feature gates in Bevy? - this could help control the increased complexity in Bevy - Do we want to limit the maximum age of a unstabilized feature? - this could help control the increased complexity in Bevy, and requires being ready to cut a feature off if it's not getting the use / stabilization expected From 19574c1f950e2d558d2be8cc9eed74a0ffdd579a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 17:08:38 +0100 Subject: [PATCH 06/17] nit on name convention --- rfcs/52-unstable_features.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index 00af0b91..aa659551 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -28,8 +28,7 @@ The new workflow for this kind of feature would be: - Subsequent PRs on the feature must be linked to the tracking issue and follow the same process. - Once the feature is finished, enter the stabilization period. Open a PR that will remove the feature gate. This PR needs to be approved by the main Bevy maintainers. -The feature gate should follow the following convention for its name: `unstable-<#tracking-issue-number>-feature-name`. - +The feature gate should follow the following convention for its name: `unstable-<#tracking-issue-number>-`. An existing PR can be retroffited in this process on the suggestion of Bevy community members, and if the PR author agrees. From d0c0d4396a9da5fbb30fcce29b8d6a62c5ffeeb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 17:08:57 +0100 Subject: [PATCH 07/17] add details on RFC <-> unstable feature --- rfcs/52-unstable_features.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index aa659551..28df175c 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -32,7 +32,18 @@ The feature gate should follow the following convention for its name: `unstable- An existing PR can be retroffited in this process on the suggestion of Bevy community members, and if the PR author agrees. -The RFCs and the unstable features are closely related. An RFC can be implemented as an unstable feature to help resolve issues that need more experimentation. An unstable feature could require an RFC to reach stabilization. +The RFCs and the unstable features are closely related. An RFC can be implemented as an unstable feature to help resolve issues that need more experimentation, or split a large implementation. An unstable feature could require an RFC to reach stabilization. For example: +- RFC to Unstable Feature + - Open a RFC, reaching a design + - Implement part of the RFC as an unstable feature + - Feedback into the RFC with the gained knowledge of implementation and usage +- Unstable Feature to RFC + - Open an tracking issue, start implementing it + - Part of the unstable feature is larger than expected with several deisgn possibilities + - Open a RFC, reaching a decision on the design + - Implement the RFC for the unstable feature + + Each PR will still need to be approved by Bevy community members, and would still need to have the same level of quality as other PRs merged. From 2f05faeea7aed5ce31a52f582412af904c0098b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 17:09:05 +0100 Subject: [PATCH 08/17] add a potential drawback --- rfcs/52-unstable_features.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index 28df175c..e52c6533 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -57,6 +57,8 @@ This will increase complexity in Bevy code. It will also increase complexity of a contribution that would like to use this process, but it is opt in and not mandatory. Think of it as a fast track for unstable features. +Stabilizing a feature could be harder, as it would mean a review across several PRs, and may not easily work with GitHub review UI. But the stabilization review should be easier than a large PR as there would be actual usage feedback. + ## Rationale and alternatives - Improve the process to get new features in Bevy that would benefir from iterative work. From 1de8d9171f5cc532c43e97521e0fe4cb8919e356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 5 Mar 2022 17:09:19 +0100 Subject: [PATCH 09/17] propose organisation and discovery through github project --- rfcs/52-unstable_features.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index e52c6533..2d69cfa7 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -51,6 +51,8 @@ The PRs for the initial feature, various changes during its finalization and for The feature gate should not be exposed on the main `bevy` crate, but only on the subcrates where it is relevant. It can be enabled as a user by adding dependencies directly on the subcrates and enabling the feature. The tracking issue should list the subcrates impacted. +For organization and discovery, a GitHub project can be used to track the stabilization issues. + ## Drawbacks This will increase complexity in Bevy code. From 53f3d1fa2b495eccb4069c81f7aa807122b69ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sun, 6 Mar 2022 03:33:38 +0100 Subject: [PATCH 10/17] add drawback on potential breakage of an unstable feature from other PR --- rfcs/52-unstable_features.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index 2d69cfa7..98571e8f 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -61,6 +61,8 @@ It will also increase complexity of a contribution that would like to use this p Stabilizing a feature could be harder, as it would mean a review across several PRs, and may not easily work with GitHub review UI. But the stabilization review should be easier than a large PR as there would be actual usage feedback. +An unstable feature accepted in Bevy may stop working due to the merge of another PR. This is the same burden as keeping a PR up to date with Bevy while it's waiting to be merged, but more visible. On the positive side, it would be easier for someone else to jump in and fix it. + ## Rationale and alternatives - Improve the process to get new features in Bevy that would benefir from iterative work. From 4cc678495cebdc149b0645cce56ae98086571ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sun, 6 Mar 2022 03:33:45 +0100 Subject: [PATCH 11/17] typo --- rfcs/52-unstable_features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index 98571e8f..6eac15a4 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -65,7 +65,7 @@ An unstable feature accepted in Bevy may stop working due to the merge of anothe ## Rationale and alternatives -- Improve the process to get new features in Bevy that would benefir from iterative work. +- Improve the process to get new features in Bevy that would benefit from iterative work. - Alternatives: - Continue as it is now, with semi large PRs that bitrot and RFCs that don't often move forward - Work harder to implement a new feature as a third party crate (this is not always possible) From 76b7e3882c05f6c3acf1e2924a25d3d2177b5016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Mon, 7 Mar 2022 13:06:26 +0100 Subject: [PATCH 12/17] typos and reformulations Co-Authored-By: Alice Cecile --- rfcs/52-unstable_features.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index 6eac15a4..f1424208 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -2,11 +2,11 @@ ## Summary -Accepting PRs for new features that may not have reach the high bar we set for Bevy, and disable their changes with a feature gate. +Experimental new features are merged into main behind a feature gate before stabilization. ## Motivation -Some features would benefit from iterative work in Bevy, but that may be hard to do when a PRs need a high level of quality to be merged in. +Some features would benefit from iterative work in Bevy, but that may be hard to do when a PRs need a high level of quality to be merged in. In this RFC, "feature" means the new feature or change under development, and "feature gate" the conditional compilation flag. "unstable" means a feature that is subject to change, not something that will break Bevy. @@ -39,12 +39,11 @@ The RFCs and the unstable features are closely related. An RFC can be implemente - Feedback into the RFC with the gained knowledge of implementation and usage - Unstable Feature to RFC - Open an tracking issue, start implementing it - - Part of the unstable feature is larger than expected with several deisgn possibilities + - Part of the unstable feature is larger than expected with several design possibilities - Open a RFC, reaching a decision on the design - Implement the RFC for the unstable feature - Each PR will still need to be approved by Bevy community members, and would still need to have the same level of quality as other PRs merged. The PRs for the initial feature, various changes during its finalization and for the stabilization can be opened by different persons. @@ -57,7 +56,7 @@ For organization and discovery, a GitHub project can be used to track the stabil This will increase complexity in Bevy code. -It will also increase complexity of a contribution that would like to use this process, but it is opt in and not mandatory. Think of it as a fast track for unstable features. +It will also increase complexity of a contribution that would like to use this process, but it is opt-in and not mandatory. Think of it as a fast track for unstable features. Stabilizing a feature could be harder, as it would mean a review across several PRs, and may not easily work with GitHub review UI. But the stabilization review should be easier than a large PR as there would be actual usage feedback. @@ -65,12 +64,10 @@ An unstable feature accepted in Bevy may stop working due to the merge of anothe ## Rationale and alternatives -- Improve the process to get new features in Bevy that would benefit from iterative work. - Alternatives: - Continue as it is now, with semi large PRs that bitrot and RFCs that don't often move forward - Work harder to implement a new feature as a third party crate (this is not always possible) - - Fork Bevy to merge unnaproved PRs and check how they work / interact - + - Fork Bevy to merge unapproved PRs and check how they work / interact ## Prior art From 000933107ac9abdb5816b76dd44a4aa40bb04d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Mon, 7 Mar 2022 13:07:13 +0100 Subject: [PATCH 13/17] adding alternative Co-Authored-By: Alice Cecile --- rfcs/52-unstable_features.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index f1424208..aa700039 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -66,6 +66,7 @@ An unstable feature accepted in Bevy may stop working due to the merge of anothe - Alternatives: - Continue as it is now, with semi large PRs that bitrot and RFCs that don't often move forward + - Grant scoped merge rights to teams / team leads for more areas of the Bevy engine, and tell users to deal with the instability - Work harder to implement a new feature as a third party crate (this is not always possible) - Fork Bevy to merge unapproved PRs and check how they work / interact From accd03971dfb66658d8084e80fe3506a36953c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Mon, 7 Mar 2022 13:07:31 +0100 Subject: [PATCH 14/17] adding discussion on Rust RFCs Co-Authored-By: Alice Cecile --- rfcs/52-unstable_features.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index aa700039..875aec16 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -72,7 +72,8 @@ An unstable feature accepted in Bevy may stop working due to the merge of anothe ## Prior art -[The Rust process](https://rustc-dev-guide.rust-lang.org/implementing_new_features.html) +- [The Rust process](https://rustc-dev-guide.rust-lang.org/implementing_new_features.html) +- [Discussion about slowness of RFCs](https://www.reddit.com/r/rust/comments/sy65f7/we_need_to_talk_about_rfcs/) ## Unresolved questions From a37bd9c31d1408c1446c7f04249830e369502976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Mon, 7 Mar 2022 13:08:01 +0100 Subject: [PATCH 15/17] other motivations --- rfcs/52-unstable_features.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index 875aec16..a7934784 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -8,6 +8,10 @@ Experimental new features are merged into main behind a feature gate before stab Some features would benefit from iterative work in Bevy, but that may be hard to do when a PRs need a high level of quality to be merged in. +Merging new features behind a feature gate could improve this situation. New features could start getting user feedback, helping reach a higher quality before stabilization. + +This would also improve the contributor experience for PRs that stay open for some time and ends up conflicting with main. + In this RFC, "feature" means the new feature or change under development, and "feature gate" the conditional compilation flag. "unstable" means a feature that is subject to change, not something that will break Bevy. ## User-facing explanation From c063ad9e5c7c6be733bc6e514313656dec4256ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Mon, 7 Mar 2022 13:08:11 +0100 Subject: [PATCH 16/17] details on drawback --- rfcs/52-unstable_features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index a7934784..b8677133 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -58,7 +58,7 @@ For organization and discovery, a GitHub project can be used to track the stabil ## Drawbacks -This will increase complexity in Bevy code. +This will increase complexity in Bevy code. Increased complexity can be controlled by limiting the number of unstable features available at a given time, or their scope. It will also increase complexity of a contribution that would like to use this process, but it is opt-in and not mandatory. Think of it as a fast track for unstable features. From 3d5766fdb7fe9bd7a94b858e4b77fecb1334e016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Mon, 7 Mar 2022 13:18:42 +0100 Subject: [PATCH 17/17] add info on other PR interactions --- rfcs/52-unstable_features.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rfcs/52-unstable_features.md b/rfcs/52-unstable_features.md index b8677133..c8203f66 100644 --- a/rfcs/52-unstable_features.md +++ b/rfcs/52-unstable_features.md @@ -56,6 +56,8 @@ The feature gate should not be exposed on the main `bevy` crate, but only on the For organization and discovery, a GitHub project can be used to track the stabilization issues. +While it should be avoided, if another PR breaks an unstable feature, it is not the PR author responsability to fix it. They may do it if they want, otherwise it must be reported on the unstable feature tracking issue. + ## Drawbacks This will increase complexity in Bevy code. Increased complexity can be controlled by limiting the number of unstable features available at a given time, or their scope.