Skip to content

Writing and Implementing RFCs ​

Use this skill when a task requires an RFC — a new public API, a behavior change, or a deprecation — or when implementing one that has already been accepted.

When you need an RFC ​

Not every change needs one. A bug fix, an internal refactor, or an addition that doesn't change public API or observable behavior does not. If the change adds, changes, or deprecates public API or behavior, it needs an RFC before implementation begins — see The RFC Process for the full discussion-and-consensus workflow leading up to drafting.

Keep deprecations in their own RFC, separate from the feature that replaces them ​

When a new feature makes existing public API or behavior obsolete, the feature and the deprecation of what it replaces belong in two separate RFCs, not one combined proposal. The feature RFC comes first and stands on its own. The deprecation is a distinct RFC that follows, and deprecates the old behavior only once the replacement has shipped and reached the Recommended stage — the point at which we're confident the successor is the right one to steer people toward.

Combining them couples two decisions the team needs to make independently: whether the new API is right, and whether (and when) the old one should go. It also forces the deprecation's timeline to track the feature's before either is settled, and tends to bloat the feature RFC with flag ids and migration mechanics that distract from the design under review.

So: keep the feature RFC to the feature. It's fine — often helpful — to note in its "Detailed design" ecosystem section that a follow-on deprecation is expected, but put the deprecation's flag id, since/until versions, and migration path in its own RFC. See 0005-deprecate-legacy-packages.md for the shape a deprecation RFC takes.

Drafting ​

WarpDrive-specific RFCs live in rfcs/ in this repository, which is the source of truth — not emberjs/rfcs. Numbering is local to this repo, 1-indexed, independent of any emberjs/rfcs number:

  1. Copy rfcs/0000-template.md to rfcs/000N-your-title.md, where N is the next unused number (check the existing files in rfcs/ — don't reuse or skip numbers).
  2. Fill in the template's frontmatter and body. The sidebar nav is generated automatically from warp-drive-rfc/title/stage/start-date, ordered by RFC number — there's no separate list to update. Leave emberjs-rfc, emberjs-pr, emberjs-branch, and sync-hash blank — the sync bot fills these in once the RFC is first mirrored upstream; hand-editing them just gets overwritten and can desync the two copies. Don't start title with "WarpDrive" — the sync bot adds that prefix automatically for the emberjs/rfcs copy and its PR title, so a local title that already has it would end up doubled there.
  3. Review the draft for terseness and conciseness before opening the PR, and again after every edit to it. Reviewers, and later implementers, read an RFC to learn what the public behavior will be and why; anything else in it costs them time and can drift from the implementation that ships. Omit internal implementation details unless they affect observable public behavior, and where they do, describe the effect in brief rather than the mechanism. Keep historical exposition minimal: enough to motivate the change, not a chronicle of how the current behavior came to be.
  4. Open a PR labeled :label: rfc (see Pull Request Labeling for the PR mechanics). That label also triggers a docs-site PR preview so reviewers can read the rendered RFC, not just the raw markdown diff. Once it's open, add its RFC summary per Write a PR Blog Summary, so the next release post lists it.
  5. Iterate on the PR like any other design discussion. Once there is team consensus to move forward, merging the PR is what publishes the RFC — see the next section for what that triggers.

How the emberjs/rfcs sync works ​

WarpDrive still follows Ember's RFC process end to end (Proposed → Exploring → FCP → Accepted → Ready for Release → Released → Recommended, per emberjs/rfcs' own stages) — those stages are tracked and voted on in emberjs/rfcs, not here. What changes is where the text lives and who edits it first: this repo, not emberjs/rfcs, is authoritative for the content.

A dedicated bot account (see scripts/rfc-sync/README.md) maintains its own fork of emberjs/rfcs and does the mirroring, entirely through PRs on both sides — it never has direct write access to emberjs/rfcs itself, and never merges anything:

  • Outbound (on merge to main here): a new RFC (no emberjs-rfc set yet) gets a brand-new PR opened against emberjs/rfcs from the bot's fork; an already-published RFC gets a new commit pushed to the same fork branch that already backs its open emberjs/rfcs PR. Either way, the commit's author is set to whoever actually wrote the change in this repo — the bot only ever appears as committer, never author, so credit for the words stays with the person who wrote them.
  • Inbound: the bot polls its own fork branches for commits it didn't make itself — e.g. an Ember reviewer applying a suggested edit directly on the PR (this requires "allow edits from maintainers", which the bot sets when opening the PR). When it finds one, it opens a PR back into warp-drive-data/warp-drive with that change, again crediting the real author.
  • Nothing is ever auto-merged on either side. Every sync lands as a PR for a human to review.

If you're picking up an RFC that predates the bot (its emberjs-branch frontmatter field is blank), the bot can't sync it until a maintainer points it at the right upstream fork branch, or lets it open a fresh PR — ask in #dev-ember-data if you hit this.

Implementing an accepted RFC ​

  • Reference the RFC number in your implementation PR's description (e.g. "Implements rfcs/0003-..."), so reviewers and future readers can find the design discussion.
  • Land the implementation behind the same phased/deprecation approach the RFC describes, if it describes one — don't skip straight to the end state an RFC called out as a later phase.
  • Ship the documentation with the implementation. An accepted RFC is the first item in the Cross-Documentation Checklist for a new public API or a deprecation; the TSDoc, guide, and upgrade page it lists come next. Follow Write Documentation for those.
  • Once landed, stage in the RFC's frontmatter (both here and, via the sync bot, upstream) advances the same way emberjs/rfcs advancement PRs do today — this repo does not add a separate advancement mechanism. A PR that changes stage adds or updates an RFC summary too, per Write a PR Blog Summary.

Released under the MIT License.