Adds "Edition Tooling" to the GitHub code repository.

PiperOrigin-RevId: 565137196
diff --git a/docs/design/prototiller/README.md b/docs/design/prototiller/README.md
index ab44afa..40496e1 100644
--- a/docs/design/prototiller/README.md
+++ b/docs/design/prototiller/README.md
@@ -18,4 +18,5 @@
 The following topics are in this repository:
 
 *   [Prototiller Requirements for Editions](prototiller-reqs-for-editions.md)
-*   [Prototiller Requirements for Edition Zero](prototiller-reqs-for-edition-zero.md)
\ No newline at end of file
+*   [Prototiller Requirements for Edition Zero](prototiller-reqs-for-edition-zero.md)
+*   [Editions Tooling](editions-tooling.md)
\ No newline at end of file
diff --git a/docs/design/prototiller/editions-tooling.md b/docs/design/prototiller/editions-tooling.md
new file mode 100644
index 0000000..2c4b137
--- /dev/null
+++ b/docs/design/prototiller/editions-tooling.md
@@ -0,0 +1,165 @@
+# Editions Tooling
+
+**Authors:** [@mcy](https://github.com/mcy)
+
+**Approved:** 2022-08-09
+
+## Overview
+
+[Protobuf Editions](../editions/what-are-protobuf-editions.md) aims to introduce
+new semantics for Protobuf, but with a major emphasis on mechanical, incremental
+upgradability, to avoid the two systems problem of proto2 and proto3. The first
+edition (likely "2023") will introduce *converged semantics* for Protobuf that
+permit everything that proto2 and proto3 permitted: any non-editions file can
+become an editions file with minimal human intervention.
+
+We plan to achieve this with a strong tooling story. These tools are intended to
+fully automate major steps in editions-related upgrade operations, for both large-scale changes
+and open source software strategic reasons. In particular:
+
+*   Non-automated large-scale change work in the editions space can be constrained to fixing
+    uses of generated code and flipping features on specific fields (or other
+    declarations).
+*   We can give our external users the most painless migration possible, which
+    consists of "run this tool and commit the results".
+
+This document describes the detailed design of the tools we need. This document
+presupposes *Protochangifier Backend Design Doc* (not available externally) integrated into protoc as a prerequisite, so we
+can ship the tooling as part of protoc. Because the tooling must know the full
+definition of an edition to work (see below), it seems to more-or-less place a
+hard requirement of being linked to protoc.
+
+There are three tools we will build.
+
+1.  The "features janitor". This is a mode of `protoc` which consumes a `.proto`
+    file and produces a `ProtoChangeSpec` that describes how to add and remove
+    features such that the resulting janitor'ed file has fewer explicit
+    features, but is not semantically different.
+2.  The "editions adopter". This is another mode of `protoc`, which produces a
+    `ProtoChangeSpec` that describes how to bring a `proto2` or `proto3` file
+    into editions mode, starting at a specific edition.
+3.  The "editions upgrader". This is a generalization of the adopter, which
+    takes an editions file and produces a `ProtoChangeSpec` that brings it into
+    a newer edition.
+
+These tools will fundamentally speak `ProtoChangeSpec`, but we should also
+provide in-place versions, since those will likely be more useful to OSS users
+that just want to run the tool atomically on their entire project.
+
+## The Janitor
+
+The features janitor is intended to be used as part of migrations to
+periodically clean up any messes made by flipping lots of features.
+Conceptually, it turns this proto file
+
+```
+edition = "2023";
+message Foo {
+  optional string a = 1 [features.(pb.cpp).string_type = VIEW];
+  optional string b = 2 [features.(pb.cpp).string_type = VIEW];
+  optional string c = 3 [features.(pb.cpp).string_type = VIEW];
+  optional string d = 4 [features.(pb.cpp).string_type = VIEW];
+  optional string e = 5 [features.(pb.cpp).string_type = VIEW];
+}
+message Bar {
+  optional string a = 1 [features.(pb.cpp).string_type = VIEW];
+  optional string b = 2;
+  optional string c = 3;
+  optional string d = 4;
+  optional string e = 5;
+}
+```
+
+into this one:
+
+```
+edition = "2023";
+message Foo {
+  option features.(pb.cpp).string_type = VIEW;
+  optional string a = 1;
+  optional string b = 2;
+  optional string c = 3;
+  optional string d = 4;
+  optional string e = 5;
+}
+message Bar {
+  optional string a = 1 [features.(pb.cpp).string_type = VIEW];
+  optional string b = 2;
+  optional string c = 3;
+  optional string d = 4;
+  optional string e = 5;
+}
+```
+
+Specifically, the janitor tries to minimize the number of explicit features on
+the Protobuf schema. Actually doing this minimally feels like it's nonlinear, so
+we should invent a heuristic. A sketch of what this could look like:
+
+1.  Each feature that can appear explicitly on an AST node is either *critical*
+    for that node or only for grouping. For example, `string_type` is critical
+    for fields but not for messages.
+2.  Propagate features explicitly to every node, including edition defaults.
+3.  For each feature `f`, for each node `n` that `f` is non-critical for that
+    contains (recursively) nodes that it is critical for (in DFS order):
+    1.  Set `f` for `n` to the value for `f` that the plurality of its direct
+        children have, and remove the explicit `f` from those. If tied, choose
+        the edition default if it is among the plurals, or else choose randomly.
+4.  Once repeated up to the root, delete all explicit features that are
+    reachable from the root without crossing another explicit feature that isn't
+    the edition default. I.e., those features which are implied by the edition
+    defaults.
+
+It is easy to construct cases where this is not optimal, but that is not
+important. This merely exists to make files prettier while keeping them
+equivalent. It is easy to see that, by construction, this algorithm satisfies
+the "semantic no-op" requirement.
+
+## The Adopter and the Updater
+
+The adopter is merely a special case of the updater where `proto2` and `proto3`
+are viewed as editions (in the sense that an edition is a set of defaults), so
+we will only describe the updater.
+
+To update one edition ("old") to another ("new", although not necessarily a
+newer edition):
+
+1.  Features that are not already explicitly set at the top level are set to the
+    default given by "old"; they are only set on the outermost scope that does
+    not have an explicit feature. For example, for file-level features, this
+    means making all features explicit at the file level. For message-level
+    features that are not file-level, this means placing an explicit feature on
+    all top-level messages. This is a no-op, because `edition = "old";` implies
+    this.
+2.  The file's edition is set from "old" to "new". Because every feature that
+    could be explicit is explicit, this is a no-op.
+3.  Feature janitor runs. This explicitly propagates all features (all of which
+    are set explicitly at the top level), and then cleans them up with respect
+    to the "new" edition; note that feature janitor gives preference to editions
+    defaults. This is a no-op, because feature janitor is a no-op.
+
+## UX Concerns
+
+Bundling the editions tooling with `protoc` ensures that it is easy to find. The
+following will be the pattern for all Protochangifier tooling bundled into
+`protoc`:
+
+*   There is a flag `--change_spec=changespec.pb` which will cause protoc to
+    apply a changespec to the passed-in `.proto` file, e.g. `protoc
+    --change_spec=spec.pb --change_out=foo-changed.proto foo.proto`. This writes
+    the change to `foo-changed.proto`. This may be the same file as `foo.proto`
+    for in-place updates; it may be left out to have the change printed to
+    stdout. This is the core entry-point for Protochanfigier.
+*   There is a flag `--my_analysis` for the given analysis, e.g. `--janitor`.
+    This flag can have an optional argument: if set, it will output the change
+    spec to that path, e.g. `--janitor=spec.pb`. If it is not passed in, the
+    change is applied in place without the need to use `protoc --change_spec`.
+
+Alternatively, we could provide these as standalone tools. However, it seems
+useful from a distribution perspective and user education perspective to say
+"this is just part of the compiler". We expect to produce new migration tooling
+with Protochangifier on an ongoing basis, so teaching users that every analysis
+looks the same is important. Compare `rustfix`, the tool that Rust uses for
+things like upgrading editions. Although it is a separate binary, it is
+accessible through `cargo fix`, and in a lot of ways `cargo` is the user-facing
+interface to Rust; having it be part of the "swiss army knife" helps put it in
+front of users.