[dm] Delete dm, tumble and some related GAE-only dependencies.

It is unused code that rots. In particular it blocks migration
off GAE APIs.

R=iannucci@chromium.org

Change-Id: Ib2e1b0c8142355f09eb2fcbcd474ed55ab58b289
Reviewed-on: https://chromium-review.googlesource.com/c/infra/luci/luci-go/+/3656372
Reviewed-by: Robbie Iannucci <iannucci@chromium.org>
Commit-Queue: Vadim Shtayura <vadimsh@chromium.org>
diff --git a/appengine/memlock/memlock.go b/appengine/memlock/memlock.go
deleted file mode 100644
index 9ec7587..0000000
--- a/appengine/memlock/memlock.go
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package memlock allows multiple appengine handlers to coordinate best-effort
-// mutual execution via memcache. "best-effort" here means "best-effort"...
-// memcache is not reliable. However, colliding on memcache is a lot cheaper
-// than, for example, colliding with datastore transactions.
-//
-// Deprecated: the implementation depends on the GAE Memcache API which is not
-// available outside of the GAE first-gen runtime. There's currently no direct
-// replacement, but one can be written on top of
-// go.chromium.org/luci/server/redisconn if necessary.
-package memlock
-
-import (
-	"bytes"
-	"context"
-	"errors"
-	"time"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/retry"
-	mc "go.chromium.org/luci/gae/service/memcache"
-)
-
-// ErrFailedToLock is returned from TryWithLock when it fails to obtain a lock
-// prior to invoking the user-supplied function.
-var ErrFailedToLock = errors.New("memlock: failed to obtain lock")
-
-// ErrEmptyClientID is returned from TryWithLock when you specify an empty
-// clientID.
-var ErrEmptyClientID = errors.New("memlock: empty clientID")
-
-// memlockKeyPrefix is the memcache Key prefix for all user-supplied keys.
-const memlockKeyPrefix = "memlock:"
-
-type checkOp string
-
-// var so we can override it in the tests
-var delay = time.Second
-
-type testStopCBKeyType int
-
-var testStopCBKey testStopCBKeyType
-
-const (
-	release checkOp = "release"
-	refresh         = "refresh"
-)
-
-// memcacheLockTime is the expiration time of the memcache entry. If the lock
-// is correctly released, then it will be released before this time. It's a
-// var so we can override it in the tests.
-var memcacheLockTime = 16 * time.Second
-
-// TryWithLock attempts to obtains the lock once, and then invokes f if
-// successful. The context provided to f will be canceled (e.g. ctx.Done() will
-// be closed) if memlock detects that we've lost the lock.
-//
-// TryWithLock function returns ErrFailedToLock if it fails to obtain the lock,
-// otherwise returns the error that f returns.
-//
-// `key` is the memcache key to use (i.e. the name of the lock). Clients locking
-// the same data must use the same key. clientID is the unique identifier for
-// this client (lock-holder). If it's empty then TryWithLock() will return
-// ErrEmptyClientID.
-//
-// Note that the lock provided by TryWithLock is a best-effort lock... some
-// other form of locking or synchronization should be used inside of f (such as
-// Datastore transactions) to ensure that f is, in fact, operating exclusively.
-// The purpose of TryWithLock is to have a cheap filter to prevent unnecessary
-// contention on heavier synchronization primitives like transactions.
-func TryWithLock(ctx context.Context, key, clientID string, f func(context.Context) error) error {
-	if len(clientID) == 0 {
-		return ErrEmptyClientID
-	}
-
-	log := logging.Get(
-		logging.SetFields(ctx, logging.Fields{
-			"key":      key,
-			"clientID": clientID,
-		}))
-
-	key = memlockKeyPrefix + key
-	cid := []byte(clientID)
-
-	// checkAnd gets the current value from memcache, and then attempts to do the
-	// checkOp (which can either be `refresh` or `release`). These pieces of
-	// functionality are necessarially intertwined, because CAS only works with
-	// the exact-same *Item which was returned from a Get.
-	//
-	// refresh will attempt to CAS the item with the same content to reset it's
-	// timeout.
-	//
-	// release will attempt to CAS the item to remove it's contents (clientID).
-	// another lock observing an empty clientID will know that the lock is
-	// obtainable.
-	checkAnd := func(op checkOp) bool {
-		limitedRetry := func() retry.Iterator {
-			return &retry.Limited{
-				Delay:   time.Second,
-				Retries: 5,
-			}
-		}
-		var itm mc.Item
-		if err := retry.Retry(ctx, limitedRetry, func() (err error) {
-			itm, err = mc.GetKey(ctx, key)
-			return
-		}, retry.LogCallback(ctx, "getting lock from memcache")); err != nil {
-			log.Warningf("permanent error getting: %s", err)
-			return false
-		}
-
-		if len(itm.Value()) > 0 && !bytes.Equal(itm.Value(), cid) {
-			log.Infof("lock owned by %q", string(itm.Value()))
-			return false
-		}
-
-		if op == refresh {
-			itm.SetValue(cid).SetExpiration(memcacheLockTime)
-		} else {
-			if len(itm.Value()) == 0 {
-				// it's already unlocked, no need to CAS
-				log.Infof("lock already released")
-				return true
-			}
-			itm.SetValue([]byte{}).SetExpiration(delay)
-		}
-
-		if err := mc.CompareAndSwap(ctx, itm); err != nil {
-			log.Warningf("failed to %s lock: %q", op, err)
-			return false
-		}
-
-		return true
-	}
-
-	// Now the actual logic begins. First we 'Add' the item, which will set it if
-	// it's not present in the memcache, otherwise leaves it alone.
-
-	err := mc.Add(ctx, mc.NewItem(ctx, key).SetValue(cid).SetExpiration(memcacheLockTime))
-	if err != nil {
-		if err != mc.ErrNotStored {
-			log.Warningf("error adding: %s", err)
-		}
-		if !checkAnd(refresh) {
-			return ErrFailedToLock
-		}
-	}
-
-	// At this point we nominally have the lock (at least for memcacheLockTime).
-	finished := make(chan struct{})
-	subCtx, cancelFunc := context.WithCancel(ctx)
-	defer func() {
-		cancelFunc()
-		<-finished
-	}()
-
-	testStopCB, _ := ctx.Value(testStopCBKey).(func())
-
-	// This goroutine checks to see if we still possess the lock, and refreshes it
-	// if we do.
-	go func() {
-		defer func() {
-			cancelFunc()
-			close(finished)
-		}()
-
-		tmr := clock.NewTimer(subCtx)
-		defer tmr.Stop()
-		for {
-			tmr.Reset(delay)
-
-			if tr := <-tmr.GetC(); tr.Incomplete() {
-				if tr.Err != context.Canceled {
-					log.Debugf("context done: %s", tr.Err)
-				}
-				break
-			}
-			if !checkAnd(refresh) {
-				log.Warningf("lost lock: %s", err)
-				return
-			}
-		}
-
-		if testStopCB != nil {
-			testStopCB()
-		}
-		checkAnd(release)
-	}()
-
-	return f(subCtx)
-}
diff --git a/appengine/memlock/memlock_test.go b/appengine/memlock/memlock_test.go
deleted file mode 100644
index cc94e9b..0000000
--- a/appengine/memlock/memlock_test.go
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package memlock
-
-import (
-	"context"
-	"fmt"
-	"sync"
-	"testing"
-	"time"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/clock/testclock"
-	"go.chromium.org/luci/gae/filter/featureBreaker"
-	"go.chromium.org/luci/gae/impl/memory"
-	mc "go.chromium.org/luci/gae/service/memcache"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-type getBlockerFilterContext struct {
-	sync.Mutex
-
-	dropAll bool
-}
-
-type getBlockerFilter struct {
-	mc.RawInterface
-	gbfc *getBlockerFilterContext
-}
-
-func (f *getBlockerFilter) GetMulti(keys []string, cb mc.RawItemCB) error {
-	f.gbfc.Lock()
-	defer f.gbfc.Unlock()
-	if f.gbfc.dropAll {
-		for _, key := range keys {
-			cb(f.NewItem(key), nil)
-		}
-		return nil
-	}
-	return f.RawInterface.GetMulti(keys, cb)
-}
-
-func TestSimple(t *testing.T) {
-	// TODO(riannucci): Mock time.After so that we don't have to delay for real.
-
-	const key = memlockKeyPrefix + "testkey"
-
-	Convey("basic locking", t, func() {
-		start := time.Date(1986, time.October, 26, 1, 20, 00, 00, time.UTC)
-		ctx, clk := testclock.UseTime(context.Background(), start)
-		blocker := make(chan struct{})
-		clk.SetTimerCallback(func(time.Duration, clock.Timer) {
-			clk.Add(delay)
-			select {
-			case blocker <- struct{}{}:
-			default:
-			}
-		})
-
-		waitFalse := func(ctx context.Context) {
-		loop:
-			for {
-				select {
-				case <-blocker:
-					continue
-				case <-ctx.Done():
-					break loop
-				}
-			}
-		}
-
-		ctx, fb := featureBreaker.FilterMC(memory.Use(ctx), nil)
-
-		Convey("fails to acquire when memcache is down", func() {
-			fb.BreakFeatures(nil, "AddMulti")
-			err := TryWithLock(ctx, "testkey", "id", func(context.Context) error {
-				// should never reach here
-				So(false, ShouldBeTrue)
-				return nil
-			})
-			So(err, ShouldEqual, ErrFailedToLock)
-		})
-
-		Convey("returns the inner error", func() {
-			toRet := fmt.Errorf("sup")
-			err := TryWithLock(ctx, "testkey", "id", func(context.Context) error {
-				return toRet
-			})
-			So(err, ShouldEqual, toRet)
-		})
-
-		Convey("returns the error", func() {
-			toRet := fmt.Errorf("sup")
-			err := TryWithLock(ctx, "testkey", "id", func(context.Context) error {
-				return toRet
-			})
-			So(err, ShouldEqual, toRet)
-		})
-
-		Convey("can acquire when empty", func() {
-			err := TryWithLock(ctx, "testkey", "id", func(ctx context.Context) error {
-				isDone := func() bool {
-					select {
-					case <-ctx.Done():
-						return true
-					default:
-						return false
-					}
-				}
-
-				So(isDone(), ShouldBeFalse)
-
-				Convey("waiting for a while keeps refreshing the lock", func() {
-					// simulate waiting for 64*delay time, and ensuring that checkLoop
-					// runs that many times.
-					for i := 0; i < 64; i++ {
-						<-blocker
-						clk.Add(delay)
-					}
-					So(isDone(), ShouldBeFalse)
-				})
-
-				Convey("but sometimes we might lose it", func() {
-					Convey("because it was evicted", func() {
-						mc.Delete(ctx, key)
-						clk.Add(memcacheLockTime)
-						waitFalse(ctx)
-					})
-
-					Convey("or because of service issues", func() {
-						fb.BreakFeatures(nil, "CompareAndSwapMulti")
-						waitFalse(ctx)
-					})
-				})
-				return nil
-			})
-			So(err, ShouldBeNil)
-		})
-
-		Convey("can lose it when it gets stolen", func() {
-			gbfc := getBlockerFilterContext{}
-			ctx = mc.AddRawFilters(ctx, func(_ context.Context, raw mc.RawInterface) mc.RawInterface {
-				return &getBlockerFilter{
-					RawInterface: raw,
-					gbfc:         &gbfc,
-				}
-			})
-			err := TryWithLock(ctx, "testkey", "id", func(ctx context.Context) error {
-				// simulate waiting for 64*delay time, and ensuring that checkLoop
-				// runs that many times.
-				for i := 0; i < 64; i++ {
-					<-blocker
-					clk.Add(delay)
-				}
-				gbfc.Lock()
-				mc.Set(ctx, mc.NewItem(ctx, key).SetValue([]byte("wat")))
-				gbfc.Unlock()
-				waitFalse(ctx)
-				return nil
-			})
-			So(err, ShouldBeNil)
-		})
-
-		Convey("can lose it when it gets preemptively released", func() {
-			gbfc := getBlockerFilterContext{}
-			ctx = mc.AddRawFilters(ctx, func(_ context.Context, raw mc.RawInterface) mc.RawInterface {
-				return &getBlockerFilter{
-					RawInterface: raw,
-					gbfc:         &gbfc,
-				}
-			})
-			ctx = context.WithValue(ctx, testStopCBKey, func() {
-				gbfc.Lock()
-				defer gbfc.Unlock()
-
-				gbfc.dropAll = true
-			})
-			err := TryWithLock(ctx, "testkey", "id", func(ctx context.Context) error {
-				// simulate waiting for 64*delay time, and ensuring that checkLoop
-				// runs that many times.
-				for i := 0; i < 64; i++ {
-					<-blocker
-					clk.Add(delay)
-				}
-				return nil
-			})
-			So(err, ShouldBeNil)
-		})
-
-		Convey("an empty context id is an error", func() {
-			So(TryWithLock(ctx, "testkey", "", nil), ShouldEqual, ErrEmptyClientID)
-		})
-	})
-}
diff --git a/appengine/meta/doc.go b/appengine/meta/doc.go
deleted file mode 100644
index 7fae908..0000000
--- a/appengine/meta/doc.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package meta contains some methods for interacting with GAE's metadata APIs.
-// It only contains an implementation for those metadata APIs we've needed so
-// far, but should be extended to support new ones in the case that we use them.
-//
-// See metadata docs: https://cloud.google.com/appengine/docs/python/datastore/metadataentityclasses#EntityGroup
-//
-// Deprecated: this package depends on Cloud Datastore features which on are not
-// available in Firestore-in-Datastore mode (which is the default Cloud
-// Datastore mode for new project).
-package meta
diff --git a/appengine/meta/eg.go b/appengine/meta/eg.go
deleted file mode 100644
index 1722fe2..0000000
--- a/appengine/meta/eg.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package meta
-
-import (
-	"context"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-)
-
-// EntityGroupMeta is the model corresponding to the __entity_group__ model in
-// appengine. You shouldn't need to use this struct directly, but instead should
-// use GetEntityGroupVersion.
-type EntityGroupMeta struct {
-	kind   string  `gae:"$kind,__entity_group__"`
-	id     int64   `gae:"$id,1"`
-	Parent *ds.Key `gae:"$parent"`
-
-	Version int64 `gae:"__version__"`
-}
-
-// GetEntityGroupVersion returns the entity group version for the entity group
-// containing root. If the entity group doesn't exist, this function will return
-// zero and a nil error.
-func GetEntityGroupVersion(ctx context.Context, key *ds.Key) (int64, error) {
-	egm := &EntityGroupMeta{Parent: key.Root()}
-	err := ds.Get(ctx, egm)
-	ret := egm.Version
-	if err == ds.ErrNoSuchEntity {
-		// this is OK for callers. The version of the entity group is effectively 0
-		// in this case.
-		err = nil
-	}
-	return ret, err
-}
diff --git a/appengine/meta/eg_test.go b/appengine/meta/eg_test.go
deleted file mode 100644
index 3b3afa8..0000000
--- a/appengine/meta/eg_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package meta
-
-import (
-	"context"
-	"errors"
-	"testing"
-
-	"go.chromium.org/luci/gae/filter/featureBreaker"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestGetEntityGroupVersion(t *testing.T) {
-	t.Parallel()
-
-	Convey("GetEntityGroupVersion", t, func() {
-		c := memory.Use(context.Background())
-		c, fb := featureBreaker.FilterRDS(c, errors.New("INTERNAL_ERROR"))
-
-		pm := ds.PropertyMap{
-			"$key": ds.MkPropertyNI(ds.MakeKey(c, "A", "")),
-			"Val":  ds.MkProperty(10),
-		}
-		So(ds.Put(c, pm), ShouldBeNil)
-		aKey := ds.KeyForObj(c, pm)
-		So(aKey, ShouldNotBeNil)
-
-		v, err := GetEntityGroupVersion(c, aKey)
-		So(err, ShouldBeNil)
-		So(v, ShouldEqual, 1)
-
-		So(ds.Delete(c, aKey), ShouldBeNil)
-
-		v, err = GetEntityGroupVersion(c, ds.NewKey(c, "madeUp", "thing", 0, aKey))
-		So(err, ShouldBeNil)
-		So(v, ShouldEqual, 2)
-
-		v, err = GetEntityGroupVersion(c, ds.NewKey(c, "madeUp", "thing", 0, nil))
-		So(err, ShouldBeNil)
-		So(v, ShouldEqual, 0)
-
-		fb.BreakFeatures(nil, "GetMulti")
-
-		v, err = GetEntityGroupVersion(c, aKey)
-		So(err.Error(), ShouldContainSubstring, "INTERNAL_ERROR")
-	})
-}
diff --git a/dm/OWNERS b/dm/OWNERS
deleted file mode 100644
index 760558a..0000000
--- a/dm/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-iannucci@chromium.org
diff --git a/dm/api/acls/acls.pb.go b/dm/api/acls/acls.pb.go
deleted file mode 100644
index a239549..0000000
--- a/dm/api/acls/acls.pb.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/acls/acls.proto
-
-package acls
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// TODO(iannucci): move these to per-project acls when implementing per-project
-// namespaces.
-type Acls struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Readers []string `protobuf:"bytes,1,rep,name=readers,proto3" json:"readers,omitempty"`
-	Writers []string `protobuf:"bytes,2,rep,name=writers,proto3" json:"writers,omitempty"`
-}
-
-func (x *Acls) Reset() {
-	*x = Acls{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_acls_acls_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Acls) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Acls) ProtoMessage() {}
-
-func (x *Acls) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_acls_acls_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Acls.ProtoReflect.Descriptor instead.
-func (*Acls) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Acls) GetReaders() []string {
-	if x != nil {
-		return x.Readers
-	}
-	return nil
-}
-
-func (x *Acls) GetWriters() []string {
-	if x != nil {
-		return x.Writers
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_acls_acls_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDesc = []byte{
-	0x0a, 0x2b, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x63,
-	0x6c, 0x73, 0x2f, 0x61, 0x63, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x61,
-	0x63, 0x6c, 0x73, 0x22, 0x3a, 0x0a, 0x04, 0x41, 0x63, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72,
-	0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65,
-	0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x73,
-	0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x73, 0x42,
-	0x22, 0x5a, 0x20, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f,
-	0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61,
-	0x63, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDescData = file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_acls_acls_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_go_chromium_org_luci_dm_api_acls_acls_proto_goTypes = []interface{}{
-	(*Acls)(nil), // 0: acls.Acls
-}
-var file_go_chromium_org_luci_dm_api_acls_acls_proto_depIdxs = []int32{
-	0, // [0:0] is the sub-list for method output_type
-	0, // [0:0] is the sub-list for method input_type
-	0, // [0:0] is the sub-list for extension type_name
-	0, // [0:0] is the sub-list for extension extendee
-	0, // [0:0] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_acls_acls_proto_init() }
-func file_go_chromium_org_luci_dm_api_acls_acls_proto_init() {
-	if File_go_chromium_org_luci_dm_api_acls_acls_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_acls_acls_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Acls); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   1,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_acls_acls_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_acls_acls_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_acls_acls_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_acls_acls_proto = out.File
-	file_go_chromium_org_luci_dm_api_acls_acls_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_acls_acls_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_acls_acls_proto_depIdxs = nil
-}
diff --git a/dm/api/acls/acls.proto b/dm/api/acls/acls.proto
deleted file mode 100644
index 3461485..0000000
--- a/dm/api/acls/acls.proto
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto3";
-
-package acls;
-
-option go_package = "go.chromium.org/luci/dm/api/acls";
-
-// TODO(iannucci): move these to per-project acls when implementing per-project
-// namespaces.
-message Acls {
-  repeated string readers = 1;
-  repeated string writers = 2;
-}
diff --git a/dm/api/acls/gen.go b/dm/api/acls/gen.go
deleted file mode 100644
index 4495016..0000000
--- a/dm/api/acls/gen.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package acls
-
-//go:generate cproto
diff --git a/dm/api/distributor/distributor.pb.go b/dm/api/distributor/distributor.pb.go
deleted file mode 100644
index 08c98e6..0000000
--- a/dm/api/distributor/distributor.pb.go
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/distributor.proto
-
-package distributor
-
-import (
-	jobsim "go.chromium.org/luci/dm/api/distributor/jobsim"
-	v1 "go.chromium.org/luci/dm/api/distributor/swarming/v1"
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type Alias struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	OtherConfig string `protobuf:"bytes,1,opt,name=other_config,json=otherConfig,proto3" json:"other_config,omitempty"`
-}
-
-func (x *Alias) Reset() {
-	*x = Alias{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Alias) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Alias) ProtoMessage() {}
-
-func (x *Alias) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Alias.ProtoReflect.Descriptor instead.
-func (*Alias) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Alias) GetOtherConfig() string {
-	if x != nil {
-		return x.OtherConfig
-	}
-	return ""
-}
-
-type Distributor struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// TODO(iannucci): Maybe something like Any or extensions would be a better
-	// fit here? The ultimate goal is that users will be able to use the proto
-	// text format for luci-config. I suspect that Any or extensions would lose
-	// the ability to validate such text-formatted protobufs, but maybe that's
-	// not the case.
-	//
-	// Types that are assignable to DistributorType:
-	//	*Distributor_Alias
-	//	*Distributor_SwarmingV1
-	//	*Distributor_Jobsim
-	DistributorType isDistributor_DistributorType `protobuf_oneof:"distributor_type"`
-}
-
-func (x *Distributor) Reset() {
-	*x = Distributor{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Distributor) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Distributor) ProtoMessage() {}
-
-func (x *Distributor) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Distributor.ProtoReflect.Descriptor instead.
-func (*Distributor) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescGZIP(), []int{1}
-}
-
-func (m *Distributor) GetDistributorType() isDistributor_DistributorType {
-	if m != nil {
-		return m.DistributorType
-	}
-	return nil
-}
-
-func (x *Distributor) GetAlias() *Alias {
-	if x, ok := x.GetDistributorType().(*Distributor_Alias); ok {
-		return x.Alias
-	}
-	return nil
-}
-
-func (x *Distributor) GetSwarmingV1() *v1.Config {
-	if x, ok := x.GetDistributorType().(*Distributor_SwarmingV1); ok {
-		return x.SwarmingV1
-	}
-	return nil
-}
-
-func (x *Distributor) GetJobsim() *jobsim.Config {
-	if x, ok := x.GetDistributorType().(*Distributor_Jobsim); ok {
-		return x.Jobsim
-	}
-	return nil
-}
-
-type isDistributor_DistributorType interface {
-	isDistributor_DistributorType()
-}
-
-type Distributor_Alias struct {
-	Alias *Alias `protobuf:"bytes,1,opt,name=alias,proto3,oneof"`
-}
-
-type Distributor_SwarmingV1 struct {
-	SwarmingV1 *v1.Config `protobuf:"bytes,4,opt,name=swarming_v1,json=swarmingV1,proto3,oneof"`
-}
-
-type Distributor_Jobsim struct {
-	// this is for testing purposes and will only be used in production to put
-	// test load on DM. It's tagged at 2048 to keep it well out of the way.
-	Jobsim *jobsim.Config `protobuf:"bytes,2048,opt,name=jobsim,proto3,oneof"`
-}
-
-func (*Distributor_Alias) isDistributor_DistributorType() {}
-
-func (*Distributor_SwarmingV1) isDistributor_DistributorType() {}
-
-func (*Distributor_Jobsim) isDistributor_DistributorType() {}
-
-type Config struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	DistributorConfigs map[string]*Distributor `protobuf:"bytes,1,rep,name=distributor_configs,json=distributorConfigs,proto3" json:"distributor_configs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-}
-
-func (x *Config) Reset() {
-	*x = Config{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Config) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Config) ProtoMessage() {}
-
-func (x *Config) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Config.ProtoReflect.Descriptor instead.
-func (*Config) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescGZIP(), []int{2}
-}
-
-func (x *Config) GetDistributorConfigs() map[string]*Distributor {
-	if x != nil {
-		return x.DistributorConfigs
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_distributor_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDesc = []byte{
-	0x0a, 0x39, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69,
-	0x62, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x64, 0x69, 0x73,
-	0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x1a, 0x3b, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72,
-	0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64,
-	0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f,
-	0x72, 0x2f, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2f, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x40, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69,
-	0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61,
-	0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73,
-	0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
-	0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x2a, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73,
-	0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x22, 0xbb, 0x01, 0x0a, 0x0b, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
-	0x74, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72,
-	0x2e, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x48, 0x00, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12,
-	0x35, 0x0a, 0x0b, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x31, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56,
-	0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0a, 0x73, 0x77, 0x61, 0x72,
-	0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x12, 0x29, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d,
-	0x18, 0x80, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d,
-	0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x6a, 0x6f, 0x62, 0x73, 0x69,
-	0x6d, 0x42, 0x12, 0x0a, 0x10, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72,
-	0x5f, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10,
-	0x04, 0x22, 0xc7, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5c, 0x0a, 0x13,
-	0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
-	0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x64, 0x69, 0x73, 0x74,
-	0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44,
-	0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
-	0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x1a, 0x5f, 0x0a, 0x17, 0x44, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73,
-	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62,
-	0x75, 0x74, 0x6f, 0x72, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72,
-	0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x29, 0x5a, 0x27, 0x67,
-	0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c,
-	0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72,
-	0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
-var file_go_chromium_org_luci_dm_api_distributor_distributor_proto_goTypes = []interface{}{
-	(*Alias)(nil),         // 0: distributor.Alias
-	(*Distributor)(nil),   // 1: distributor.Distributor
-	(*Config)(nil),        // 2: distributor.Config
-	nil,                   // 3: distributor.Config.DistributorConfigsEntry
-	(*v1.Config)(nil),     // 4: swarmingV1.Config
-	(*jobsim.Config)(nil), // 5: jobsim.Config
-}
-var file_go_chromium_org_luci_dm_api_distributor_distributor_proto_depIdxs = []int32{
-	0, // 0: distributor.Distributor.alias:type_name -> distributor.Alias
-	4, // 1: distributor.Distributor.swarming_v1:type_name -> swarmingV1.Config
-	5, // 2: distributor.Distributor.jobsim:type_name -> jobsim.Config
-	3, // 3: distributor.Config.distributor_configs:type_name -> distributor.Config.DistributorConfigsEntry
-	1, // 4: distributor.Config.DistributorConfigsEntry.value:type_name -> distributor.Distributor
-	5, // [5:5] is the sub-list for method output_type
-	5, // [5:5] is the sub-list for method input_type
-	5, // [5:5] is the sub-list for extension type_name
-	5, // [5:5] is the sub-list for extension extendee
-	0, // [0:5] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_distributor_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_distributor_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_distributor_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Alias); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Distributor); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Config); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes[1].OneofWrappers = []interface{}{
-		(*Distributor_Alias)(nil),
-		(*Distributor_SwarmingV1)(nil),
-		(*Distributor_Jobsim)(nil),
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   4,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_distributor_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_distributor_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_distributor_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_distributor_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_distributor_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_distributor_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_distributor_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/distributor.proto b/dm/api/distributor/distributor.proto
deleted file mode 100644
index 8a291a0..0000000
--- a/dm/api/distributor/distributor.proto
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor";
-
-package distributor;
-
-import "go.chromium.org/luci/dm/api/distributor/jobsim/jobsim.proto";
-import "go.chromium.org/luci/dm/api/distributor/swarming/v1/config.proto";
-
-message Alias {
-  string other_config = 1;
-}
-
-message Distributor {
-  reserved 2; // future: generic pRPC based distributor
-  reserved 3; // future: generic gRPC based distributor
-
-  // TODO(iannucci): Maybe something like Any or extensions would be a better
-  // fit here? The ultimate goal is that users will be able to use the proto
-  // text format for luci-config. I suspect that Any or extensions would lose
-  // the ability to validate such text-formatted protobufs, but maybe that's
-  // not the case.
-  oneof distributor_type {
-    Alias alias = 1;
-
-    swarmingV1.Config swarming_v1 = 4;
-
-    // this is for testing purposes and will only be used in production to put
-    // test load on DM. It's tagged at 2048 to keep it well out of the way.
-    jobsim.Config jobsim = 2048;
-  }
-}
-
-message Config {
-  map<string, Distributor> distributor_configs = 1;
-}
diff --git a/dm/api/distributor/gen.go b/dm/api/distributor/gen.go
deleted file mode 100644
index 4b72033..0000000
--- a/dm/api/distributor/gen.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package distributor
-
-//go:generate cproto
diff --git a/dm/api/distributor/jobsim/gen.go b/dm/api/distributor/jobsim/gen.go
deleted file mode 100644
index adf11db..0000000
--- a/dm/api/distributor/jobsim/gen.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//go:generate cproto
-//go:generate proto-gae -type Phrase
-
-package jobsim
diff --git a/dm/api/distributor/jobsim/iterate.go b/dm/api/distributor/jobsim/iterate.go
deleted file mode 100644
index 31c78ed..0000000
--- a/dm/api/distributor/jobsim/iterate.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package jobsim
-
-import (
-	"encoding/binary"
-	"fmt"
-	"hash/fnv"
-	"math"
-	"math/rand"
-)
-
-// ToSlice returns this SparseRange as an expanded slice of uint32s.
-func (s *SparseRange) ToSlice() (ret []uint32) {
-	for _, itm := range s.Items {
-		switch x := itm.RangeItem.(type) {
-		case *RangeItem_Single:
-			ret = append(ret, x.Single)
-		case *RangeItem_Range:
-			for i := x.Range.Low; i <= x.Range.High; i++ {
-				ret = append(ret, i)
-			}
-		}
-	}
-	return
-}
-
-// ExpandShards expands any dependencies that have non-zero Shards values.
-func (s *DepsStage) ExpandShards() {
-	newSlice := make([]*Dependency, 0, len(s.Deps))
-	for _, dep := range s.Deps {
-		if dep.Shards != 0 {
-			for i := uint64(0); i < dep.Shards; i++ {
-				depCopy := *dep
-				depCopy.Shards = 0
-				phraseCopy := *depCopy.Phrase
-				phraseCopy.Name = fmt.Sprintf("%s_%d", phraseCopy.Name, i)
-				depCopy.Phrase = &phraseCopy
-				newSlice = append(newSlice, &depCopy)
-			}
-		} else {
-			newSlice = append(newSlice, dep)
-		}
-	}
-	s.Deps = newSlice
-}
-
-// fastHash is a non-cryptographic NxN -> N hash function. It's used to
-// deterministically blend seeds for subjobs.
-func fastHash(a int64, bs ...int64) int64 {
-	buf := make([]byte, 8)
-	hasher := fnv.New64a()
-	w := func(v int64) {
-		binary.LittleEndian.PutUint64(buf, uint64(v))
-		if _, err := hasher.Write(buf); err != nil {
-			panic(err)
-		}
-	}
-	w(a)
-	for _, b := range bs {
-		w(b)
-	}
-	return int64(hasher.Sum64())
-}
-
-// Seed rewrites this dependency's Seed value
-func (d *Dependency) Seed(rnd *rand.Rand, seed, round int64) {
-	if d.MixSeed {
-		if d.Phrase.Seed == 0 {
-			d.Phrase.Seed = rnd.Int63()
-		} else {
-			d.Phrase.Seed = fastHash(seed*(math.MaxInt32), d.Phrase.Seed, round)
-		}
-	} else if d.Phrase.Seed == 0 {
-		d.Phrase.Seed = seed
-	}
-}
diff --git a/dm/api/distributor/jobsim/jobsim.pb.go b/dm/api/distributor/jobsim/jobsim.pb.go
deleted file mode 100644
index 639cc07..0000000
--- a/dm/api/distributor/jobsim/jobsim.pb.go
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/jobsim/jobsim.proto
-
-package jobsim
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// Config is ONLY for testing purposes in dm/service. However, because of the
-// way that the distributor proto works it needs to be included in the main
-// distributor.proto file. For consistency, this jobsim proto lives here.
-type Config struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Pool specifies the unique 'pool' name for this jobsim configuration. This
-	// will be used to namespace jobsim objects in the datastore, and can be used
-	// to demonstrate cross-distributor dependencies (by having one pool's jobs
-	// depend on another pool's results).
-	Pool string `protobuf:"bytes,1,opt,name=pool,proto3" json:"pool,omitempty"`
-	// DoPollback controls whether or not this configuration will force DM to
-	// poll back when recieving a HandleNotification. If this is true, then
-	// HandleNotification will return (nil, nil), and DM will call GetStatus
-	// at some later point. If this is false, then HandleNotification will
-	// directly return the job's status.
-	DoPollback bool `protobuf:"varint,2,opt,name=do_pollback,json=doPollback,proto3" json:"do_pollback,omitempty"`
-}
-
-func (x *Config) Reset() {
-	*x = Config{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Config) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Config) ProtoMessage() {}
-
-func (x *Config) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Config.ProtoReflect.Descriptor instead.
-func (*Config) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Config) GetPool() string {
-	if x != nil {
-		return x.Pool
-	}
-	return ""
-}
-
-func (x *Config) GetDoPollback() bool {
-	if x != nil {
-		return x.DoPollback
-	}
-	return false
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDesc = []byte{
-	0x0a, 0x3b, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d,
-	0x2f, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6a,
-	0x6f, 0x62, 0x73, 0x69, 0x6d, 0x22, 0x3d, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
-	0x12, 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70,
-	0x6f, 0x6f, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x6f, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
-	0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, 0x6f, 0x50, 0x6f, 0x6c, 0x6c,
-	0x62, 0x61, 0x63, 0x6b, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d,
-	0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f,
-	0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f,
-	0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_goTypes = []interface{}{
-	(*Config)(nil), // 0: jobsim.Config
-}
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_depIdxs = []int32{
-	0, // [0:0] is the sub-list for method output_type
-	0, // [0:0] is the sub-list for method input_type
-	0, // [0:0] is the sub-list for extension type_name
-	0, // [0:0] is the sub-list for extension extendee
-	0, // [0:0] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Config); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   1,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_jobsim_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/jobsim/jobsim.proto b/dm/api/distributor/jobsim/jobsim.proto
deleted file mode 100644
index 896ca27..0000000
--- a/dm/api/distributor/jobsim/jobsim.proto
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor/jobsim";
-
-package jobsim;
-
-// Config is ONLY for testing purposes in dm/service. However, because of the
-// way that the distributor proto works it needs to be included in the main
-// distributor.proto file. For consistency, this jobsim proto lives here.
-message Config {
-  // Pool specifies the unique 'pool' name for this jobsim configuration. This
-  // will be used to namespace jobsim objects in the datastore, and can be used
-  // to demonstrate cross-distributor dependencies (by having one pool's jobs
-  // depend on another pool's results).
-  string pool = 1;
-
-  // DoPollback controls whether or not this configuration will force DM to
-  // poll back when recieving a HandleNotification. If this is true, then
-  // HandleNotification will return (nil, nil), and DM will call GetStatus
-  // at some later point. If this is false, then HandleNotification will
-  // directly return the job's status.
-  bool do_pollback = 2;
-}
diff --git a/dm/api/distributor/jobsim/proto_gae.gen.go b/dm/api/distributor/jobsim/proto_gae.gen.go
deleted file mode 100644
index d09ab40..0000000
--- a/dm/api/distributor/jobsim/proto_gae.gen.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Code generated by gae/tools/proto-gae/proto_gae.go. DO NOT EDIT.
-
-//go:build !copybara
-// +build !copybara
-
-package jobsim
-
-import (
-	"google.golang.org/protobuf/proto"
-
-	"go.chromium.org/luci/gae/service/datastore"
-)
-
-var _ datastore.PropertyConverter = (*Phrase)(nil)
-
-// ToProperty implements datastore.PropertyConverter. It causes an embedded
-// 'Phrase' to serialize to an unindexed '[]byte' when used with the
-// "go.chromium.org/luci/gae" library.
-func (p *Phrase) ToProperty() (prop datastore.Property, err error) {
-	data, err := proto.Marshal(p)
-	if err == nil {
-		prop.SetValue(data, datastore.NoIndex)
-	}
-	return
-}
-
-// FromProperty implements datastore.PropertyConverter. It parses a '[]byte'
-// into an embedded 'Phrase' when used with the "go.chromium.org/luci/gae" library.
-func (p *Phrase) FromProperty(prop datastore.Property) error {
-	data, err := prop.Project(datastore.PTBytes)
-	if err != nil {
-		return err
-	}
-	return proto.Unmarshal(data.([]byte), p)
-}
diff --git a/dm/api/distributor/jobsim/result.pb.go b/dm/api/distributor/jobsim/result.pb.go
deleted file mode 100644
index f694647..0000000
--- a/dm/api/distributor/jobsim/result.pb.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/jobsim/result.proto
-
-package jobsim
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// Result is the jobsim distributor result object used for executions.
-type Result struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Success bool  `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
-	Value   int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"`
-}
-
-func (x *Result) Reset() {
-	*x = Result{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Result) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Result) ProtoMessage() {}
-
-func (x *Result) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Result.ProtoReflect.Descriptor instead.
-func (*Result) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Result) GetSuccess() bool {
-	if x != nil {
-		return x.Success
-	}
-	return false
-}
-
-func (x *Result) GetValue() int64 {
-	if x != nil {
-		return x.Value
-	}
-	return 0
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDesc = []byte{
-	0x0a, 0x3b, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d,
-	0x2f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6a,
-	0x6f, 0x62, 0x73, 0x69, 0x6d, 0x22, 0x38, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12,
-	0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
-	0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
-	0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42,
-	0x30, 0x5a, 0x2e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f,
-	0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64,
-	0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x6a, 0x6f, 0x62, 0x73, 0x69,
-	0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_goTypes = []interface{}{
-	(*Result)(nil), // 0: jobsim.Result
-}
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_depIdxs = []int32{
-	0, // [0:0] is the sub-list for method output_type
-	0, // [0:0] is the sub-list for method input_type
-	0, // [0:0] is the sub-list for extension type_name
-	0, // [0:0] is the sub-list for extension extendee
-	0, // [0:0] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Result); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   1,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_result_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/jobsim/result.proto b/dm/api/distributor/jobsim/result.proto
deleted file mode 100644
index 6cc04dc..0000000
--- a/dm/api/distributor/jobsim/result.proto
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor/jobsim";
-
-package jobsim;
-
-// Result is the jobsim distributor result object used for executions.
-message Result {
-  bool success = 1;
-  int64 value = 2;
-}
diff --git a/dm/api/distributor/jobsim/task.pb.go b/dm/api/distributor/jobsim/task.pb.go
deleted file mode 100644
index 7fc20d9..0000000
--- a/dm/api/distributor/jobsim/task.pb.go
+++ /dev/null
@@ -1,992 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/jobsim/task.proto
-
-package jobsim
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	durationpb "google.golang.org/protobuf/types/known/durationpb"
-	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// Phrase is a task to do. It consists of zero or more stages, followed by
-// an optional ReturnStage.
-type Phrase struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	// Seed should be selected via a fair dice roll (using a d1.84e19).
-	Seed        int64        `protobuf:"varint,2,opt,name=seed,proto3" json:"seed,omitempty"`
-	Stages      []*Stage     `protobuf:"bytes,3,rep,name=stages,proto3" json:"stages,omitempty"`
-	ReturnStage *ReturnStage `protobuf:"bytes,4,opt,name=return_stage,json=returnStage,proto3" json:"return_stage,omitempty"`
-}
-
-func (x *Phrase) Reset() {
-	*x = Phrase{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Phrase) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Phrase) ProtoMessage() {}
-
-func (x *Phrase) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Phrase.ProtoReflect.Descriptor instead.
-func (*Phrase) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Phrase) GetName() string {
-	if x != nil {
-		return x.Name
-	}
-	return ""
-}
-
-func (x *Phrase) GetSeed() int64 {
-	if x != nil {
-		return x.Seed
-	}
-	return 0
-}
-
-func (x *Phrase) GetStages() []*Stage {
-	if x != nil {
-		return x.Stages
-	}
-	return nil
-}
-
-func (x *Phrase) GetReturnStage() *ReturnStage {
-	if x != nil {
-		return x.ReturnStage
-	}
-	return nil
-}
-
-// ReturnStage indicates that the Phrase should return the numerical value
-// 'retval' as the result of the current Phrase. If expiration is provided,
-// it will set that as the expiration timestamp for the provided retval.
-type ReturnStage struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Retval     int64                  `protobuf:"varint,1,opt,name=retval,proto3" json:"retval,omitempty"`
-	Expiration *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expiration,proto3" json:"expiration,omitempty"`
-}
-
-func (x *ReturnStage) Reset() {
-	*x = ReturnStage{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *ReturnStage) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*ReturnStage) ProtoMessage() {}
-
-func (x *ReturnStage) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use ReturnStage.ProtoReflect.Descriptor instead.
-func (*ReturnStage) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{1}
-}
-
-func (x *ReturnStage) GetRetval() int64 {
-	if x != nil {
-		return x.Retval
-	}
-	return 0
-}
-
-func (x *ReturnStage) GetExpiration() *timestamppb.Timestamp {
-	if x != nil {
-		return x.Expiration
-	}
-	return nil
-}
-
-// Stage is the union of the following stage types:
-//   * FailureStage
-//   * StallStage
-//   * DepsStage
-type Stage struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Types that are assignable to StageType:
-	//	*Stage_Failure
-	//	*Stage_Stall
-	//	*Stage_Deps
-	StageType isStage_StageType `protobuf_oneof:"stage_type"`
-}
-
-func (x *Stage) Reset() {
-	*x = Stage{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Stage) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Stage) ProtoMessage() {}
-
-func (x *Stage) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Stage.ProtoReflect.Descriptor instead.
-func (*Stage) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{2}
-}
-
-func (m *Stage) GetStageType() isStage_StageType {
-	if m != nil {
-		return m.StageType
-	}
-	return nil
-}
-
-func (x *Stage) GetFailure() *FailureStage {
-	if x, ok := x.GetStageType().(*Stage_Failure); ok {
-		return x.Failure
-	}
-	return nil
-}
-
-func (x *Stage) GetStall() *StallStage {
-	if x, ok := x.GetStageType().(*Stage_Stall); ok {
-		return x.Stall
-	}
-	return nil
-}
-
-func (x *Stage) GetDeps() *DepsStage {
-	if x, ok := x.GetStageType().(*Stage_Deps); ok {
-		return x.Deps
-	}
-	return nil
-}
-
-type isStage_StageType interface {
-	isStage_StageType()
-}
-
-type Stage_Failure struct {
-	Failure *FailureStage `protobuf:"bytes,1,opt,name=failure,proto3,oneof"`
-}
-
-type Stage_Stall struct {
-	Stall *StallStage `protobuf:"bytes,2,opt,name=stall,proto3,oneof"`
-}
-
-type Stage_Deps struct {
-	Deps *DepsStage `protobuf:"bytes,3,opt,name=deps,proto3,oneof"`
-}
-
-func (*Stage_Failure) isStage_StageType() {}
-
-func (*Stage_Stall) isStage_StageType() {}
-
-func (*Stage_Deps) isStage_StageType() {}
-
-// FailureStage is the /chance/ to fail with a certain liklihood. The chance
-// is calculated using the current Phrase's 'seed' with the "math/rand" package,
-// The seed is either 0 (unspecified), or the value of the 'seed' property for
-// the currently running phrase.
-//
-// 0 is a 0-percent chance of failure.
-// 1 is a 100-percent chance of failure.
-type FailureStage struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Chance float32 `protobuf:"fixed32,1,opt,name=chance,proto3" json:"chance,omitempty"`
-}
-
-func (x *FailureStage) Reset() {
-	*x = FailureStage{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[3]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *FailureStage) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*FailureStage) ProtoMessage() {}
-
-func (x *FailureStage) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[3]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use FailureStage.ProtoReflect.Descriptor instead.
-func (*FailureStage) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{3}
-}
-
-func (x *FailureStage) GetChance() float32 {
-	if x != nil {
-		return x.Chance
-	}
-	return 0
-}
-
-// StallStage delays the phrase for the provided Duration. This could be used
-// to simulate long-running tasks (like builds).
-type StallStage struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Delay *durationpb.Duration `protobuf:"bytes,1,opt,name=delay,proto3" json:"delay,omitempty"`
-}
-
-func (x *StallStage) Reset() {
-	*x = StallStage{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[4]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *StallStage) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*StallStage) ProtoMessage() {}
-
-func (x *StallStage) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[4]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use StallStage.ProtoReflect.Descriptor instead.
-func (*StallStage) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{4}
-}
-
-func (x *StallStage) GetDelay() *durationpb.Duration {
-	if x != nil {
-		return x.Delay
-	}
-	return nil
-}
-
-// DepsStage represents the opportunity to depend on 1 or more dependencies
-// simultaneously.
-type DepsStage struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Deps []*Dependency `protobuf:"bytes,1,rep,name=deps,proto3" json:"deps,omitempty"`
-}
-
-func (x *DepsStage) Reset() {
-	*x = DepsStage{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[5]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *DepsStage) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*DepsStage) ProtoMessage() {}
-
-func (x *DepsStage) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[5]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use DepsStage.ProtoReflect.Descriptor instead.
-func (*DepsStage) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{5}
-}
-
-func (x *DepsStage) GetDeps() []*Dependency {
-	if x != nil {
-		return x.Deps
-	}
-	return nil
-}
-
-// Dependency represents a nested Phrase that this Phrase depends on.
-type Dependency struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// shards append [1], [2], [3], etc. to the "name"s of the dependencies, making
-	// them unique quests.
-	Shards uint64 `protobuf:"varint,1,opt,name=shards,proto3" json:"shards,omitempty"`
-	// Types that are assignable to AttemptStrategy:
-	//	*Dependency_Attempts
-	//	*Dependency_Retries
-	AttemptStrategy isDependency_AttemptStrategy `protobuf_oneof:"attempt_strategy"`
-	// MixSeed will blend the current seed with the seed in the phrase seed,
-	// when depending on it.
-	//
-	//   mix_seed phrase.seed==0 -> dep uses "random" seed
-	//   mix_seed phrase.seed!=0 -> dep uses blend(current seed, phrase.seed)
-	//  !mix_seed phrase.seed==0 -> dep uses current seed
-	//  !mix_seed phrase.seed!=0 -> dep uses phrase.seed
-	MixSeed bool    `protobuf:"varint,4,opt,name=mix_seed,json=mixSeed,proto3" json:"mix_seed,omitempty"`
-	Phrase  *Phrase `protobuf:"bytes,5,opt,name=phrase,proto3" json:"phrase,omitempty"`
-}
-
-func (x *Dependency) Reset() {
-	*x = Dependency{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[6]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Dependency) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Dependency) ProtoMessage() {}
-
-func (x *Dependency) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[6]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Dependency.ProtoReflect.Descriptor instead.
-func (*Dependency) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{6}
-}
-
-func (x *Dependency) GetShards() uint64 {
-	if x != nil {
-		return x.Shards
-	}
-	return 0
-}
-
-func (m *Dependency) GetAttemptStrategy() isDependency_AttemptStrategy {
-	if m != nil {
-		return m.AttemptStrategy
-	}
-	return nil
-}
-
-func (x *Dependency) GetAttempts() *SparseRange {
-	if x, ok := x.GetAttemptStrategy().(*Dependency_Attempts); ok {
-		return x.Attempts
-	}
-	return nil
-}
-
-func (x *Dependency) GetRetries() uint32 {
-	if x, ok := x.GetAttemptStrategy().(*Dependency_Retries); ok {
-		return x.Retries
-	}
-	return 0
-}
-
-func (x *Dependency) GetMixSeed() bool {
-	if x != nil {
-		return x.MixSeed
-	}
-	return false
-}
-
-func (x *Dependency) GetPhrase() *Phrase {
-	if x != nil {
-		return x.Phrase
-	}
-	return nil
-}
-
-type isDependency_AttemptStrategy interface {
-	isDependency_AttemptStrategy()
-}
-
-type Dependency_Attempts struct {
-	Attempts *SparseRange `protobuf:"bytes,2,opt,name=attempts,proto3,oneof"`
-}
-
-type Dependency_Retries struct {
-	Retries uint32 `protobuf:"varint,3,opt,name=retries,proto3,oneof"`
-}
-
-func (*Dependency_Attempts) isDependency_AttemptStrategy() {}
-
-func (*Dependency_Retries) isDependency_AttemptStrategy() {}
-
-// SparseRange allows the expression of mixed partial ranges like [1,3-10,19,21].
-type SparseRange struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Items []*RangeItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
-}
-
-func (x *SparseRange) Reset() {
-	*x = SparseRange{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[7]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *SparseRange) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*SparseRange) ProtoMessage() {}
-
-func (x *SparseRange) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[7]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use SparseRange.ProtoReflect.Descriptor instead.
-func (*SparseRange) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{7}
-}
-
-func (x *SparseRange) GetItems() []*RangeItem {
-	if x != nil {
-		return x.Items
-	}
-	return nil
-}
-
-// RangeItem is either a single number or a Range.
-type RangeItem struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Types that are assignable to RangeItem:
-	//	*RangeItem_Single
-	//	*RangeItem_Range
-	RangeItem isRangeItem_RangeItem `protobuf_oneof:"range_item"`
-}
-
-func (x *RangeItem) Reset() {
-	*x = RangeItem{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[8]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *RangeItem) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*RangeItem) ProtoMessage() {}
-
-func (x *RangeItem) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[8]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use RangeItem.ProtoReflect.Descriptor instead.
-func (*RangeItem) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{8}
-}
-
-func (m *RangeItem) GetRangeItem() isRangeItem_RangeItem {
-	if m != nil {
-		return m.RangeItem
-	}
-	return nil
-}
-
-func (x *RangeItem) GetSingle() uint32 {
-	if x, ok := x.GetRangeItem().(*RangeItem_Single); ok {
-		return x.Single
-	}
-	return 0
-}
-
-func (x *RangeItem) GetRange() *Range {
-	if x, ok := x.GetRangeItem().(*RangeItem_Range); ok {
-		return x.Range
-	}
-	return nil
-}
-
-type isRangeItem_RangeItem interface {
-	isRangeItem_RangeItem()
-}
-
-type RangeItem_Single struct {
-	Single uint32 `protobuf:"varint,1,opt,name=single,proto3,oneof"`
-}
-
-type RangeItem_Range struct {
-	Range *Range `protobuf:"bytes,2,opt,name=range,proto3,oneof"`
-}
-
-func (*RangeItem_Single) isRangeItem_RangeItem() {}
-
-func (*RangeItem_Range) isRangeItem_RangeItem() {}
-
-// Range represents a single low-high pair (e.g. [3-40])
-type Range struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Low  uint32 `protobuf:"varint,1,opt,name=low,proto3" json:"low,omitempty"`
-	High uint32 `protobuf:"varint,2,opt,name=high,proto3" json:"high,omitempty"`
-}
-
-func (x *Range) Reset() {
-	*x = Range{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[9]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Range) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Range) ProtoMessage() {}
-
-func (x *Range) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[9]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Range.ProtoReflect.Descriptor instead.
-func (*Range) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP(), []int{9}
-}
-
-func (x *Range) GetLow() uint32 {
-	if x != nil {
-		return x.Low
-	}
-	return 0
-}
-
-func (x *Range) GetHigh() uint32 {
-	if x != nil {
-		return x.High
-	}
-	return 0
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDesc = []byte{
-	0x0a, 0x39, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d,
-	0x2f, 0x74, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6a, 0x6f, 0x62,
-	0x73, 0x69, 0x6d, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8f, 0x01, 0x0a, 0x06, 0x50, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12,
-	0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x03, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x67, 0x65,
-	0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d,
-	0x2e, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x67, 0x65, 0x73, 0x12, 0x36,
-	0x0a, 0x0c, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x52, 0x65,
-	0x74, 0x75, 0x72, 0x6e, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x75, 0x72,
-	0x6e, 0x53, 0x74, 0x61, 0x67, 0x65, 0x22, 0x61, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e,
-	0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x12, 0x3a, 0x0a,
-	0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65,
-	0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9c, 0x01, 0x0a, 0x05, 0x53, 0x74,
-	0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x07, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x46, 0x61,
-	0x69, 0x6c, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x07, 0x66, 0x61,
-	0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x53, 0x74,
-	0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x6c,
-	0x6c, 0x12, 0x27, 0x0a, 0x04, 0x64, 0x65, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x11, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x44, 0x65, 0x70, 0x73, 0x53, 0x74, 0x61,
-	0x67, 0x65, 0x48, 0x00, 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x73, 0x74,
-	0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x26, 0x0a, 0x0c, 0x46, 0x61, 0x69, 0x6c,
-	0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e,
-	0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x63, 0x65,
-	0x22, 0x3d, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x2f,
-	0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-	0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x22,
-	0x33, 0x0a, 0x09, 0x44, 0x65, 0x70, 0x73, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x04,
-	0x64, 0x65, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6a, 0x6f, 0x62,
-	0x73, 0x69, 0x6d, 0x2e, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x04,
-	0x64, 0x65, 0x70, 0x73, 0x22, 0xca, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65,
-	0x6e, 0x63, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x04, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x61,
-	0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e,
-	0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x52, 0x61, 0x6e,
-	0x67, 0x65, 0x48, 0x00, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x12, 0x1a,
-	0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x48,
-	0x00, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x69,
-	0x78, 0x5f, 0x73, 0x65, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6d, 0x69,
-	0x78, 0x53, 0x65, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x06, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18,
-	0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x50,
-	0x68, 0x72, 0x61, 0x73, 0x65, 0x52, 0x06, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x42, 0x12, 0x0a,
-	0x10, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
-	0x79, 0x22, 0x36, 0x0a, 0x0b, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65,
-	0x12, 0x27, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x11, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x74,
-	0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x5a, 0x0a, 0x09, 0x52, 0x61, 0x6e,
-	0x67, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x18, 0x0a, 0x06, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x06, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65,
-	0x12, 0x25, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x0d, 0x2e, 0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x00,
-	0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x72, 0x61, 0x6e, 0x67, 0x65,
-	0x5f, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x2d, 0x0a, 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x10,
-	0x0a, 0x03, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6c, 0x6f, 0x77,
-	0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x67, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04,
-	0x68, 0x69, 0x67, 0x68, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d,
-	0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f,
-	0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f,
-	0x6a, 0x6f, 0x62, 0x73, 0x69, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_goTypes = []interface{}{
-	(*Phrase)(nil),                // 0: jobsim.Phrase
-	(*ReturnStage)(nil),           // 1: jobsim.ReturnStage
-	(*Stage)(nil),                 // 2: jobsim.Stage
-	(*FailureStage)(nil),          // 3: jobsim.FailureStage
-	(*StallStage)(nil),            // 4: jobsim.StallStage
-	(*DepsStage)(nil),             // 5: jobsim.DepsStage
-	(*Dependency)(nil),            // 6: jobsim.Dependency
-	(*SparseRange)(nil),           // 7: jobsim.SparseRange
-	(*RangeItem)(nil),             // 8: jobsim.RangeItem
-	(*Range)(nil),                 // 9: jobsim.Range
-	(*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp
-	(*durationpb.Duration)(nil),   // 11: google.protobuf.Duration
-}
-var file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_depIdxs = []int32{
-	2,  // 0: jobsim.Phrase.stages:type_name -> jobsim.Stage
-	1,  // 1: jobsim.Phrase.return_stage:type_name -> jobsim.ReturnStage
-	10, // 2: jobsim.ReturnStage.expiration:type_name -> google.protobuf.Timestamp
-	3,  // 3: jobsim.Stage.failure:type_name -> jobsim.FailureStage
-	4,  // 4: jobsim.Stage.stall:type_name -> jobsim.StallStage
-	5,  // 5: jobsim.Stage.deps:type_name -> jobsim.DepsStage
-	11, // 6: jobsim.StallStage.delay:type_name -> google.protobuf.Duration
-	6,  // 7: jobsim.DepsStage.deps:type_name -> jobsim.Dependency
-	7,  // 8: jobsim.Dependency.attempts:type_name -> jobsim.SparseRange
-	0,  // 9: jobsim.Dependency.phrase:type_name -> jobsim.Phrase
-	8,  // 10: jobsim.SparseRange.items:type_name -> jobsim.RangeItem
-	9,  // 11: jobsim.RangeItem.range:type_name -> jobsim.Range
-	12, // [12:12] is the sub-list for method output_type
-	12, // [12:12] is the sub-list for method input_type
-	12, // [12:12] is the sub-list for extension type_name
-	12, // [12:12] is the sub-list for extension extendee
-	0,  // [0:12] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Phrase); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ReturnStage); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Stage); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*FailureStage); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*StallStage); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*DepsStage); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Dependency); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*SparseRange); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*RangeItem); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Range); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[2].OneofWrappers = []interface{}{
-		(*Stage_Failure)(nil),
-		(*Stage_Stall)(nil),
-		(*Stage_Deps)(nil),
-	}
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[6].OneofWrappers = []interface{}{
-		(*Dependency_Attempts)(nil),
-		(*Dependency_Retries)(nil),
-	}
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes[8].OneofWrappers = []interface{}{
-		(*RangeItem_Single)(nil),
-		(*RangeItem_Range)(nil),
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   10,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_jobsim_task_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/jobsim/task.proto b/dm/api/distributor/jobsim/task.proto
deleted file mode 100644
index 31129e6..0000000
--- a/dm/api/distributor/jobsim/task.proto
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor/jobsim";
-
-import "google/protobuf/timestamp.proto";
-import "google/protobuf/duration.proto";
-
-package jobsim;
-
-// Phrase is a task to do. It consists of zero or more stages, followed by
-// an optional ReturnStage.
-message Phrase {
-  string name = 1;
-  // Seed should be selected via a fair dice roll (using a d1.84e19).
-  int64 seed = 2;
-  repeated Stage stages = 3;
-  ReturnStage return_stage = 4;
-}
-
-// ReturnStage indicates that the Phrase should return the numerical value
-// 'retval' as the result of the current Phrase. If expiration is provided,
-// it will set that as the expiration timestamp for the provided retval.
-message ReturnStage {
-  int64 retval = 1;
-  google.protobuf.Timestamp expiration = 2;
-}
-
-// Stage is the union of the following stage types:
-//   * FailureStage
-//   * StallStage
-//   * DepsStage
-message Stage {
-  oneof stage_type {
-    FailureStage failure = 1;
-    StallStage stall = 2;
-    DepsStage deps = 3;
-  }
-}
-
-// FailureStage is the /chance/ to fail with a certain liklihood. The chance
-// is calculated using the current Phrase's 'seed' with the "math/rand" package,
-// The seed is either 0 (unspecified), or the value of the 'seed' property for
-// the currently running phrase.
-//
-// 0 is a 0-percent chance of failure.
-// 1 is a 100-percent chance of failure.
-message FailureStage {
-  float chance = 1;
-}
-
-// StallStage delays the phrase for the provided Duration. This could be used
-// to simulate long-running tasks (like builds).
-message StallStage {
-  google.protobuf.Duration delay = 1;
-}
-
-// DepsStage represents the opportunity to depend on 1 or more dependencies
-// simultaneously.
-message DepsStage {
-  repeated Dependency deps = 1;
-}
-
-// Dependency represents a nested Phrase that this Phrase depends on.
-message Dependency {
-  // shards append [1], [2], [3], etc. to the "name"s of the dependencies, making
-  // them unique quests.
-  uint64 shards = 1;
-
-  oneof attempt_strategy {
-    SparseRange attempts = 2;
-    uint32 retries = 3;
-  }
-
-  // MixSeed will blend the current seed with the seed in the phrase seed,
-  // when depending on it.
-  //
-  //   mix_seed phrase.seed==0 -> dep uses "random" seed
-  //   mix_seed phrase.seed!=0 -> dep uses blend(current seed, phrase.seed)
-  //  !mix_seed phrase.seed==0 -> dep uses current seed
-  //  !mix_seed phrase.seed!=0 -> dep uses phrase.seed
-  bool mix_seed = 4;
-  Phrase phrase = 5;
-}
-
-// SparseRange allows the expression of mixed partial ranges like [1,3-10,19,21].
-message SparseRange {
-  repeated RangeItem items = 1;
-}
-
-// RangeItem is either a single number or a Range.
-message RangeItem {
-  oneof range_item {
-    uint32 single = 1;
-    Range range = 2;
-  }
-}
-
-// Range represents a single low-high pair (e.g. [3-40])
-message Range {
-  uint32 low = 1;
-  uint32 high = 2;
-}
diff --git a/dm/api/distributor/jobsim/validate.go b/dm/api/distributor/jobsim/validate.go
deleted file mode 100644
index a9d13ee..0000000
--- a/dm/api/distributor/jobsim/validate.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package jobsim
-
-import (
-	"fmt"
-)
-
-var _ interface {
-	Normalize() error
-} = (*Phrase)(nil)
-
-// Normalize checks Phrase for errors and converts it to its normalized form.
-func (p *Phrase) Normalize() error {
-	if p != nil {
-		if p.Name == "" {
-			return fmt.Errorf("empty ID")
-		}
-		for _, s := range p.Stages {
-			if err := s.Normalize(); err != nil {
-				return err
-			}
-		}
-		if p.ReturnStage == nil {
-			p.ReturnStage = &ReturnStage{Retval: 1}
-		}
-	}
-	return nil
-}
-
-// Normalize checks Stage for errors and converts it to its normalized form.
-func (s *Stage) Normalize() error {
-	switch st := s.GetStageType().(type) {
-	case *Stage_Failure:
-		return st.Failure.Normalize()
-	case *Stage_Stall:
-		return st.Stall.Normalize()
-	case *Stage_Deps:
-		return st.Deps.Normalize()
-	}
-	return fmt.Errorf("empty stage")
-}
-
-// Normalize checks FailureStage for errors and converts it to its normalized
-// form.
-func (f *FailureStage) Normalize() error {
-	if f.Chance < 0 {
-		return fmt.Errorf("too small FailureStage chance")
-	}
-	if f.Chance > 1 {
-		return fmt.Errorf("too large FailureStage chance")
-	}
-	return nil
-}
-
-// Normalize checks StallStage for errors and converts it to its normalized form.
-func (s *StallStage) Normalize() error {
-	// nothing to do
-	return nil
-}
-
-// Normalize checks DepsStage for errors and converts it to its normalized form.
-func (d *DepsStage) Normalize() error {
-	for _, d := range d.Deps {
-		if err := d.Normalize(); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// Normalize checks Dependency for errors and converts it to its normalized form.
-func (d *Dependency) Normalize() error {
-	if d.Shards == 0 {
-		d.Shards = 1
-	}
-	if err := d.GetAttempts().Normalize(); err != nil {
-		return err
-	}
-	return d.Phrase.Normalize()
-}
-
-// Normalize checks SparseRange for errors and converts it to its normalized form.
-func (s *SparseRange) Normalize() error {
-	if len(s.Items) == 0 {
-		s.Items = []*RangeItem{{RangeItem: &RangeItem_Single{1}}}
-		return nil
-	}
-	current := uint32(0)
-	for _, itm := range s.Items {
-		switch i := itm.RangeItem.(type) {
-		case *RangeItem_Single:
-			if i.Single <= current {
-				return fmt.Errorf("malformed SparseRange")
-			}
-			current = i.Single
-		case *RangeItem_Range:
-			if err := i.Range.Normalize(); err != nil {
-				return err
-			}
-			if i.Range.Low <= current {
-				return fmt.Errorf("malformed SparseRange")
-			}
-			current = i.Range.High
-		default:
-			return fmt.Errorf("unknown SparseRange entry")
-		}
-	}
-	return nil
-}
-
-// Normalize checks Range for errors and converts it to its normalized form.
-func (r *Range) Normalize() error {
-	if r.High <= r.Low {
-		return fmt.Errorf("malformed Range")
-	}
-	return nil
-}
diff --git a/dm/api/distributor/jobsim/validate_test.go b/dm/api/distributor/jobsim/validate_test.go
deleted file mode 100644
index 1a70501..0000000
--- a/dm/api/distributor/jobsim/validate_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package jobsim
-
-import (
-	"fmt"
-	"testing"
-
-	"github.com/golang/protobuf/jsonpb"
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestNormalization(t *testing.T) {
-	positive := []struct {
-		Name string
-
-		Phrase string
-		Parsed *Phrase
-	}{
-		{
-			Name:   "FailureStage",
-			Phrase: `{"stages": [{"failure": {"chance": 0.75}}]}`,
-			Parsed: &Phrase{
-				Stages: []*Stage{{StageType: &Stage_Failure{&FailureStage{Chance: .75}}}},
-			},
-		},
-	}
-
-	bad := []struct {
-		Name string
-
-		Phrase   string
-		ParseErr interface{}
-		NormErr  interface{}
-	}{
-		{
-			Name:    "FailureStage",
-			Phrase:  `{"stages": [{"failure": {"chance": -2}}]}`,
-			NormErr: "too small FailureStage chance",
-		},
-	}
-
-	Convey("TestNormalization", t, func() {
-		for _, t := range positive {
-			Convey(fmt.Sprintf("good: %s", t.Name), func() {
-				p := Phrase{Name: "basic"}
-				So(jsonpb.UnmarshalString(t.Phrase, &p), ShouldBeNil)
-				So(p.Normalize(), ShouldBeNil)
-				if t.Parsed != nil {
-					So(t.Parsed, ShouldResemble, t.Parsed)
-				}
-			})
-		}
-
-		for _, t := range bad {
-			Convey(fmt.Sprintf("bad: %s", t.Name), func() {
-				p := Phrase{Name: "basic"}
-				So(jsonpb.UnmarshalString(t.Phrase, &p), ShouldErrLike, t.ParseErr)
-				So(p.Normalize(), ShouldErrLike, t.NormErr)
-			})
-		}
-	})
-}
diff --git a/dm/api/distributor/swarming/v1/cipd.go b/dm/api/distributor/swarming/v1/cipd.go
deleted file mode 100644
index 22c218a..0000000
--- a/dm/api/distributor/swarming/v1/cipd.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package swarmingV1
-
-import (
-	"sort"
-
-	swarm "go.chromium.org/luci/common/api/swarming/swarming/v1"
-)
-
-// ToCipdPackage converts this to a swarming api SwarmingRpcsCipdPackage.
-func (c *CipdPackage) ToCipdPackage() *swarm.SwarmingRpcsCipdPackage {
-	if c == nil {
-		return nil
-	}
-	return &swarm.SwarmingRpcsCipdPackage{PackageName: c.Name, Version: c.Version}
-}
-
-// ToCipdInput converts this to a swarming api SwarmingRpcsCipdInput.
-func (c *CipdSpec) ToCipdInput() *swarm.SwarmingRpcsCipdInput {
-	if c == nil || c.Client == nil && len(c.ByPath) == 0 {
-		return nil
-	}
-	ret := &swarm.SwarmingRpcsCipdInput{
-		ClientPackage: c.Client.ToCipdPackage(),
-	}
-	if len(c.ByPath) > 0 {
-		count := 0
-		paths := make(sort.StringSlice, 0, len(c.ByPath))
-		for path, pkgs := range c.ByPath {
-			paths = append(paths, path)
-			count += len(pkgs.Pkg)
-		}
-		ret.Packages = make([]*swarm.SwarmingRpcsCipdPackage, 0, count)
-		for _, path := range paths {
-			for _, pkg := range c.ByPath[path].Pkg {
-				retPkg := pkg.ToCipdPackage()
-				retPkg.Path = path
-				ret.Packages = append(ret.Packages, retPkg)
-			}
-		}
-	}
-	return ret
-}
diff --git a/dm/api/distributor/swarming/v1/cipd.pb.go b/dm/api/distributor/swarming/v1/cipd.pb.go
deleted file mode 100644
index a0c68ce..0000000
--- a/dm/api/distributor/swarming/v1/cipd.pb.go
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/swarming/v1/cipd.proto
-
-package swarmingV1
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type CipdPackage struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Name    string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
-}
-
-func (x *CipdPackage) Reset() {
-	*x = CipdPackage{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *CipdPackage) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CipdPackage) ProtoMessage() {}
-
-func (x *CipdPackage) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use CipdPackage.ProtoReflect.Descriptor instead.
-func (*CipdPackage) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *CipdPackage) GetName() string {
-	if x != nil {
-		return x.Name
-	}
-	return ""
-}
-
-func (x *CipdPackage) GetVersion() string {
-	if x != nil {
-		return x.Version
-	}
-	return ""
-}
-
-type CipdSpec struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Server to use for cipd packages. Required (though it may be specified
-	// by the quest's designated distributor config). This must be
-	// scheme://<hostname>, e.g. "https://example.appspot.com". The only
-	// supported schemes are http and https.
-	Server string `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"`
-	// Specifies the CIPD package to use for the job to obtain the actual CIPD
-	// client binary. You usually want to omit this.
-	Client *CipdPackage `protobuf:"bytes,2,opt,name=client,proto3" json:"client,omitempty"`
-	// A mapping from path-to-install to a list of cipd packages to install at
-	// that location. To install packages in the root of the job, use the path
-	// ''.
-	ByPath map[string]*CipdSpec_CipdPackages `protobuf:"bytes,3,rep,name=by_path,json=byPath,proto3" json:"by_path,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-}
-
-func (x *CipdSpec) Reset() {
-	*x = CipdSpec{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *CipdSpec) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CipdSpec) ProtoMessage() {}
-
-func (x *CipdSpec) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use CipdSpec.ProtoReflect.Descriptor instead.
-func (*CipdSpec) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescGZIP(), []int{1}
-}
-
-func (x *CipdSpec) GetServer() string {
-	if x != nil {
-		return x.Server
-	}
-	return ""
-}
-
-func (x *CipdSpec) GetClient() *CipdPackage {
-	if x != nil {
-		return x.Client
-	}
-	return nil
-}
-
-func (x *CipdSpec) GetByPath() map[string]*CipdSpec_CipdPackages {
-	if x != nil {
-		return x.ByPath
-	}
-	return nil
-}
-
-type CipdSpec_CipdPackages struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Pkg []*CipdPackage `protobuf:"bytes,1,rep,name=pkg,proto3" json:"pkg,omitempty"`
-}
-
-func (x *CipdSpec_CipdPackages) Reset() {
-	*x = CipdSpec_CipdPackages{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *CipdSpec_CipdPackages) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CipdSpec_CipdPackages) ProtoMessage() {}
-
-func (x *CipdSpec_CipdPackages) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use CipdSpec_CipdPackages.ProtoReflect.Descriptor instead.
-func (*CipdSpec_CipdPackages) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescGZIP(), []int{1, 0}
-}
-
-func (x *CipdSpec_CipdPackages) GetPkg() []*CipdPackage {
-	if x != nil {
-		return x.Pkg
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDesc = []byte{
-	0x0a, 0x3e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x69, 0x70, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x12, 0x0a, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x22, 0x3b, 0x0a, 0x0b,
-	0x43, 0x69, 0x70, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
-	0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x08, 0x43, 0x69,
-	0x70, 0x64, 0x53, 0x70, 0x65, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2f,
-	0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
-	0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e, 0x43, 0x69, 0x70, 0x64,
-	0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12,
-	0x39, 0x0a, 0x07, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x20, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e, 0x43, 0x69,
-	0x70, 0x64, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x45, 0x6e, 0x74,
-	0x72, 0x79, 0x52, 0x06, 0x62, 0x79, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x39, 0x0a, 0x0c, 0x43, 0x69,
-	0x70, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x03, 0x70, 0x6b,
-	0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x56, 0x31, 0x2e, 0x43, 0x69, 0x70, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
-	0x52, 0x03, 0x70, 0x6b, 0x67, 0x1a, 0x5c, 0x0a, 0x0b, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x45,
-	0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x56, 0x31, 0x2e, 0x43, 0x69, 0x70, 0x64, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x43, 0x69, 0x70, 0x64,
-	0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
-	0x02, 0x38, 0x01, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69,
-	0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61,
-	0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73,
-	0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x77, 0x61, 0x72, 0x6d,
-	0x69, 0x6e, 0x67, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_goTypes = []interface{}{
-	(*CipdPackage)(nil),           // 0: swarmingV1.CipdPackage
-	(*CipdSpec)(nil),              // 1: swarmingV1.CipdSpec
-	(*CipdSpec_CipdPackages)(nil), // 2: swarmingV1.CipdSpec.CipdPackages
-	nil,                           // 3: swarmingV1.CipdSpec.ByPathEntry
-}
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_depIdxs = []int32{
-	0, // 0: swarmingV1.CipdSpec.client:type_name -> swarmingV1.CipdPackage
-	3, // 1: swarmingV1.CipdSpec.by_path:type_name -> swarmingV1.CipdSpec.ByPathEntry
-	0, // 2: swarmingV1.CipdSpec.CipdPackages.pkg:type_name -> swarmingV1.CipdPackage
-	2, // 3: swarmingV1.CipdSpec.ByPathEntry.value:type_name -> swarmingV1.CipdSpec.CipdPackages
-	4, // [4:4] is the sub-list for method output_type
-	4, // [4:4] is the sub-list for method input_type
-	4, // [4:4] is the sub-list for extension type_name
-	4, // [4:4] is the sub-list for extension extendee
-	0, // [0:4] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CipdPackage); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CipdSpec); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CipdSpec_CipdPackages); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   4,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/swarming/v1/cipd.proto b/dm/api/distributor/swarming/v1/cipd.proto
deleted file mode 100644
index d80bb14..0000000
--- a/dm/api/distributor/swarming/v1/cipd.proto
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor/swarming/v1;swarmingV1";
-
-package swarmingV1;
-
-message CipdPackage {
-  string name = 1;
-  string version = 2;
-}
-
-message CipdSpec {
-  // Server to use for cipd packages. Required (though it may be specified
-  // by the quest's designated distributor config). This must be
-  // scheme://<hostname>, e.g. "https://example.appspot.com". The only
-  // supported schemes are http and https.
-  string server = 1;
-
-  // Specifies the CIPD package to use for the job to obtain the actual CIPD
-  // client binary. You usually want to omit this.
-  CipdPackage client = 2;
-
-  message CipdPackages {
-    repeated CipdPackage pkg = 1;
-  }
-  // A mapping from path-to-install to a list of cipd packages to install at
-  // that location. To install packages in the root of the job, use the path
-  // ''.
-  map<string, CipdPackages> by_path = 3;
-}
diff --git a/dm/api/distributor/swarming/v1/config.pb.go b/dm/api/distributor/swarming/v1/config.pb.go
deleted file mode 100644
index 4a0d5c1..0000000
--- a/dm/api/distributor/swarming/v1/config.pb.go
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/swarming/v1/config.proto
-
-package swarmingV1
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	durationpb "google.golang.org/protobuf/types/known/durationpb"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type Config struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Swarming *Config_Swarming `protobuf:"bytes,1,opt,name=swarming,proto3" json:"swarming,omitempty"`
-	Isolate  *Config_Isolate  `protobuf:"bytes,2,opt,name=isolate,proto3" json:"isolate,omitempty"`
-}
-
-func (x *Config) Reset() {
-	*x = Config{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Config) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Config) ProtoMessage() {}
-
-func (x *Config) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Config.ProtoReflect.Descriptor instead.
-func (*Config) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Config) GetSwarming() *Config_Swarming {
-	if x != nil {
-		return x.Swarming
-	}
-	return nil
-}
-
-func (x *Config) GetIsolate() *Config_Isolate {
-	if x != nil {
-		return x.Isolate
-	}
-	return nil
-}
-
-type Config_Swarming struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
-}
-
-func (x *Config_Swarming) Reset() {
-	*x = Config_Swarming{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Config_Swarming) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Config_Swarming) ProtoMessage() {}
-
-func (x *Config_Swarming) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Config_Swarming.ProtoReflect.Descriptor instead.
-func (*Config_Swarming) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescGZIP(), []int{0, 0}
-}
-
-func (x *Config_Swarming) GetUrl() string {
-	if x != nil {
-		return x.Url
-	}
-	return ""
-}
-
-type Config_Isolate struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// The host of the isolate service, e.g. isolateserver.appspot.com.
-	Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
-	// The default assumed expiration period for execution results.
-	Expiration *durationpb.Duration `protobuf:"bytes,2,opt,name=expiration,proto3" json:"expiration,omitempty"`
-}
-
-func (x *Config_Isolate) Reset() {
-	*x = Config_Isolate{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Config_Isolate) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Config_Isolate) ProtoMessage() {}
-
-func (x *Config_Isolate) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Config_Isolate.ProtoReflect.Descriptor instead.
-func (*Config_Isolate) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescGZIP(), []int{0, 1}
-}
-
-func (x *Config_Isolate) GetUrl() string {
-	if x != nil {
-		return x.Url
-	}
-	return ""
-}
-
-func (x *Config_Isolate) GetExpiration() *durationpb.Duration {
-	if x != nil {
-		return x.Expiration
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDesc = []byte{
-	0x0a, 0x40, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x12, 0x0a, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x1a, 0x1e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
-	0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xed,
-	0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x0a, 0x08, 0x73, 0x77, 0x61,
-	0x72, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x77,
-	0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
-	0x53, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x12, 0x34, 0x0a, 0x07, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31,
-	0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x52,
-	0x07, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x1a, 0x1c, 0x0a, 0x08, 0x53, 0x77, 0x61, 0x72,
-	0x6d, 0x69, 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x1a, 0x56, 0x0a, 0x07, 0x49, 0x73, 0x6f, 0x6c, 0x61, 0x74,
-	0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x75, 0x72, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x40,
-	0x5a, 0x3e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31,
-	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_goTypes = []interface{}{
-	(*Config)(nil),              // 0: swarmingV1.Config
-	(*Config_Swarming)(nil),     // 1: swarmingV1.Config.Swarming
-	(*Config_Isolate)(nil),      // 2: swarmingV1.Config.Isolate
-	(*durationpb.Duration)(nil), // 3: google.protobuf.Duration
-}
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_depIdxs = []int32{
-	1, // 0: swarmingV1.Config.swarming:type_name -> swarmingV1.Config.Swarming
-	2, // 1: swarmingV1.Config.isolate:type_name -> swarmingV1.Config.Isolate
-	3, // 2: swarmingV1.Config.Isolate.expiration:type_name -> google.protobuf.Duration
-	3, // [3:3] is the sub-list for method output_type
-	3, // [3:3] is the sub-list for method input_type
-	3, // [3:3] is the sub-list for extension type_name
-	3, // [3:3] is the sub-list for extension extendee
-	0, // [0:3] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Config); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Config_Swarming); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Config_Isolate); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   3,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_config_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/swarming/v1/config.proto b/dm/api/distributor/swarming/v1/config.proto
deleted file mode 100644
index 6ff28d2..0000000
--- a/dm/api/distributor/swarming/v1/config.proto
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor/swarming/v1;swarmingV1";
-
-import "google/protobuf/duration.proto";
-
-package swarmingV1;
-
-message Config {
-  message Swarming {
-    string url = 1;
-  }
-  Swarming swarming = 1;
-
-  message Isolate {
-    // The host of the isolate service, e.g. isolateserver.appspot.com.
-    string url = 1;
-
-    // The default assumed expiration period for execution results.
-    google.protobuf.Duration expiration = 2;
-  }
-  Isolate isolate = 2;
-}
diff --git a/dm/api/distributor/swarming/v1/gen.go b/dm/api/distributor/swarming/v1/gen.go
deleted file mode 100644
index 796a5bb..0000000
--- a/dm/api/distributor/swarming/v1/gen.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//go:generate cproto
-
-package swarmingV1
diff --git a/dm/api/distributor/swarming/v1/isolate_ref.pb.go b/dm/api/distributor/swarming/v1/isolate_ref.pb.go
deleted file mode 100644
index d0b556b..0000000
--- a/dm/api/distributor/swarming/v1/isolate_ref.pb.go
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/swarming/v1/isolate_ref.proto
-
-package swarmingV1
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type IsolatedRef struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Id     string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Server string `protobuf:"bytes,2,opt,name=server,proto3" json:"server,omitempty"`
-}
-
-func (x *IsolatedRef) Reset() {
-	*x = IsolatedRef{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *IsolatedRef) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*IsolatedRef) ProtoMessage() {}
-
-func (x *IsolatedRef) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use IsolatedRef.ProtoReflect.Descriptor instead.
-func (*IsolatedRef) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *IsolatedRef) GetId() string {
-	if x != nil {
-		return x.Id
-	}
-	return ""
-}
-
-func (x *IsolatedRef) GetServer() string {
-	if x != nil {
-		return x.Server
-	}
-	return ""
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDesc = []byte{
-	0x0a, 0x45, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x65,
-	0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e,
-	0x67, 0x56, 0x31, 0x22, 0x35, 0x0a, 0x0b, 0x49, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x52,
-	0x65, 0x66, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
-	0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x6f,
-	0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75,
-	0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69,
-	0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x2f, 0x76,
-	0x31, 0x3b, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_goTypes = []interface{}{
-	(*IsolatedRef)(nil), // 0: swarmingV1.IsolatedRef
-}
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_depIdxs = []int32{
-	0, // [0:0] is the sub-list for method output_type
-	0, // [0:0] is the sub-list for method input_type
-	0, // [0:0] is the sub-list for extension type_name
-	0, // [0:0] is the sub-list for extension extendee
-	0, // [0:0] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*IsolatedRef); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   1,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/swarming/v1/isolate_ref.proto b/dm/api/distributor/swarming/v1/isolate_ref.proto
deleted file mode 100644
index 0bafff4..0000000
--- a/dm/api/distributor/swarming/v1/isolate_ref.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor/swarming/v1;swarmingV1";
-
-package swarmingV1;
-
-message IsolatedRef {
-  string id = 1;
-  string server = 2;
-}
diff --git a/dm/api/distributor/swarming/v1/normalize.go b/dm/api/distributor/swarming/v1/normalize.go
deleted file mode 100644
index 102d463..0000000
--- a/dm/api/distributor/swarming/v1/normalize.go
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package swarmingV1
-
-import (
-	"errors"
-	"fmt"
-	"net/url"
-	"strings"
-	"unicode"
-)
-
-// DefaultSwarmingPriority is the priority used if
-// Parameters.scheduling.priority == 0.
-const DefaultSwarmingPriority = 100
-
-// Normalize normalizes and checks for input violations.
-func (p *Parameters) Normalize() (err error) {
-	if err = p.Scheduling.Normalize(); err != nil {
-		return
-	}
-	if err = p.Meta.Normalize(); err != nil {
-		return
-	}
-	if err = p.Job.Normalize(); err != nil {
-		return
-	}
-	return
-}
-
-// Normalize normalizes and checks for input violations.
-func (s *Parameters_Scheduling) Normalize() (err error) {
-	if s.Priority > 255 {
-		return errors.New("scheduling.priority > 256")
-	}
-	// Priority == 0 means default.
-	if s.Priority == 0 {
-		s.Priority = DefaultSwarmingPriority
-	}
-	for k, v := range s.Dimensions {
-		if k == "" {
-			return errors.New("scheduling.dimensions: empty dimension key")
-		}
-		if v == "" {
-			return fmt.Errorf("scheduling.dimensions: dimension key %q with empty value", k)
-		}
-	}
-	if s.IoTimeout.AsDuration() < 0 {
-		return errors.New("scheduling.io_timeout: negative timeout not allowed")
-	}
-	return
-}
-
-// Normalize normalizes and checks for input violations.
-func (m *Parameters_Meta) Normalize() (err error) {
-	return
-}
-
-// Normalize normalizes and checks for input violations.
-func (j *Parameters_Job) Normalize() (err error) {
-	if err = j.Inputs.Normalize(); err != nil {
-		return
-	}
-	if len(j.Command) == 0 {
-		return errors.New("job.command: command is required")
-	}
-	for k := range j.Env {
-		if k == "" {
-			return errors.New("job.env: environment key is empty")
-		}
-	}
-	return
-}
-
-// Normalize normalizes and checks for input violations.
-func (p *CipdPackage) Normalize() error {
-	if p.Name == "" {
-		return errors.New("missing name")
-	}
-	if p.Version == "" {
-		return errors.New("missing version")
-	}
-	return nil
-}
-
-// Normalize normalizes and checks for input violations.
-func (c *CipdSpec) Normalize() error {
-	if err := schemaHostURLValidate(c.Server); err != nil {
-		return fmt.Errorf("job.inputs.cipd.server: %s", err)
-	}
-	if c.Client != nil {
-		if err := c.Client.Normalize(); err != nil {
-			return fmt.Errorf("job.inputs.cipd.client: %s", err)
-		}
-	}
-	for path, pkgs := range c.ByPath {
-		for i, p := range pkgs.Pkg {
-			if err := p.Normalize(); err != nil {
-				return fmt.Errorf("job.inputs.cipd.by_path[%s].pkg[%d]: %s", path, i, err)
-			}
-		}
-	}
-	return nil
-}
-
-// Normalize normalizes and checks for input violations.
-func (i *Parameters_Job_Inputs) Normalize() (err error) {
-	if i.Cipd == nil && len(i.Isolated) == 0 {
-		return errors.New(
-			"job.inputs: at least one of packages and isolated must be specified")
-	}
-	if i.Cipd != nil {
-		if err = i.Cipd.Normalize(); err != nil {
-			return
-		}
-	}
-	return
-}
-
-func schemaHostURLValidate(uStr string) error {
-	if uStr == "" {
-		return errors.New("required")
-	}
-	if strings.IndexFunc(uStr, unicode.IsUpper) != -1 {
-		return errors.New("must be lower-case")
-	}
-	u, err := url.Parse(uStr)
-	if err != nil {
-		return fmt.Errorf("invalid url: %s", err)
-	}
-	if u.Scheme != "http" && u.Scheme != "https" {
-		return fmt.Errorf("unsupported scheme: %s", u.Scheme)
-	}
-	if fmt.Sprintf("%s://%s", u.Scheme, u.Host) != uStr {
-		return fmt.Errorf("unsupported url: %s", uStr)
-	}
-	return nil
-}
-
-// Normalize normalizes and checks for input violations.
-func (c *Config) Normalize() (err error) {
-	if err = c.Swarming.Normalize(); err != nil {
-		return
-	}
-	if err = c.Isolate.Normalize(); err != nil {
-		return
-	}
-	return
-}
-
-// Normalize normalizes and checks for input violations.
-func (s *Config_Swarming) Normalize() (err error) {
-	if err = schemaHostURLValidate(s.Url); err != nil {
-		return fmt.Errorf("config.swarming.host: %s", err)
-	}
-	return
-}
-
-// Normalize normalizes and checks for input violations.
-func (i *Config_Isolate) Normalize() (err error) {
-	if err = schemaHostURLValidate(i.Url); err != nil {
-		return fmt.Errorf("config.isolate.host: %s", err)
-	}
-	return
-}
diff --git a/dm/api/distributor/swarming/v1/params.pb.go b/dm/api/distributor/swarming/v1/params.pb.go
deleted file mode 100644
index 5d03314..0000000
--- a/dm/api/distributor/swarming/v1/params.pb.go
+++ /dev/null
@@ -1,593 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/swarming/v1/params.proto
-
-package swarmingV1
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	durationpb "google.golang.org/protobuf/types/known/durationpb"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// Parameters represents the set of swarming parameters that the Swarming v1
-// distributor can interpret for use with a Swarming v1 compatible service.
-type Parameters struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Scheduling *Parameters_Scheduling `protobuf:"bytes,1,opt,name=scheduling,proto3" json:"scheduling,omitempty"`
-	Meta       *Parameters_Meta       `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"`
-	Job        *Parameters_Job        `protobuf:"bytes,3,opt,name=job,proto3" json:"job,omitempty"`
-}
-
-func (x *Parameters) Reset() {
-	*x = Parameters{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Parameters) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Parameters) ProtoMessage() {}
-
-func (x *Parameters) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Parameters.ProtoReflect.Descriptor instead.
-func (*Parameters) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Parameters) GetScheduling() *Parameters_Scheduling {
-	if x != nil {
-		return x.Scheduling
-	}
-	return nil
-}
-
-func (x *Parameters) GetMeta() *Parameters_Meta {
-	if x != nil {
-		return x.Meta
-	}
-	return nil
-}
-
-func (x *Parameters) GetJob() *Parameters_Job {
-	if x != nil {
-		return x.Job
-	}
-	return nil
-}
-
-// These parameters affect how the Executions for this Quest are scheduled.
-type Parameters_Scheduling struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Priority adjusts the scheduling preference for Executions. The higher the
-	// priority number, the longer it will take to schedule, and vice versa (ala
-	// `nice`).
-	//
-	// A value of 0 (default) corresponds to a default priority (currently 100).
-	// Other values correspond directly to the swarming task Priority.
-	//
-	// THIS MEANS THAT PRIORITY 0 IS NOT PERMITTED HERE! If you want 0, use
-	// 1 instead.
-	//
-	// This must be <= 255.
-	Priority uint32 `protobuf:"varint,1,opt,name=priority,proto3" json:"priority,omitempty"`
-	// These specifiy the profile of the machine to use for Execuions of this
-	// quest. These can indicate OS, number of cores, amount of ram, GPU type,
-	// pool, etc. See the swarming service instance for available dimensions.
-	Dimensions map[string]string `protobuf:"bytes,2,rep,name=dimensions,proto3" json:"dimensions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	// These dimensions will be snapshotted from the first execution of each
-	// attempt, and will be subsequently re-used for all following executions of
-	// that attempt.
-	//
-	// The most-specific value for these dimensions will be taken for tasks
-	// where a given dimension has multiple values.
-	SnapshotDimensions []string `protobuf:"bytes,3,rep,name=snapshot_dimensions,json=snapshotDimensions,proto3" json:"snapshot_dimensions,omitempty"`
-	// This indicates the maximum amount of time that an Execution may run
-	// without emitting IO on stdout/err. 0 means 'no timeout'.
-	IoTimeout *durationpb.Duration `protobuf:"bytes,4,opt,name=io_timeout,json=ioTimeout,proto3" json:"io_timeout,omitempty"`
-}
-
-func (x *Parameters_Scheduling) Reset() {
-	*x = Parameters_Scheduling{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Parameters_Scheduling) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Parameters_Scheduling) ProtoMessage() {}
-
-func (x *Parameters_Scheduling) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Parameters_Scheduling.ProtoReflect.Descriptor instead.
-func (*Parameters_Scheduling) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescGZIP(), []int{0, 0}
-}
-
-func (x *Parameters_Scheduling) GetPriority() uint32 {
-	if x != nil {
-		return x.Priority
-	}
-	return 0
-}
-
-func (x *Parameters_Scheduling) GetDimensions() map[string]string {
-	if x != nil {
-		return x.Dimensions
-	}
-	return nil
-}
-
-func (x *Parameters_Scheduling) GetSnapshotDimensions() []string {
-	if x != nil {
-		return x.SnapshotDimensions
-	}
-	return nil
-}
-
-func (x *Parameters_Scheduling) GetIoTimeout() *durationpb.Duration {
-	if x != nil {
-		return x.IoTimeout
-	}
-	return nil
-}
-
-type Parameters_Meta struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// The 'human readable' name prefix for Executions of this quest. DM will
-	// automatically prepend this to the execution ID. So if this was "cool
-	// job", the swarming task name would be
-	//   "cool job / <quest_ID>|<attempt>|<execution>"
-	NamePrefix string `protobuf:"bytes,1,opt,name=name_prefix,json=namePrefix,proto3" json:"name_prefix,omitempty"`
-}
-
-func (x *Parameters_Meta) Reset() {
-	*x = Parameters_Meta{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Parameters_Meta) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Parameters_Meta) ProtoMessage() {}
-
-func (x *Parameters_Meta) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Parameters_Meta.ProtoReflect.Descriptor instead.
-func (*Parameters_Meta) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescGZIP(), []int{0, 1}
-}
-
-func (x *Parameters_Meta) GetNamePrefix() string {
-	if x != nil {
-		return x.NamePrefix
-	}
-	return ""
-}
-
-type Parameters_Job struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Inputs *Parameters_Job_Inputs `protobuf:"bytes,1,opt,name=inputs,proto3" json:"inputs,omitempty"`
-	// This is the "argv" to run with this job. This includes substitution
-	// paramters defined by swarming's run_isolated.py script:
-	//   https://github.com/luci/luci-py/blob/master/client/run_isolated.py
-	//
-	// Additionally, DM provides the following substitutions:
-	//   ${DM.PREVIOUS.EXECUTION.STATE:PATH} - the path to a JSONPB encoding of
-	//     the swarming_v1.Result from the previous Execution of this Attempt.
-	//   ${DM.QUEST.DATA.DESC:PATH} - the path to the
-	//     dm.Quest.Data.Desc JSONPB for the quest that this execution is part
-	//     of.
-	//   ${DM.HOST} - the hostname to use to access DM's pRPC API.
-	//
-	// DM also provides a JSONPB encoded dm.Execution.Auth via the LUCI_CONTEXT
-	// swarming.secret_bytes value. See:
-	//   https://github.com/luci/luci-py/blob/master/client/LUCI_CONTEXT.md
-	//
-	// Command MUST be specified; specifying a command in any of the isolated
-	// inputs WILL NOT DO ANYTHING.
-	Command []string `protobuf:"bytes,2,rep,name=command,proto3" json:"command,omitempty"`
-	// Environment variables for the executions.
-	Env map[string]string `protobuf:"bytes,3,rep,name=env,proto3" json:"env,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-}
-
-func (x *Parameters_Job) Reset() {
-	*x = Parameters_Job{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[3]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Parameters_Job) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Parameters_Job) ProtoMessage() {}
-
-func (x *Parameters_Job) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[3]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Parameters_Job.ProtoReflect.Descriptor instead.
-func (*Parameters_Job) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescGZIP(), []int{0, 2}
-}
-
-func (x *Parameters_Job) GetInputs() *Parameters_Job_Inputs {
-	if x != nil {
-		return x.Inputs
-	}
-	return nil
-}
-
-func (x *Parameters_Job) GetCommand() []string {
-	if x != nil {
-		return x.Command
-	}
-	return nil
-}
-
-func (x *Parameters_Job) GetEnv() map[string]string {
-	if x != nil {
-		return x.Env
-	}
-	return nil
-}
-
-type Parameters_Job_Inputs struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// 0 or more isolated IDs that will be 'included' together into the final
-	// job .isolated sent to swarming.
-	//
-	// The "server" value must either be omitted, or equal the isolate server
-	// defined by this distributor's config (the `isolate.host` field,
-	// prepended with "https://").
-	Isolated []*IsolatedRef `protobuf:"bytes,1,rep,name=isolated,proto3" json:"isolated,omitempty"`
-	// CIPD packages to use for the job. These specs may contain templated
-	// parameters for package names or non-instance_ids for the package
-	// versions. The first successful execution for each attempt will
-	// resolve+snapshot all package names and versions. These package names
-	// and versions will be used for all subsequent executions of that
-	// attempt.
-	Cipd *CipdSpec `protobuf:"bytes,2,opt,name=cipd,proto3" json:"cipd,omitempty"`
-}
-
-func (x *Parameters_Job_Inputs) Reset() {
-	*x = Parameters_Job_Inputs{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[5]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Parameters_Job_Inputs) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Parameters_Job_Inputs) ProtoMessage() {}
-
-func (x *Parameters_Job_Inputs) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[5]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Parameters_Job_Inputs.ProtoReflect.Descriptor instead.
-func (*Parameters_Job_Inputs) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescGZIP(), []int{0, 2, 0}
-}
-
-func (x *Parameters_Job_Inputs) GetIsolated() []*IsolatedRef {
-	if x != nil {
-		return x.Isolated
-	}
-	return nil
-}
-
-func (x *Parameters_Job_Inputs) GetCipd() *CipdSpec {
-	if x != nil {
-		return x.Cipd
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDesc = []byte{
-	0x0a, 0x40, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x12, 0x0a, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x1a, 0x1e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
-	0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3e,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74,
-	0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x2f, 0x76, 0x31, 0x2f, 0x63, 0x69, 0x70, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x45,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74,
-	0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x2f, 0x76, 0x31, 0x2f, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb4, 0x06, 0x0a, 0x0a, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65,
-	0x74, 0x65, 0x72, 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69,
-	0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d,
-	0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73,
-	0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x0a, 0x73, 0x63, 0x68,
-	0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x56, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x4d, 0x65,
-	0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x56, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x4a, 0x6f,
-	0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x1a, 0xa5, 0x02, 0x0a, 0x0a, 0x53, 0x63, 0x68, 0x65, 0x64,
-	0x75, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
-	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
-	0x79, 0x12, 0x51, 0x0a, 0x0a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18,
-	0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x56, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x53, 0x63,
-	0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69,
-	0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73,
-	0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
-	0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
-	0x09, 0x52, 0x12, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x44, 0x69, 0x6d, 0x65, 0x6e,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x38, 0x0a, 0x0a, 0x69, 0x6f, 0x5f, 0x74, 0x69, 0x6d, 0x65,
-	0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x69, 0x6f, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x1a,
-	0x3d, 0x0a, 0x0f, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74,
-	0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x27,
-	0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70,
-	0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x61, 0x6d,
-	0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x1a, 0xb2, 0x02, 0x0a, 0x03, 0x4a, 0x6f, 0x62, 0x12,
-	0x39, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x21, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e, 0x50, 0x61, 0x72,
-	0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x2e, 0x49, 0x6e, 0x70, 0x75,
-	0x74, 0x73, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x12, 0x35, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x03, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x23, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e, 0x50,
-	0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x2e, 0x45, 0x6e,
-	0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x1a, 0x67, 0x0a, 0x06, 0x49,
-	0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x33, 0x0a, 0x08, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65,
-	0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x56, 0x31, 0x2e, 0x49, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x66,
-	0x52, 0x08, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x63, 0x69,
-	0x70, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d,
-	0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e, 0x43, 0x69, 0x70, 0x64, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04,
-	0x63, 0x69, 0x70, 0x64, 0x1a, 0x36, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x40, 0x5a, 0x3e,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74,
-	0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x2f, 0x76, 0x31, 0x3b, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x62, 0x06,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_goTypes = []interface{}{
-	(*Parameters)(nil),            // 0: swarmingV1.Parameters
-	(*Parameters_Scheduling)(nil), // 1: swarmingV1.Parameters.Scheduling
-	(*Parameters_Meta)(nil),       // 2: swarmingV1.Parameters.Meta
-	(*Parameters_Job)(nil),        // 3: swarmingV1.Parameters.Job
-	nil,                           // 4: swarmingV1.Parameters.Scheduling.DimensionsEntry
-	(*Parameters_Job_Inputs)(nil), // 5: swarmingV1.Parameters.Job.Inputs
-	nil,                           // 6: swarmingV1.Parameters.Job.EnvEntry
-	(*durationpb.Duration)(nil),   // 7: google.protobuf.Duration
-	(*IsolatedRef)(nil),           // 8: swarmingV1.IsolatedRef
-	(*CipdSpec)(nil),              // 9: swarmingV1.CipdSpec
-}
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_depIdxs = []int32{
-	1, // 0: swarmingV1.Parameters.scheduling:type_name -> swarmingV1.Parameters.Scheduling
-	2, // 1: swarmingV1.Parameters.meta:type_name -> swarmingV1.Parameters.Meta
-	3, // 2: swarmingV1.Parameters.job:type_name -> swarmingV1.Parameters.Job
-	4, // 3: swarmingV1.Parameters.Scheduling.dimensions:type_name -> swarmingV1.Parameters.Scheduling.DimensionsEntry
-	7, // 4: swarmingV1.Parameters.Scheduling.io_timeout:type_name -> google.protobuf.Duration
-	5, // 5: swarmingV1.Parameters.Job.inputs:type_name -> swarmingV1.Parameters.Job.Inputs
-	6, // 6: swarmingV1.Parameters.Job.env:type_name -> swarmingV1.Parameters.Job.EnvEntry
-	8, // 7: swarmingV1.Parameters.Job.Inputs.isolated:type_name -> swarmingV1.IsolatedRef
-	9, // 8: swarmingV1.Parameters.Job.Inputs.cipd:type_name -> swarmingV1.CipdSpec
-	9, // [9:9] is the sub-list for method output_type
-	9, // [9:9] is the sub-list for method input_type
-	9, // [9:9] is the sub-list for extension type_name
-	9, // [9:9] is the sub-list for extension extendee
-	0, // [0:9] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_init()
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_init()
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Parameters); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Parameters_Scheduling); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Parameters_Meta); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Parameters_Job); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Parameters_Job_Inputs); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   7,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_params_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/swarming/v1/params.proto b/dm/api/distributor/swarming/v1/params.proto
deleted file mode 100644
index 692d521..0000000
--- a/dm/api/distributor/swarming/v1/params.proto
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor/swarming/v1;swarmingV1";
-
-import "google/protobuf/duration.proto";
-
-import "go.chromium.org/luci/dm/api/distributor/swarming/v1/cipd.proto";
-import "go.chromium.org/luci/dm/api/distributor/swarming/v1/isolate_ref.proto";
-
-package swarmingV1;
-
-// Parameters represents the set of swarming parameters that the Swarming v1
-// distributor can interpret for use with a Swarming v1 compatible service.
-message Parameters {
-  // These parameters affect how the Executions for this Quest are scheduled.
-  message Scheduling {
-    // Priority adjusts the scheduling preference for Executions. The higher the
-    // priority number, the longer it will take to schedule, and vice versa (ala
-    // `nice`).
-    //
-    // A value of 0 (default) corresponds to a default priority (currently 100).
-    // Other values correspond directly to the swarming task Priority.
-    //
-    // THIS MEANS THAT PRIORITY 0 IS NOT PERMITTED HERE! If you want 0, use
-    // 1 instead.
-    //
-    // This must be <= 255.
-    uint32 priority = 1;
-
-    // These specifiy the profile of the machine to use for Execuions of this
-    // quest. These can indicate OS, number of cores, amount of ram, GPU type,
-    // pool, etc. See the swarming service instance for available dimensions.
-    map<string, string> dimensions = 2;
-
-    // These dimensions will be snapshotted from the first execution of each
-    // attempt, and will be subsequently re-used for all following executions of
-    // that attempt.
-    //
-    // The most-specific value for these dimensions will be taken for tasks
-    // where a given dimension has multiple values.
-    repeated string snapshot_dimensions = 3;
-
-    // This indicates the maximum amount of time that an Execution may run
-    // without emitting IO on stdout/err. 0 means 'no timeout'.
-    google.protobuf.Duration io_timeout = 4;
-  }
-  Scheduling scheduling = 1;
-
-  message Meta {
-    // The 'human readable' name prefix for Executions of this quest. DM will
-    // automatically prepend this to the execution ID. So if this was "cool
-    // job", the swarming task name would be
-    //   "cool job / <quest_ID>|<attempt>|<execution>"
-    string name_prefix = 1;
-  }
-  Meta meta = 2;
-
-  message Job {
-    message Inputs {
-      // 0 or more isolated IDs that will be 'included' together into the final
-      // job .isolated sent to swarming.
-      //
-      // The "server" value must either be omitted, or equal the isolate server
-      // defined by this distributor's config (the `isolate.host` field,
-      // prepended with "https://").
-      repeated swarmingV1.IsolatedRef isolated = 1;
-
-      // CIPD packages to use for the job. These specs may contain templated
-      // parameters for package names or non-instance_ids for the package
-      // versions. The first successful execution for each attempt will
-      // resolve+snapshot all package names and versions. These package names
-      // and versions will be used for all subsequent executions of that
-      // attempt.
-      swarmingV1.CipdSpec cipd = 2;
-    }
-    Inputs inputs = 1;
-
-    // This is the "argv" to run with this job. This includes substitution
-    // paramters defined by swarming's run_isolated.py script:
-    //   https://github.com/luci/luci-py/blob/master/client/run_isolated.py
-    //
-    // Additionally, DM provides the following substitutions:
-    //   ${DM.PREVIOUS.EXECUTION.STATE:PATH} - the path to a JSONPB encoding of
-    //     the swarming_v1.Result from the previous Execution of this Attempt.
-    //   ${DM.QUEST.DATA.DESC:PATH} - the path to the
-    //     dm.Quest.Data.Desc JSONPB for the quest that this execution is part
-    //     of.
-    //   ${DM.HOST} - the hostname to use to access DM's pRPC API.
-    //
-    // DM also provides a JSONPB encoded dm.Execution.Auth via the LUCI_CONTEXT
-    // swarming.secret_bytes value. See:
-    //   https://github.com/luci/luci-py/blob/master/client/LUCI_CONTEXT.md
-    //
-    // Command MUST be specified; specifying a command in any of the isolated
-    // inputs WILL NOT DO ANYTHING.
-    repeated string command = 2;
-
-    // Environment variables for the executions.
-    map<string, string> env = 3;
-  }
-  Job job = 3;
-}
diff --git a/dm/api/distributor/swarming/v1/result.pb.go b/dm/api/distributor/swarming/v1/result.pb.go
deleted file mode 100644
index 9c92e13..0000000
--- a/dm/api/distributor/swarming/v1/result.pb.go
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/distributor/swarming/v1/result.proto
-
-package swarmingV1
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// This is the swarming-specific result for Executions run via swarming.
-type Result struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	ExitCode int64 `protobuf:"varint,1,opt,name=exit_code,json=exitCode,proto3" json:"exit_code,omitempty"`
-	// The isolated hash of the output directory
-	IsolatedOutdir *IsolatedRef `protobuf:"bytes,2,opt,name=isolated_outdir,json=isolatedOutdir,proto3" json:"isolated_outdir,omitempty"`
-	// The pinned cipd packages that this task actually used.
-	CipdPins *CipdSpec `protobuf:"bytes,3,opt,name=cipd_pins,json=cipdPins,proto3" json:"cipd_pins,omitempty"`
-	// The captured snapshot dimensions that the bot actually had.
-	SnapshotDimensions map[string]string `protobuf:"bytes,4,rep,name=snapshot_dimensions,json=snapshotDimensions,proto3" json:"snapshot_dimensions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-}
-
-func (x *Result) Reset() {
-	*x = Result{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Result) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Result) ProtoMessage() {}
-
-func (x *Result) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Result.ProtoReflect.Descriptor instead.
-func (*Result) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *Result) GetExitCode() int64 {
-	if x != nil {
-		return x.ExitCode
-	}
-	return 0
-}
-
-func (x *Result) GetIsolatedOutdir() *IsolatedRef {
-	if x != nil {
-		return x.IsolatedOutdir
-	}
-	return nil
-}
-
-func (x *Result) GetCipdPins() *CipdSpec {
-	if x != nil {
-		return x.CipdPins
-	}
-	return nil
-}
-
-func (x *Result) GetSnapshotDimensions() map[string]string {
-	if x != nil {
-		return x.SnapshotDimensions
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDesc = []byte{
-	0x0a, 0x40, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69,
-	0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69,
-	0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x12, 0x0a, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x1a, 0x3e,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74,
-	0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x2f, 0x76, 0x31, 0x2f, 0x63, 0x69, 0x70, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x45,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74,
-	0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67,
-	0x2f, 0x76, 0x31, 0x2f, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbe, 0x02, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
-	0x12, 0x1b, 0x0a, 0x09, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x03, 0x52, 0x08, 0x65, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x40, 0x0a,
-	0x0f, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x64, 0x69, 0x72,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e,
-	0x67, 0x56, 0x31, 0x2e, 0x49, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x66, 0x52,
-	0x0e, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x64, 0x69, 0x72, 0x12,
-	0x31, 0x0a, 0x09, 0x63, 0x69, 0x70, 0x64, 0x5f, 0x70, 0x69, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e,
-	0x43, 0x69, 0x70, 0x64, 0x53, 0x70, 0x65, 0x63, 0x52, 0x08, 0x63, 0x69, 0x70, 0x64, 0x50, 0x69,
-	0x6e, 0x73, 0x12, 0x5b, 0x0a, 0x13, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x64,
-	0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x2a, 0x2e, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x2e, 0x52, 0x65, 0x73,
-	0x75, 0x6c, 0x74, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x44, 0x69, 0x6d, 0x65,
-	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x73, 0x6e, 0x61,
-	0x70, 0x73, 0x68, 0x6f, 0x74, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a,
-	0x45, 0x0a, 0x17, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x44, 0x69, 0x6d, 0x65, 0x6e,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
-	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
-	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
-	0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72,
-	0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64,
-	0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f,
-	0x72, 0x2f, 0x73, 0x77, 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x77,
-	0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDescData = file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_goTypes = []interface{}{
-	(*Result)(nil),      // 0: swarmingV1.Result
-	nil,                 // 1: swarmingV1.Result.SnapshotDimensionsEntry
-	(*IsolatedRef)(nil), // 2: swarmingV1.IsolatedRef
-	(*CipdSpec)(nil),    // 3: swarmingV1.CipdSpec
-}
-var file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_depIdxs = []int32{
-	2, // 0: swarmingV1.Result.isolated_outdir:type_name -> swarmingV1.IsolatedRef
-	3, // 1: swarmingV1.Result.cipd_pins:type_name -> swarmingV1.CipdSpec
-	1, // 2: swarmingV1.Result.snapshot_dimensions:type_name -> swarmingV1.Result.SnapshotDimensionsEntry
-	3, // [3:3] is the sub-list for method output_type
-	3, // [3:3] is the sub-list for method input_type
-	3, // [3:3] is the sub-list for extension type_name
-	3, // [3:3] is the sub-list for extension extendee
-	0, // [0:3] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_init() }
-func file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_init() {
-	if File_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_cipd_proto_init()
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_isolate_ref_proto_init()
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Result); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   2,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto = out.File
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_distributor_swarming_v1_result_proto_depIdxs = nil
-}
diff --git a/dm/api/distributor/swarming/v1/result.proto b/dm/api/distributor/swarming/v1/result.proto
deleted file mode 100644
index 7019247..0000000
--- a/dm/api/distributor/swarming/v1/result.proto
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/distributor/swarming/v1;swarmingV1";
-
-import "go.chromium.org/luci/dm/api/distributor/swarming/v1/cipd.proto";
-import "go.chromium.org/luci/dm/api/distributor/swarming/v1/isolate_ref.proto";
-
-package swarmingV1;
-
-// This is the swarming-specific result for Executions run via swarming.
-message Result {
-  int64 exit_code = 1;
-
-  // The isolated hash of the output directory
-  swarmingV1.IsolatedRef isolated_outdir = 2;
-
-  // The pinned cipd packages that this task actually used.
-  swarmingV1.CipdSpec cipd_pins = 3;
-
-  // The captured snapshot dimensions that the bot actually had.
-  map<string, string> snapshot_dimensions = 4;
-}
diff --git a/dm/api/service/v1/activate_execution.pb.go b/dm/api/service/v1/activate_execution.pb.go
deleted file mode 100644
index 02ed9d3..0000000
--- a/dm/api/service/v1/activate_execution.pb.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/service/v1/activate_execution.proto
-
-package dm
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// ActivateExecutionReq allows a currently-running Execution to activate itself.
-// Doing this allows DM to know that the Execution has started, and also enables
-// the Execution to access other APIs like WalkGraph, AddDeps, and
-// FinishAttempt.
-//
-// ActivateExecution must be called with the ExecutionID and Activation token
-// that DM provided when the Execution was started with the distributor.
-//
-// If the Execution has not been activated, the Execution will be marked as
-// 'activating' and this will return an OK code. At this point, your client
-// may use the ExecutionToken with any RPCs that have an ExecutionAuth field.
-//
-// This RPC may return:
-//   * OK - The Execution is now activated.
-//   * InvalidArgmument - The request was malformed. Retrying will not help.
-//   * PermissionDenied - The provided activation token was incorrect.
-//     Retrying will not help.
-//   * AlreadyExists - The activation token was correct, but some other entity
-//     already activated this Execution. The client should cease operations.
-//     Retrying will not help.
-//
-// All other errors should be retried with the exact same ActivateExecutionReq
-// data.
-type ActivateExecutionReq struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Auth is the Execution_Auth containing the Activation Token, as provided
-	// to the distributor when the Execution was created.
-	Auth *Execution_Auth `protobuf:"bytes,1,opt,name=auth,proto3" json:"auth,omitempty"`
-	// ExecutionToken should be randomly generated by the machine running the
-	// execution, or by the distributor service such that if two racing Executions
-	// both attempt to Activate with the same ExecutionID and ActivationToken, the
-	// ExecutionToken will (probably) be different for them so that only one will
-	// win.
-	ExecutionToken []byte `protobuf:"bytes,2,opt,name=execution_token,json=executionToken,proto3" json:"execution_token,omitempty"`
-}
-
-func (x *ActivateExecutionReq) Reset() {
-	*x = ActivateExecutionReq{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *ActivateExecutionReq) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*ActivateExecutionReq) ProtoMessage() {}
-
-func (x *ActivateExecutionReq) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use ActivateExecutionReq.ProtoReflect.Descriptor instead.
-func (*ActivateExecutionReq) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *ActivateExecutionReq) GetAuth() *Execution_Auth {
-	if x != nil {
-		return x.Auth
-	}
-	return nil
-}
-
-func (x *ActivateExecutionReq) GetExecutionToken() []byte {
-	if x != nil {
-		return x.ExecutionToken
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDesc = []byte{
-	0x0a, 0x3f, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
-	0x65, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x12, 0x02, 0x64, 0x6d, 0x1a, 0x37, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69,
-	0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61,
-	0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72,
-	0x61, 0x70, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x67,
-	0x0a, 0x14, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
-	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x26, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
-	0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x27,
-	0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65,
-	0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
-	0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x6f, 0x2e, 0x63, 0x68,
-	0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f,
-	0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76,
-	0x31, 0x3b, 0x64, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDescData = file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_goTypes = []interface{}{
-	(*ActivateExecutionReq)(nil), // 0: dm.ActivateExecutionReq
-	(*Execution_Auth)(nil),       // 1: dm.Execution.Auth
-}
-var file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_depIdxs = []int32{
-	1, // 0: dm.ActivateExecutionReq.auth:type_name -> dm.Execution.Auth
-	1, // [1:1] is the sub-list for method output_type
-	1, // [1:1] is the sub-list for method input_type
-	1, // [1:1] is the sub-list for extension type_name
-	1, // [1:1] is the sub-list for extension extendee
-	0, // [0:1] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_init() }
-func file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_init() {
-	if File_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_init()
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ActivateExecutionReq); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   1,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto = out.File
-	file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_depIdxs = nil
-}
diff --git a/dm/api/service/v1/activate_execution.proto b/dm/api/service/v1/activate_execution.proto
deleted file mode 100644
index f8d9717..0000000
--- a/dm/api/service/v1/activate_execution.proto
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/service/v1;dm";
-
-import "go.chromium.org/luci/dm/api/service/v1/graph_data.proto";
-
-package dm;
-
-// ActivateExecutionReq allows a currently-running Execution to activate itself.
-// Doing this allows DM to know that the Execution has started, and also enables
-// the Execution to access other APIs like WalkGraph, AddDeps, and
-// FinishAttempt.
-//
-// ActivateExecution must be called with the ExecutionID and Activation token
-// that DM provided when the Execution was started with the distributor.
-//
-// If the Execution has not been activated, the Execution will be marked as
-// 'activating' and this will return an OK code. At this point, your client
-// may use the ExecutionToken with any RPCs that have an ExecutionAuth field.
-//
-// This RPC may return:
-//   * OK - The Execution is now activated.
-//   * InvalidArgmument - The request was malformed. Retrying will not help.
-//   * PermissionDenied - The provided activation token was incorrect.
-//     Retrying will not help.
-//   * AlreadyExists - The activation token was correct, but some other entity
-//     already activated this Execution. The client should cease operations.
-//     Retrying will not help.
-//
-// All other errors should be retried with the exact same ActivateExecutionReq
-// data.
-message ActivateExecutionReq {
-  // Auth is the Execution_Auth containing the Activation Token, as provided
-  // to the distributor when the Execution was created.
-  dm.Execution.Auth auth = 1;
-
-  // ExecutionToken should be randomly generated by the machine running the
-  // execution, or by the distributor service such that if two racing Executions
-  // both attempt to Activate with the same ExecutionID and ActivationToken, the
-  // ExecutionToken will (probably) be different for them so that only one will
-  // win.
-  bytes execution_token = 2;
-}
diff --git a/dm/api/service/v1/activate_execution_normalize.go b/dm/api/service/v1/activate_execution_normalize.go
deleted file mode 100644
index 2312fbd..0000000
--- a/dm/api/service/v1/activate_execution_normalize.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import "fmt"
-
-// MinimumActivationTokenLength is the minimum number of bytes in an appropriate
-// ExecutionToken.
-const MinimumActivationTokenLength = 32
-
-// Normalize returns an error iff the ActivateExecutionReq has bad form (nils,
-// insufficient activation token length, etc.
-func (a *ActivateExecutionReq) Normalize() error {
-	if err := a.Auth.Normalize(); err != nil {
-		return err
-	}
-	if len(a.ExecutionToken) < MinimumActivationTokenLength {
-		return fmt.Errorf("insufficiently long ExecutionToken: %d",
-			len(a.ExecutionToken))
-	}
-	return nil
-}
diff --git a/dm/api/service/v1/attempt_data.go b/dm/api/service/v1/attempt_data.go
deleted file mode 100644
index 4efcc36..0000000
--- a/dm/api/service/v1/attempt_data.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"time"
-
-	"google.golang.org/protobuf/types/known/timestamppb"
-)
-
-// NewJsonResult creates a new JsonResult object with optional expiration time.
-func NewJsonResult(data string, exps ...time.Time) *JsonResult {
-	exp := time.Time{}
-	switch l := len(exps); {
-	case l == 1:
-		exp = exps[0]
-	case l > 1:
-		panic("too many exps")
-	}
-	res := &JsonResult{
-		Object: data,
-		Size:   uint32(len(data)),
-	}
-	if !exp.IsZero() {
-		res.Expiration = timestamppb.New(exp)
-	}
-	return res
-}
-
-// NewDatalessJsonResult creates a new JsonResult object without data and with
-// optional expiration time.
-func NewDatalessJsonResult(size uint32, exps ...time.Time) *JsonResult {
-	exp := time.Time{}
-	switch l := len(exps); {
-	case l == 1:
-		exp = exps[0]
-	case l > 1:
-		panic("too many exps")
-	}
-	res := &JsonResult{Size: size}
-	if !exp.IsZero() {
-		res.Expiration = timestamppb.New(exp)
-	}
-	return res
-}
-
-// NewAttemptScheduling creates an Attempt in the SCHEDULING state.
-func NewAttemptScheduling() *Attempt {
-	return &Attempt{
-		Data: &Attempt_Data{
-			AttemptType: &Attempt_Data_Scheduling_{
-				&Attempt_Data_Scheduling{}}}}
-}
-
-// NewAttemptExecuting creates an Attempt in the EXECUTING state.
-func NewAttemptExecuting(curExID uint32) *Attempt {
-	return &Attempt{
-		Data: &Attempt_Data{
-			NumExecutions: curExID,
-			AttemptType: &Attempt_Data_Executing_{
-				&Attempt_Data_Executing{CurExecutionId: curExID}}}}
-}
-
-// NewAttemptWaiting creates an Attempt in the WAITING state.
-func NewAttemptWaiting(numWaiting uint32) *Attempt {
-	return &Attempt{
-		Data: &Attempt_Data{
-			AttemptType: &Attempt_Data_Waiting_{
-				&Attempt_Data_Waiting{NumWaiting: numWaiting}}}}
-}
-
-// NewAttemptFinished creates an Attempt in the FINISHED state.
-func NewAttemptFinished(result *JsonResult) *Attempt {
-	return &Attempt{
-		Data: &Attempt_Data{
-			AttemptType: &Attempt_Data_Finished_{
-				&Attempt_Data_Finished{Data: result}}}}
-}
-
-// NewAttemptAbnormalFinish creates an Attempt in the ABNORMAL_FINISH state.
-func NewAttemptAbnormalFinish(af *AbnormalFinish) *Attempt {
-	return &Attempt{
-		Data: &Attempt_Data{
-			AttemptType: &Attempt_Data_AbnormalFinish{af}}}
-}
-
-// State computes the Attempt_State for the current Attempt_Data
-func (d *Attempt_Data) State() Attempt_State {
-	if d != nil {
-		switch d.AttemptType.(type) {
-		case *Attempt_Data_Scheduling_:
-			return Attempt_SCHEDULING
-		case *Attempt_Data_Executing_:
-			return Attempt_EXECUTING
-		case *Attempt_Data_Waiting_:
-			return Attempt_WAITING
-		case *Attempt_Data_Finished_:
-			return Attempt_FINISHED
-		case *Attempt_Data_AbnormalFinish:
-			return Attempt_ABNORMAL_FINISHED
-		}
-	}
-	return Attempt_SCHEDULING
-}
-
-// NormalizePartial will nil out the Partial field for this Attempt if all
-// Partial fields are false.
-func (d *Attempt) NormalizePartial() {
-	p := d.GetPartial()
-	if p == nil {
-		return
-	}
-	if !(p.Data || p.Executions || p.FwdDeps || p.BackDeps ||
-		p.Result != Attempt_Partial_LOADED) {
-		d.Partial = nil
-	}
-}
-
-// Any returns true iff any of the Partial fields are true such that they could
-// be successfully loaded on a subsequent query.
-func (p *Attempt_Partial) Any() bool {
-	return (p.BackDeps || p.Data || p.Executions || p.FwdDeps ||
-		p.Result == Attempt_Partial_NOT_LOADED)
-}
diff --git a/dm/api/service/v1/attempt_list.go b/dm/api/service/v1/attempt_list.go
deleted file mode 100644
index 3d9dc04..0000000
--- a/dm/api/service/v1/attempt_list.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"errors"
-	"sort"
-
-	"github.com/xtgo/set"
-)
-
-// Normalize sorts and uniq's attempt nums
-func (a *AttemptList) Normalize() error {
-	for q, vals := range a.GetTo() {
-		if vals == nil {
-			a.To[q] = &AttemptList_Nums{}
-		} else {
-			if err := vals.Normalize(); err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-type revUint32Slice []uint32
-
-func (u revUint32Slice) Len() int      { return len(u) }
-func (u revUint32Slice) Swap(i, j int) { u[i], u[j] = u[j], u[i] }
-
-// Less intentionally reverses the comparison of i and j.
-func (u revUint32Slice) Less(i, j int) bool { return u[j] < u[i] }
-
-// Normalize sorts and uniq's attempt nums. If Nums equals [0], [] or nil,
-// it implies all attempts for the quest and will be normalized to nil.
-//
-// It is an error for Nums to contain 0 as well as other numbers.
-func (a *AttemptList_Nums) Normalize() error {
-	if len(a.Nums) == 0 || (len(a.Nums) == 1 && a.Nums[0] == 0) {
-		a.Nums = nil
-		return nil
-	}
-	slc := revUint32Slice(a.Nums)
-	sort.Sort(slc)
-	if a.Nums[len(a.Nums)-1] == 0 {
-		return errors.New("AttemptList.Nums contains 0 as well as other values")
-	}
-	a.Nums = a.Nums[:set.Uniq(slc)]
-	return nil
-}
-
-// NewAttemptList is a convenience method for making a normalized
-// *AttemptList with a pre-normalized literal map of quest -> attempt nums.
-//
-// If the provided data is invalid, this method will panic.
-func NewAttemptList(data map[string][]uint32) *AttemptList {
-	ret := &AttemptList{To: make(map[string]*AttemptList_Nums, len(data))}
-	for qst, atmpts := range data {
-		nums := &AttemptList_Nums{Nums: atmpts}
-		if err := nums.Normalize(); err != nil {
-			panic(err)
-		}
-		ret.To[qst] = nums
-	}
-	return ret
-}
-
-// AddAIDs adds the given Attempt_ID to the AttemptList
-func (a *AttemptList) AddAIDs(aids ...*Attempt_ID) {
-	for _, aid := range aids {
-		if a.To == nil {
-			a.To = map[string]*AttemptList_Nums{}
-		}
-		atmptNums := a.To[aid.Quest]
-		if atmptNums == nil {
-			atmptNums = &AttemptList_Nums{}
-			a.To[aid.Quest] = atmptNums
-		}
-		atmptNums.Nums = append(atmptNums.Nums, aid.Id)
-	}
-}
-
-// Dup does a deep copy of this AttemptList.
-func (a *AttemptList) Dup() *AttemptList {
-	ret := &AttemptList{}
-	for k, v := range a.To {
-		if ret.To == nil {
-			ret.To = make(map[string]*AttemptList_Nums, len(a.To))
-		}
-		vals := &AttemptList_Nums{Nums: make([]uint32, len(v.Nums))}
-		copy(vals.Nums, v.Nums)
-		ret.To[k] = vals
-	}
-	return ret
-}
-
-// UpdateWith updates this AttemptList with all the entries in the other
-// AttemptList.
-func (a *AttemptList) UpdateWith(o *AttemptList) {
-	for qid, atmpts := range o.To {
-		if curAtmpts, ok := a.To[qid]; !ok {
-			a.To[qid] = atmpts
-		} else {
-			curAtmpts.Nums = append(curAtmpts.Nums, atmpts.Nums...)
-			curAtmpts.Normalize()
-		}
-	}
-}
diff --git a/dm/api/service/v1/attempt_list_test.go b/dm/api/service/v1/attempt_list_test.go
deleted file mode 100644
index 30af900..0000000
--- a/dm/api/service/v1/attempt_list_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestAttemptListNormalize(t *testing.T) {
-	t.Parallel()
-
-	Convey("AttemptList.Normalize", t, func() {
-		Convey("empty", func() {
-			a := &AttemptList{}
-			So(a.Normalize(), ShouldBeNil)
-		})
-
-		Convey("stuff", func() {
-			a := &AttemptList{To: map[string]*AttemptList_Nums{}}
-			a.To["quest"] = &AttemptList_Nums{Nums: []uint32{700, 2, 7, 90, 1, 1, 700}}
-			a.To["other"] = &AttemptList_Nums{}
-			a.To["other2"] = &AttemptList_Nums{Nums: []uint32{}}
-			So(a.Normalize(), ShouldBeNil)
-
-			So(a, ShouldResemble, &AttemptList{To: map[string]*AttemptList_Nums{
-				"quest":  {Nums: []uint32{700, 90, 7, 2, 1}},
-				"other":  {},
-				"other2": {},
-			}})
-		})
-
-		Convey("empty attempts / 0 attempts", func() {
-			a := &AttemptList{To: map[string]*AttemptList_Nums{}}
-			a.To["quest"] = nil
-			a.To["other"] = &AttemptList_Nums{Nums: []uint32{0}}
-			a.To["woot"] = &AttemptList_Nums{Nums: []uint32{}}
-			So(a.Normalize(), ShouldBeNil)
-			So(a, ShouldResemble, NewAttemptList(map[string][]uint32{
-				"quest": nil,
-				"other": nil,
-				"woot":  nil,
-			}))
-
-			Convey("0 + other nums is error", func() {
-				a.To["nerp"] = &AttemptList_Nums{Nums: []uint32{30, 7, 0}}
-				So(a.Normalize(), ShouldErrLike, "contains 0 as well as other values")
-			})
-		})
-	})
-
-	Convey("AttemptList.AddAIDs", t, func() {
-		list := &AttemptList{}
-		list.AddAIDs(NewAttemptID("a", 1), NewAttemptID("b", 1), NewAttemptID("b", 2))
-		So(list.To, ShouldResemble, map[string]*AttemptList_Nums{
-			"a": {Nums: []uint32{1}},
-			"b": {Nums: []uint32{1, 2}},
-		})
-	})
-}
diff --git a/dm/api/service/v1/attempt_state_evolve.go b/dm/api/service/v1/attempt_state_evolve.go
deleted file mode 100644
index 92e05c9..0000000
--- a/dm/api/service/v1/attempt_state_evolve.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"fmt"
-)
-
-// validAttemptStateEvolution defines all valid {From -> []To} state
-// transitions. The identity transition (X -> X) is implied, as long as X has an
-// entry in this mapping.
-var validAttemptStateEvolution = map[Attempt_State][]Attempt_State{
-	Attempt_SCHEDULING: {
-		Attempt_EXECUTING,         // scheduled
-		Attempt_ABNORMAL_FINISHED, // cancelled/timeout/err/etc.
-	},
-	Attempt_EXECUTING: {
-		Attempt_SCHEDULING,        // Retry
-		Attempt_WAITING,           // EnsureGraphData
-		Attempt_FINISHED,          // FinishAttempt
-		Attempt_ABNORMAL_FINISHED, // cancel/timeout/err/etc.
-	},
-	Attempt_WAITING: {
-		Attempt_SCHEDULING,        // unblocked
-		Attempt_ABNORMAL_FINISHED, // cancelled
-	},
-
-	Attempt_FINISHED:          {},
-	Attempt_ABNORMAL_FINISHED: {},
-}
-
-// Evolve attempts to evolve the state of this Attempt. If the state evolution
-// is not allowed (e.g. invalid state transition), this returns an error.
-func (s *Attempt_State) Evolve(newState Attempt_State) error {
-	nextStates := validAttemptStateEvolution[*s]
-	if nextStates == nil {
-		return fmt.Errorf("invalid state transition: no transitions defined for %s", *s)
-	}
-
-	if newState == *s {
-		return nil
-	}
-
-	for _, val := range nextStates {
-		if newState == val {
-			*s = newState
-			return nil
-		}
-	}
-
-	return fmt.Errorf("invalid state transition %v -> %v", *s, newState)
-}
-
-// MustEvolve is a panic'ing version of Evolve.
-func (s *Attempt_State) MustEvolve(newState Attempt_State) {
-	err := s.Evolve(newState)
-	if err != nil {
-		panic(err)
-	}
-}
-
-// Terminal returns true iff there are no valid evolutions from the current
-// state.
-func (s Attempt_State) Terminal() bool {
-	return len(validAttemptStateEvolution[s]) == 0
-}
diff --git a/dm/api/service/v1/attempt_state_evolve_test.go b/dm/api/service/v1/attempt_state_evolve_test.go
deleted file mode 100644
index 88224d2..0000000
--- a/dm/api/service/v1/attempt_state_evolve_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestAttemptState(t *testing.T) {
-	t.Parallel()
-
-	Convey("Evolve", t, func() {
-		Convey("Identity", func() {
-			s := Attempt_SCHEDULING
-			So(s.Evolve(Attempt_SCHEDULING), ShouldBeNil)
-			So(s, ShouldEqual, Attempt_SCHEDULING)
-		})
-
-		Convey("Transition", func() {
-			s := Attempt_EXECUTING
-			So(s.Evolve(Attempt_WAITING), ShouldBeNil)
-			So(s, ShouldEqual, Attempt_WAITING)
-		})
-
-		Convey("Invalid starting transistion", func() {
-			s := Attempt_SCHEDULING
-			So(s.Evolve(Attempt_FINISHED), ShouldErrLike, "invalid state transition SCHEDULING -> FINISHED")
-			So(s, ShouldEqual, Attempt_SCHEDULING)
-		})
-
-		Convey("Invalid ending transistion", func() {
-			s := Attempt_WAITING
-			So(s.Evolve(Attempt_FINISHED), ShouldErrLike, "invalid state transition WAITING -> FINISHED")
-			So(s, ShouldEqual, Attempt_WAITING)
-		})
-
-		Convey("MustEvolve", func() {
-			s := Attempt_FINISHED
-			So(func() { s.MustEvolve(Attempt_SCHEDULING) }, ShouldPanic)
-		})
-	})
-}
diff --git a/dm/api/service/v1/datastore_embed.go b/dm/api/service/v1/datastore_embed.go
deleted file mode 100644
index 77769ec..0000000
--- a/dm/api/service/v1/datastore_embed.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"fmt"
-	"strconv"
-	"strings"
-
-	"google.golang.org/protobuf/proto"
-
-	"go.chromium.org/luci/common/data/sortby"
-	"go.chromium.org/luci/gae/service/datastore"
-)
-
-const flipMask uint32 = 0xFFFFFFFF
-
-var _ datastore.PropertyConverter = (*Attempt_ID)(nil)
-
-// NewQuestID is a shorthand to New a new *Quest_ID
-func NewQuestID(qst string) *Quest_ID {
-	return &Quest_ID{Id: qst}
-}
-
-// NewAttemptID is a shorthand to New a new *Attempt_ID
-func NewAttemptID(qst string, aid uint32) *Attempt_ID {
-	return &Attempt_ID{Quest: qst, Id: aid}
-}
-
-// NewExecutionID is a shorthand to New a new *Execution_ID
-func NewExecutionID(qst string, aid, eid uint32) *Execution_ID {
-	return &Execution_ID{Quest: qst, Attempt: aid, Id: eid}
-}
-
-// ToProperty implements datastore.PropertyConverter for the purpose of
-// embedding this Attempt_ID as the ID of a luci/gae compatible datastore
-// object. The numerical id field is stored as an inverted, hex-encoded string,
-// so that Attempt_ID{"quest", 1} would encode as "quest|fffffffe". This is done
-// so that the __key__ ordering in the dm application prefers to order the most
-// recent attempts first.
-//
-// The go representation will always have the normal non-flipped numerical id.
-func (a *Attempt_ID) ToProperty() (datastore.Property, error) {
-	return datastore.MkPropertyNI(a.DMEncoded()), nil
-}
-
-// FromProperty implements datastore.PropertyConverter
-func (a *Attempt_ID) FromProperty(p datastore.Property) error {
-	if p.Type() != datastore.PTString {
-		return fmt.Errorf("wrong type for property: %s", p.Type())
-	}
-	return a.SetDMEncoded(p.Value().(string))
-}
-
-// DMEncoded returns the encoded string id for this Attempt. Numeric values are
-// inverted if flip is true.
-func (a *Attempt_ID) DMEncoded() string {
-	return fmt.Sprintf("%s|%08x", a.Quest, flipMask^a.Id)
-}
-
-// SetDMEncoded decodes val into this Attempt_ID, returning an error if
-// there's a problem. Numeric values are inverted if flip is true.
-func (a *Attempt_ID) SetDMEncoded(val string) error {
-	toks := strings.SplitN(val, "|", 2)
-	if len(toks) != 2 {
-		return fmt.Errorf("unable to parse Attempt id: %q", val)
-	}
-	an, err := strconv.ParseUint(toks[1], 16, 32)
-	if err != nil {
-		return err
-	}
-
-	a.Quest = toks[0]
-	a.Id = flipMask ^ uint32(an)
-	return nil
-}
-
-// GetQuest gets the specified quest from GraphData, if it's already there. If
-// it's not, then a new Quest will be created, added, and returned.
-//
-// If the Quests map is uninitialized, this will initialize it.
-func (g *GraphData) GetQuest(qid string) (*Quest, bool) {
-	cur, ok := g.Quests[qid]
-	if !ok {
-		cur = &Quest{
-			Id:       NewQuestID(qid),
-			Attempts: map[uint32]*Attempt{},
-		}
-		if g.Quests == nil {
-			g.Quests = map[string]*Quest{}
-		}
-		g.Quests[qid] = cur
-	}
-	return cur, ok
-}
-
-// NewQuestDesc is a shorthand method for building a new *Quest_Desc.
-func NewQuestDesc(cfg string, params, distParams string, meta *Quest_Desc_Meta) *Quest_Desc {
-	return &Quest_Desc{
-		DistributorConfigName: cfg,
-		Parameters:            params,
-		DistributorParameters: distParams,
-		Meta:                  meta,
-	}
-}
-
-// NewTemplateSpec is a shorthand method for building a new *Quest_TemplateSpec.
-func NewTemplateSpec(project, ref, version, name string) *Quest_TemplateSpec {
-	return &Quest_TemplateSpec{
-		Project: project,
-		Ref:     ref,
-		Version: version,
-		Name:    name,
-	}
-}
-
-// Equals returns true iff this Quest_TemplateSpec matches all of the fields of
-// the `o` Quest_TemplateSpec.
-func (t *Quest_TemplateSpec) Equals(o *Quest_TemplateSpec) bool {
-	return proto.Equal(t, o)
-}
-
-// QuestTemplateSpecs is a sortable slice of *Quest_TemplateSpec.
-type QuestTemplateSpecs []*Quest_TemplateSpec
-
-func (s QuestTemplateSpecs) Len() int { return len(s) }
-func (s QuestTemplateSpecs) Less(i, j int) bool {
-	return sortby.Chain{
-		func(i, j int) bool { return s[i].Project < s[j].Project },
-		func(i, j int) bool { return s[i].Ref < s[j].Ref },
-		func(i, j int) bool { return s[i].Version < s[j].Version },
-		func(i, j int) bool { return s[i].Name < s[j].Name },
-	}.Use(i, j)
-}
-func (s QuestTemplateSpecs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
diff --git a/dm/api/service/v1/datastore_embed_test.go b/dm/api/service/v1/datastore_embed_test.go
deleted file mode 100644
index fe9a2eb..0000000
--- a/dm/api/service/v1/datastore_embed_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-	"go.chromium.org/luci/gae/service/datastore"
-)
-
-func TestAttemptID(t *testing.T) {
-	t.Parallel()
-
-	Convey("Test Attempt_ID DM encoding", t, func() {
-		Convey("render", func() {
-			aid := NewAttemptID("", 0)
-			So(aid.DMEncoded(), ShouldEqual, "|ffffffff")
-
-			aid.Quest = "moo"
-			So(aid.DMEncoded(), ShouldEqual, "moo|ffffffff")
-
-			aid.Id = 10
-			So(aid.DMEncoded(), ShouldEqual, "moo|fffffff5")
-
-			p, err := aid.ToProperty()
-			So(err, ShouldBeNil)
-			So(p, ShouldResemble, datastore.MkPropertyNI("moo|fffffff5"))
-		})
-
-		Convey("parse", func() {
-			Convey("good", func() {
-				aid := &Attempt_ID{}
-				So(aid.SetDMEncoded("something|ffffffff"), ShouldBeNil)
-				So(aid, ShouldResemble, NewAttemptID("something", 0))
-
-				So(aid.FromProperty(datastore.MkPropertyNI("wat|fffffffa")), ShouldBeNil)
-				So(aid, ShouldResemble, NewAttemptID("wat", 5))
-			})
-
-			Convey("err", func() {
-				aid := &Attempt_ID{}
-				So(aid.SetDMEncoded("somethingfatsrnt"), ShouldErrLike, "unable to parse")
-				So(aid.SetDMEncoded("something|cat"), ShouldErrLike, `strconv.ParseUint: parsing "cat"`)
-				So(aid.SetDMEncoded(""), ShouldErrLike, "unable to parse")
-				So(aid.SetDMEncoded("somethingffffffff"), ShouldErrLike, "unable to parse Attempt")
-				So(aid.FromProperty(datastore.MkPropertyNI(100)), ShouldErrLike, "wrong type")
-			})
-
-		})
-	})
-}
diff --git a/dm/api/service/v1/depsserver_dec.go b/dm/api/service/v1/depsserver_dec.go
deleted file mode 100644
index 61ed966..0000000
--- a/dm/api/service/v1/depsserver_dec.go
+++ /dev/null
@@ -1,94 +0,0 @@
-// Code generated by svcdec; DO NOT EDIT.
-
-package dm
-
-import (
-	"context"
-
-	proto "github.com/golang/protobuf/proto"
-
-	emptypb "google.golang.org/protobuf/types/known/emptypb"
-)
-
-type DecoratedDeps struct {
-	// Service is the service to decorate.
-	Service DepsServer
-	// Prelude is called for each method before forwarding the call to Service.
-	// If Prelude returns an error, then the call is skipped and the error is
-	// processed via the Postlude (if one is defined), or it is returned directly.
-	Prelude func(ctx context.Context, methodName string, req proto.Message) (context.Context, error)
-	// Postlude is called for each method after Service has processed the call, or
-	// after the Prelude has returned an error. This takes the the Service's
-	// response proto (which may be nil) and/or any error. The decorated
-	// service will return the response (possibly mutated) and error that Postlude
-	// returns.
-	Postlude func(ctx context.Context, methodName string, rsp proto.Message, err error) error
-}
-
-func (s *DecoratedDeps) EnsureGraphData(ctx context.Context, req *EnsureGraphDataReq) (rsp *EnsureGraphDataRsp, err error) {
-	if s.Prelude != nil {
-		var newCtx context.Context
-		newCtx, err = s.Prelude(ctx, "EnsureGraphData", req)
-		if err == nil {
-			ctx = newCtx
-		}
-	}
-	if err == nil {
-		rsp, err = s.Service.EnsureGraphData(ctx, req)
-	}
-	if s.Postlude != nil {
-		err = s.Postlude(ctx, "EnsureGraphData", rsp, err)
-	}
-	return
-}
-
-func (s *DecoratedDeps) ActivateExecution(ctx context.Context, req *ActivateExecutionReq) (rsp *emptypb.Empty, err error) {
-	if s.Prelude != nil {
-		var newCtx context.Context
-		newCtx, err = s.Prelude(ctx, "ActivateExecution", req)
-		if err == nil {
-			ctx = newCtx
-		}
-	}
-	if err == nil {
-		rsp, err = s.Service.ActivateExecution(ctx, req)
-	}
-	if s.Postlude != nil {
-		err = s.Postlude(ctx, "ActivateExecution", rsp, err)
-	}
-	return
-}
-
-func (s *DecoratedDeps) FinishAttempt(ctx context.Context, req *FinishAttemptReq) (rsp *emptypb.Empty, err error) {
-	if s.Prelude != nil {
-		var newCtx context.Context
-		newCtx, err = s.Prelude(ctx, "FinishAttempt", req)
-		if err == nil {
-			ctx = newCtx
-		}
-	}
-	if err == nil {
-		rsp, err = s.Service.FinishAttempt(ctx, req)
-	}
-	if s.Postlude != nil {
-		err = s.Postlude(ctx, "FinishAttempt", rsp, err)
-	}
-	return
-}
-
-func (s *DecoratedDeps) WalkGraph(ctx context.Context, req *WalkGraphReq) (rsp *GraphData, err error) {
-	if s.Prelude != nil {
-		var newCtx context.Context
-		newCtx, err = s.Prelude(ctx, "WalkGraph", req)
-		if err == nil {
-			ctx = newCtx
-		}
-	}
-	if err == nil {
-		rsp, err = s.Service.WalkGraph(ctx, req)
-	}
-	if s.Postlude != nil {
-		err = s.Postlude(ctx, "WalkGraph", rsp, err)
-	}
-	return
-}
diff --git a/dm/api/service/v1/ensure_graph_data.pb.go b/dm/api/service/v1/ensure_graph_data.pb.go
deleted file mode 100644
index 75281e1..0000000
--- a/dm/api/service/v1/ensure_graph_data.pb.go
+++ /dev/null
@@ -1,771 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/service/v1/ensure_graph_data.proto
-
-package dm
-
-import (
-	templateproto "go.chromium.org/luci/common/data/text/templateproto"
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type TemplateInstantiation struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// project is the luci-config project which defines the template.
-	Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"`
-	// ref is the git ref of the project that defined this template. If omitted,
-	// this will use the template definition from the project-wide configuration
-	// and not the configuration located on a particular ref (like
-	// 'refs/heads/master').
-	//
-	// UNUSED.
-	Ref string `protobuf:"bytes,2,opt,name=ref,proto3" json:"ref,omitempty"`
-	// specifier specifies the actual template name, as well as any substitution
-	// parameters which that template might require.
-	Specifier *templateproto.Specifier `protobuf:"bytes,4,opt,name=specifier,proto3" json:"specifier,omitempty"`
-}
-
-func (x *TemplateInstantiation) Reset() {
-	*x = TemplateInstantiation{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *TemplateInstantiation) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*TemplateInstantiation) ProtoMessage() {}
-
-func (x *TemplateInstantiation) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use TemplateInstantiation.ProtoReflect.Descriptor instead.
-func (*TemplateInstantiation) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *TemplateInstantiation) GetProject() string {
-	if x != nil {
-		return x.Project
-	}
-	return ""
-}
-
-func (x *TemplateInstantiation) GetRef() string {
-	if x != nil {
-		return x.Ref
-	}
-	return ""
-}
-
-func (x *TemplateInstantiation) GetSpecifier() *templateproto.Specifier {
-	if x != nil {
-		return x.Specifier
-	}
-	return nil
-}
-
-// EnsureGraphDataReq allows you to assert the existence of Attempts in DM's
-// graph, and allows you to declare dependencies from one Attempt to another.
-//
-// You can declare Attempts by any combination of:
-//   * Providing a quest description plus a list of Attempt numbers for that
-//     quest.
-//   * Providing a template instantiation (for a project-declared quest
-//     template) plus a list of Attempt numbers for that quest.
-//   * Providing a raw set of quest_id -> attempt numbers for quests that you
-//     already know that DM has a definition for.
-//
-// In response, DM will tell you what the IDs of all supplied Quests/Attempts
-// are.
-//
-// To create a dependencies, call this method while running as part of an
-// execution by filling the for_execution field. All attempts named as described
-// above will become dependencies for the indicated execution. It is only
-// possible for a currently-running execution to create dependencies for its own
-// Attempt. In particular, it is not possible to create dependencies as
-// a non-execution user (e.g. a human), nor is it possible for an execution to
-// create attempts on behalf of some other execution.
-//
-// If the attempts were being created as dependencies, and were already in the
-// Finished state, this request can also opt to include the AttemptResults
-// directly.
-type EnsureGraphDataReq struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Quest is a list of quest descriptors. DM will ensure that the
-	// corresponding Quests exist. If they don't, they'll be created.
-	Quest []*Quest_Desc `protobuf:"bytes,1,rep,name=quest,proto3" json:"quest,omitempty"`
-	// QuestAttempt allows the addition of attempts which are derived from
-	// the quest bodies provided above.
-	// Each entry here maps 1:1 with the equivalent quest.
-	QuestAttempt []*AttemptList_Nums `protobuf:"bytes,2,rep,name=quest_attempt,json=questAttempt,proto3" json:"quest_attempt,omitempty"`
-	// TemplateQuest allows the addition of quests which are derived from
-	// Templates, as defined on a per-project basis.
-	TemplateQuest []*TemplateInstantiation `protobuf:"bytes,3,rep,name=template_quest,json=templateQuest,proto3" json:"template_quest,omitempty"`
-	// TemplateAttempt allows the addition of attempts which are derived from
-	// Templates. This must be equal in length to template_quest.
-	// Each entry here maps 1:1 with the equivalent quest in template_quest.
-	TemplateAttempt []*AttemptList_Nums `protobuf:"bytes,4,rep,name=template_attempt,json=templateAttempt,proto3" json:"template_attempt,omitempty"`
-	// RawAttempts is a list that asserts that the following attempts should
-	// exist. The quest ids in this list must be already-known to DM, NOT
-	// included in the quest field above. This is useful when you know the ID of
-	// the Quest, but not the actual definition of the quest.
-	RawAttempts *AttemptList `protobuf:"bytes,5,opt,name=raw_attempts,json=rawAttempts,proto3" json:"raw_attempts,omitempty"`
-	// ForExecution is an authentication pair (Execution_ID, Token).
-	//
-	// If this is provided then it will serve as authorization for the creation of
-	// any `quests` included, and any `attempts` indicated will be set as
-	// dependencies for the execution.
-	//
-	// If this omitted, then the request requires some user/bot authentication,
-	// and any quests/attempts provided will be made standalone (e.g. nothing will
-	// depend on them).
-	ForExecution *Execution_Auth             `protobuf:"bytes,6,opt,name=for_execution,json=forExecution,proto3" json:"for_execution,omitempty"`
-	Limit        *EnsureGraphDataReq_Limit   `protobuf:"bytes,7,opt,name=limit,proto3" json:"limit,omitempty"`
-	Include      *EnsureGraphDataReq_Include `protobuf:"bytes,8,opt,name=include,proto3" json:"include,omitempty"`
-}
-
-func (x *EnsureGraphDataReq) Reset() {
-	*x = EnsureGraphDataReq{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *EnsureGraphDataReq) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*EnsureGraphDataReq) ProtoMessage() {}
-
-func (x *EnsureGraphDataReq) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use EnsureGraphDataReq.ProtoReflect.Descriptor instead.
-func (*EnsureGraphDataReq) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescGZIP(), []int{1}
-}
-
-func (x *EnsureGraphDataReq) GetQuest() []*Quest_Desc {
-	if x != nil {
-		return x.Quest
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataReq) GetQuestAttempt() []*AttemptList_Nums {
-	if x != nil {
-		return x.QuestAttempt
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataReq) GetTemplateQuest() []*TemplateInstantiation {
-	if x != nil {
-		return x.TemplateQuest
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataReq) GetTemplateAttempt() []*AttemptList_Nums {
-	if x != nil {
-		return x.TemplateAttempt
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataReq) GetRawAttempts() *AttemptList {
-	if x != nil {
-		return x.RawAttempts
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataReq) GetForExecution() *Execution_Auth {
-	if x != nil {
-		return x.ForExecution
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataReq) GetLimit() *EnsureGraphDataReq_Limit {
-	if x != nil {
-		return x.Limit
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataReq) GetInclude() *EnsureGraphDataReq_Include {
-	if x != nil {
-		return x.Include
-	}
-	return nil
-}
-
-type EnsureGraphDataRsp struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// accepted is true when all new graph data was journaled successfully. This
-	// means that `quests`, `attempts`, `template_quest`, `template_attempt` were
-	// all well-formed and are scheduled to be added. They will 'eventually' be
-	// readable via other APIs (like WalkGraph), but when they are, they'll have
-	// the IDs reflected in this response.
-	//
-	// If `attempts` referrs to quests that don't exist and weren't provided in
-	// `quests`, those quests will be listed in `result` with the DNE flag set.
-	//
-	// If `template_quest` had errors (missing template, bad params, etc.), the
-	// errors will be located in `template_error`. If all of the templates parsed
-	// successfully, the quest ids for those rendered `template_quest` will be in
-	// `template_ids`.
-	Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"`
-	// quest_ids will be populated with the Quest.IDs of any quests defined
-	// by quest in the initial request. Its length is guaranteed to match
-	// the length of quest, if there were no errors.
-	QuestIds []*Quest_ID `protobuf:"bytes,2,rep,name=quest_ids,json=questIds,proto3" json:"quest_ids,omitempty"`
-	// template_ids will be populated with the Quest.IDs of any templates defined
-	// by template_quest in the initial request. Its length is guaranteed to match
-	// the length of template_quest, if there were no errors.
-	TemplateIds []*Quest_ID `protobuf:"bytes,3,rep,name=template_ids,json=templateIds,proto3" json:"template_ids,omitempty"`
-	// template_error is either empty if there were no template errors, or the
-	// length of template_quest. Non-empty strings are errors.
-	TemplateError []string `protobuf:"bytes,4,rep,name=template_error,json=templateError,proto3" json:"template_error,omitempty"`
-	// result holds the graph data pertaining to the request, containing any
-	// graph state that already existed at the time of the call. Any new data
-	// that was added to the graph state (accepted==true) will appear with
-	// `DNE==true`.
-	//
-	// Quest data will always be returned for any Quests which exist.
-	//
-	// If accepted==false, you can inspect this to determine why:
-	//   * Quests (without data) mentioned by the `attempts` field that do not
-	//     exist will have `DNE==true`.
-	//
-	// This also can be used to make adding dependencies a stateless
-	// single-request action:
-	//   * Attempts requested (assuming the corresponding Quest exists) will
-	//     contain their current state. If Include.AttemptResult was true, the
-	//     results will be populated (with the size limit mentioned in the request
-	//     documentation).
-	Result *GraphData `protobuf:"bytes,5,opt,name=result,proto3" json:"result,omitempty"`
-	// (if `for_execution` was specified) ShouldHalt indicates that the request
-	// was accepted by DM, and the execution should halt (DM will re-execute the
-	// Attempt when it becomes unblocked). If this is true, then the execution's
-	// auth Token is also revoked and will no longer work for futher API calls.
-	//
-	// If `for_execution` was provided in the request and this is false, it means
-	// that the execution may continue executing.
-	ShouldHalt bool `protobuf:"varint,6,opt,name=should_halt,json=shouldHalt,proto3" json:"should_halt,omitempty"`
-}
-
-func (x *EnsureGraphDataRsp) Reset() {
-	*x = EnsureGraphDataRsp{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *EnsureGraphDataRsp) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*EnsureGraphDataRsp) ProtoMessage() {}
-
-func (x *EnsureGraphDataRsp) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use EnsureGraphDataRsp.ProtoReflect.Descriptor instead.
-func (*EnsureGraphDataRsp) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescGZIP(), []int{2}
-}
-
-func (x *EnsureGraphDataRsp) GetAccepted() bool {
-	if x != nil {
-		return x.Accepted
-	}
-	return false
-}
-
-func (x *EnsureGraphDataRsp) GetQuestIds() []*Quest_ID {
-	if x != nil {
-		return x.QuestIds
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataRsp) GetTemplateIds() []*Quest_ID {
-	if x != nil {
-		return x.TemplateIds
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataRsp) GetTemplateError() []string {
-	if x != nil {
-		return x.TemplateError
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataRsp) GetResult() *GraphData {
-	if x != nil {
-		return x.Result
-	}
-	return nil
-}
-
-func (x *EnsureGraphDataRsp) GetShouldHalt() bool {
-	if x != nil {
-		return x.ShouldHalt
-	}
-	return false
-}
-
-type EnsureGraphDataReq_Limit struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// MaxDataSize sets the maximum amount of 'Data' (in bytes) that can be
-	// returned, if include.attempt_result is set. If this limit is hit, then
-	// the appropriate 'partial' value will be set for that object, but the base
-	// object would still be included in the result.
-	//
-	// If this limit is 0, a default limit of 16MB will be used. If this limit
-	// exceeds 30MB, it will be reduced to 30MB.
-	MaxDataSize uint32 `protobuf:"varint,3,opt,name=max_data_size,json=maxDataSize,proto3" json:"max_data_size,omitempty"`
-}
-
-func (x *EnsureGraphDataReq_Limit) Reset() {
-	*x = EnsureGraphDataReq_Limit{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[3]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *EnsureGraphDataReq_Limit) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*EnsureGraphDataReq_Limit) ProtoMessage() {}
-
-func (x *EnsureGraphDataReq_Limit) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[3]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use EnsureGraphDataReq_Limit.ProtoReflect.Descriptor instead.
-func (*EnsureGraphDataReq_Limit) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescGZIP(), []int{1, 0}
-}
-
-func (x *EnsureGraphDataReq_Limit) GetMaxDataSize() uint32 {
-	if x != nil {
-		return x.MaxDataSize
-	}
-	return 0
-}
-
-type EnsureGraphDataReq_Include struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Attempt *EnsureGraphDataReq_Include_Options `protobuf:"bytes,4,opt,name=attempt,proto3" json:"attempt,omitempty"`
-}
-
-func (x *EnsureGraphDataReq_Include) Reset() {
-	*x = EnsureGraphDataReq_Include{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[4]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *EnsureGraphDataReq_Include) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*EnsureGraphDataReq_Include) ProtoMessage() {}
-
-func (x *EnsureGraphDataReq_Include) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[4]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use EnsureGraphDataReq_Include.ProtoReflect.Descriptor instead.
-func (*EnsureGraphDataReq_Include) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescGZIP(), []int{1, 1}
-}
-
-func (x *EnsureGraphDataReq_Include) GetAttempt() *EnsureGraphDataReq_Include_Options {
-	if x != nil {
-		return x.Attempt
-	}
-	return nil
-}
-
-type EnsureGraphDataReq_Include_Options struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Instructs finished objects to include the Result field.
-	Result bool `protobuf:"varint,3,opt,name=result,proto3" json:"result,omitempty"`
-}
-
-func (x *EnsureGraphDataReq_Include_Options) Reset() {
-	*x = EnsureGraphDataReq_Include_Options{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[5]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *EnsureGraphDataReq_Include_Options) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*EnsureGraphDataReq_Include_Options) ProtoMessage() {}
-
-func (x *EnsureGraphDataReq_Include_Options) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[5]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use EnsureGraphDataReq_Include_Options.ProtoReflect.Descriptor instead.
-func (*EnsureGraphDataReq_Include_Options) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescGZIP(), []int{1, 1, 0}
-}
-
-func (x *EnsureGraphDataReq_Include_Options) GetResult() bool {
-	if x != nil {
-		return x.Result
-	}
-	return false
-}
-
-var File_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDesc = []byte{
-	0x0a, 0x3e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x5f,
-	0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x12, 0x02, 0x64, 0x6d, 0x1a, 0x42, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75,
-	0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
-	0x6e, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x6d, 0x70,
-	0x6c, 0x61, 0x74, 0x65, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61,
-	0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x37, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72,
-	0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64,
-	0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31,
-	0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x1a, 0x32, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f,
-	0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73,
-	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x81, 0x01, 0x0a, 0x15, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61,
-	0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
-	0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x36, 0x0a, 0x09, 0x73,
-	0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18,
-	0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
-	0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66,
-	0x69, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0xad, 0x05, 0x0a, 0x12, 0x45, 0x6e,
-	0x73, 0x75, 0x72, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71,
-	0x12, 0x24, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x0e, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x52,
-	0x05, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0d, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f,
-	0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e,
-	0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x4e,
-	0x75, 0x6d, 0x73, 0x52, 0x0c, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70,
-	0x74, 0x12, 0x40, 0x0a, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x6d, 0x2e, 0x54,
-	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x51, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f,
-	0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e,
-	0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x4e,
-	0x75, 0x6d, 0x73, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74,
-	0x65, 0x6d, 0x70, 0x74, 0x12, 0x32, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x61, 0x74, 0x74, 0x65,
-	0x6d, 0x70, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x6d, 0x2e,
-	0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0b, 0x72, 0x61, 0x77,
-	0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x0d, 0x66, 0x6f, 0x72, 0x5f,
-	0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x12, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41,
-	0x75, 0x74, 0x68, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
-	0x6e, 0x12, 0x32, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x1c, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x47, 0x72, 0x61, 0x70,
-	0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x2e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x05,
-	0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x07, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
-	0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x6e, 0x73, 0x75,
-	0x72, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x2e, 0x49,
-	0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x07, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x1a,
-	0x37, 0x0a, 0x05, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f,
-	0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
-	0x0b, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x74, 0x61, 0x53, 0x69, 0x7a, 0x65, 0x4a, 0x04, 0x08, 0x01,
-	0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x1a, 0x9e, 0x01, 0x0a, 0x07, 0x49, 0x6e, 0x63,
-	0x6c, 0x75, 0x64, 0x65, 0x12, 0x40, 0x0a, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18,
-	0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x6e, 0x73, 0x75, 0x72,
-	0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x2e, 0x49, 0x6e,
-	0x63, 0x6c, 0x75, 0x64, 0x65, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x61,
-	0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x1a, 0x39, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
-	0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a,
-	0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10,
-	0x06, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08,
-	0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xfb, 0x01, 0x0a, 0x12, 0x45, 0x6e,
-	0x73, 0x75, 0x72, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x73, 0x70,
-	0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x09,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x0c, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x44, 0x52, 0x08, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x6c,
-	0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
-	0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x44, 0x52, 0x0b, 0x74, 0x65, 0x6d,
-	0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x65, 0x6d, 0x70,
-	0x6c, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09,
-	0x52, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12,
-	0x25, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x0d, 0x2e, 0x64, 0x6d, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x06,
-	0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
-	0x5f, 0x68, 0x61, 0x6c, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x68, 0x6f,
-	0x75, 0x6c, 0x64, 0x48, 0x61, 0x6c, 0x74, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x6f, 0x2e, 0x63, 0x68,
-	0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f,
-	0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76,
-	0x31, 0x3b, 0x64, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescData = file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
-var file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_goTypes = []interface{}{
-	(*TemplateInstantiation)(nil),              // 0: dm.TemplateInstantiation
-	(*EnsureGraphDataReq)(nil),                 // 1: dm.EnsureGraphDataReq
-	(*EnsureGraphDataRsp)(nil),                 // 2: dm.EnsureGraphDataRsp
-	(*EnsureGraphDataReq_Limit)(nil),           // 3: dm.EnsureGraphDataReq.Limit
-	(*EnsureGraphDataReq_Include)(nil),         // 4: dm.EnsureGraphDataReq.Include
-	(*EnsureGraphDataReq_Include_Options)(nil), // 5: dm.EnsureGraphDataReq.Include.Options
-	(*templateproto.Specifier)(nil),            // 6: templateproto.Specifier
-	(*Quest_Desc)(nil),                         // 7: dm.Quest.Desc
-	(*AttemptList_Nums)(nil),                   // 8: dm.AttemptList.Nums
-	(*AttemptList)(nil),                        // 9: dm.AttemptList
-	(*Execution_Auth)(nil),                     // 10: dm.Execution.Auth
-	(*Quest_ID)(nil),                           // 11: dm.Quest.ID
-	(*GraphData)(nil),                          // 12: dm.GraphData
-}
-var file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_depIdxs = []int32{
-	6,  // 0: dm.TemplateInstantiation.specifier:type_name -> templateproto.Specifier
-	7,  // 1: dm.EnsureGraphDataReq.quest:type_name -> dm.Quest.Desc
-	8,  // 2: dm.EnsureGraphDataReq.quest_attempt:type_name -> dm.AttemptList.Nums
-	0,  // 3: dm.EnsureGraphDataReq.template_quest:type_name -> dm.TemplateInstantiation
-	8,  // 4: dm.EnsureGraphDataReq.template_attempt:type_name -> dm.AttemptList.Nums
-	9,  // 5: dm.EnsureGraphDataReq.raw_attempts:type_name -> dm.AttemptList
-	10, // 6: dm.EnsureGraphDataReq.for_execution:type_name -> dm.Execution.Auth
-	3,  // 7: dm.EnsureGraphDataReq.limit:type_name -> dm.EnsureGraphDataReq.Limit
-	4,  // 8: dm.EnsureGraphDataReq.include:type_name -> dm.EnsureGraphDataReq.Include
-	11, // 9: dm.EnsureGraphDataRsp.quest_ids:type_name -> dm.Quest.ID
-	11, // 10: dm.EnsureGraphDataRsp.template_ids:type_name -> dm.Quest.ID
-	12, // 11: dm.EnsureGraphDataRsp.result:type_name -> dm.GraphData
-	5,  // 12: dm.EnsureGraphDataReq.Include.attempt:type_name -> dm.EnsureGraphDataReq.Include.Options
-	13, // [13:13] is the sub-list for method output_type
-	13, // [13:13] is the sub-list for method input_type
-	13, // [13:13] is the sub-list for extension type_name
-	13, // [13:13] is the sub-list for extension extendee
-	0,  // [0:13] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_init() }
-func file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_init() {
-	if File_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_init()
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_init()
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*TemplateInstantiation); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*EnsureGraphDataReq); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*EnsureGraphDataRsp); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*EnsureGraphDataReq_Limit); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*EnsureGraphDataReq_Include); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*EnsureGraphDataReq_Include_Options); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   6,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto = out.File
-	file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_depIdxs = nil
-}
diff --git a/dm/api/service/v1/ensure_graph_data.proto b/dm/api/service/v1/ensure_graph_data.proto
deleted file mode 100644
index cb2cf26..0000000
--- a/dm/api/service/v1/ensure_graph_data.proto
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/service/v1;dm";
-
-import "go.chromium.org/luci/common/data/text/templateproto/template.proto";
-import "go.chromium.org/luci/dm/api/service/v1/graph_data.proto";
-import "go.chromium.org/luci/dm/api/service/v1/types.proto";
-
-package dm;
-
-message TemplateInstantiation {
-  // project is the luci-config project which defines the template.
-  string project = 1;
-
-  // ref is the git ref of the project that defined this template. If omitted,
-  // this will use the template definition from the project-wide configuration
-  // and not the configuration located on a particular ref (like
-  // 'refs/heads/master').
-  //
-  // UNUSED.
-  string ref = 2;
-
-  // reserve 3 for luci-config version
-  reserved 3;
-
-  // specifier specifies the actual template name, as well as any substitution
-  // parameters which that template might require.
-  templateproto.Specifier specifier = 4;
-}
-
-// EnsureGraphDataReq allows you to assert the existence of Attempts in DM's
-// graph, and allows you to declare dependencies from one Attempt to another.
-//
-// You can declare Attempts by any combination of:
-//   * Providing a quest description plus a list of Attempt numbers for that
-//     quest.
-//   * Providing a template instantiation (for a project-declared quest
-//     template) plus a list of Attempt numbers for that quest.
-//   * Providing a raw set of quest_id -> attempt numbers for quests that you
-//     already know that DM has a definition for.
-//
-// In response, DM will tell you what the IDs of all supplied Quests/Attempts
-// are.
-//
-// To create a dependencies, call this method while running as part of an
-// execution by filling the for_execution field. All attempts named as described
-// above will become dependencies for the indicated execution. It is only
-// possible for a currently-running execution to create dependencies for its own
-// Attempt. In particular, it is not possible to create dependencies as
-// a non-execution user (e.g. a human), nor is it possible for an execution to
-// create attempts on behalf of some other execution.
-//
-// If the attempts were being created as dependencies, and were already in the
-// Finished state, this request can also opt to include the AttemptResults
-// directly.
-message EnsureGraphDataReq {
-  // Quest is a list of quest descriptors. DM will ensure that the
-  // corresponding Quests exist. If they don't, they'll be created.
-  repeated dm.Quest.Desc quest = 1;
-
-  // QuestAttempt allows the addition of attempts which are derived from
-  // the quest bodies provided above.
-  // Each entry here maps 1:1 with the equivalent quest.
-  repeated dm.AttemptList.Nums quest_attempt = 2;
-
-  // TemplateQuest allows the addition of quests which are derived from
-  // Templates, as defined on a per-project basis.
-  repeated TemplateInstantiation template_quest = 3;
-
-  // TemplateAttempt allows the addition of attempts which are derived from
-  // Templates. This must be equal in length to template_quest.
-  // Each entry here maps 1:1 with the equivalent quest in template_quest.
-  repeated dm.AttemptList.Nums template_attempt = 4;
-
-  // RawAttempts is a list that asserts that the following attempts should
-  // exist. The quest ids in this list must be already-known to DM, NOT
-  // included in the quest field above. This is useful when you know the ID of
-  // the Quest, but not the actual definition of the quest.
-  dm.AttemptList raw_attempts = 5;
-
-  // ForExecution is an authentication pair (Execution_ID, Token).
-  //
-  // If this is provided then it will serve as authorization for the creation of
-  // any `quests` included, and any `attempts` indicated will be set as
-  // dependencies for the execution.
-  //
-  // If this omitted, then the request requires some user/bot authentication,
-  // and any quests/attempts provided will be made standalone (e.g. nothing will
-  // depend on them).
-  dm.Execution.Auth for_execution = 6;
-
-  message Limit {
-    // to be compatible with WalkGraphReq.Limit, should we later expand this
-    // Limit message. However, right now we ONLY use max_data_size.
-    reserved 1, 2;
-
-    // MaxDataSize sets the maximum amount of 'Data' (in bytes) that can be
-    // returned, if include.attempt_result is set. If this limit is hit, then
-    // the appropriate 'partial' value will be set for that object, but the base
-    // object would still be included in the result.
-    //
-    // If this limit is 0, a default limit of 16MB will be used. If this limit
-    // exceeds 30MB, it will be reduced to 30MB.
-    uint32 max_data_size = 3;
-  }
-  Limit limit = 7;
-
-  message Include {
-    // to be compatible with WalkGraphReq.Include, should we later expand this
-    // Include message. However, right now we ONLY use attempt.
-    reserved 1, 3, 5, 6;
-
-    message Options {
-      // to be compatible with WalkGraphReq.Include.Options, should we later
-      // expand this Include.Options message. However, right now we ONLY use
-      // result.
-      reserved 1, 2, 4, 5;
-
-      // Instructs finished objects to include the Result field.
-      bool result = 3;
-    }
-
-    Options attempt = 4;
-  }
-  Include include = 8;
-}
-
-message EnsureGraphDataRsp {
-  // accepted is true when all new graph data was journaled successfully. This
-  // means that `quests`, `attempts`, `template_quest`, `template_attempt` were
-  // all well-formed and are scheduled to be added. They will 'eventually' be
-  // readable via other APIs (like WalkGraph), but when they are, they'll have
-  // the IDs reflected in this response.
-  //
-  // If `attempts` referrs to quests that don't exist and weren't provided in
-  // `quests`, those quests will be listed in `result` with the DNE flag set.
-  //
-  // If `template_quest` had errors (missing template, bad params, etc.), the
-  // errors will be located in `template_error`. If all of the templates parsed
-  // successfully, the quest ids for those rendered `template_quest` will be in
-  // `template_ids`.
-  bool accepted = 1;
-
-  // quest_ids will be populated with the Quest.IDs of any quests defined
-  // by quest in the initial request. Its length is guaranteed to match
-  // the length of quest, if there were no errors.
-  repeated dm.Quest.ID quest_ids = 2;
-
-  // template_ids will be populated with the Quest.IDs of any templates defined
-  // by template_quest in the initial request. Its length is guaranteed to match
-  // the length of template_quest, if there were no errors.
-  repeated dm.Quest.ID template_ids = 3;
-
-  // template_error is either empty if there were no template errors, or the
-  // length of template_quest. Non-empty strings are errors.
-  repeated string template_error = 4;
-
-  // result holds the graph data pertaining to the request, containing any
-  // graph state that already existed at the time of the call. Any new data
-  // that was added to the graph state (accepted==true) will appear with
-  // `DNE==true`.
-  //
-  // Quest data will always be returned for any Quests which exist.
-  //
-  // If accepted==false, you can inspect this to determine why:
-  //   * Quests (without data) mentioned by the `attempts` field that do not
-  //     exist will have `DNE==true`.
-  //
-  // This also can be used to make adding dependencies a stateless
-  // single-request action:
-  //   * Attempts requested (assuming the corresponding Quest exists) will
-  //     contain their current state. If Include.AttemptResult was true, the
-  //     results will be populated (with the size limit mentioned in the request
-  //     documentation).
-  dm.GraphData result = 5;
-
-  // (if `for_execution` was specified) ShouldHalt indicates that the request
-  // was accepted by DM, and the execution should halt (DM will re-execute the
-  // Attempt when it becomes unblocked). If this is true, then the execution's
-  // auth Token is also revoked and will no longer work for futher API calls.
-  //
-  // If `for_execution` was provided in the request and this is false, it means
-  // that the execution may continue executing.
-  bool should_halt = 6;
-}
diff --git a/dm/api/service/v1/ensure_graph_data_normalize.go b/dm/api/service/v1/ensure_graph_data_normalize.go
deleted file mode 100644
index f3fe9b5..0000000
--- a/dm/api/service/v1/ensure_graph_data_normalize.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"fmt"
-
-	"go.chromium.org/luci/common/errors"
-)
-
-// Normalize returns an error iff the TemplateInstantiation is invalid.
-func (t *TemplateInstantiation) Normalize() error {
-	if t.Project == "" {
-		return errors.New("empty project")
-	}
-	return t.Specifier.Normalize()
-}
-
-func checkAttemptNums(name string, lst []*AttemptList_Nums) error {
-	for i, nums := range lst {
-		if err := nums.Normalize(); err != nil {
-			return fmt.Errorf("%s[%d]: %s", name, i, err)
-		}
-		if len(nums.Nums) == 0 {
-			return fmt.Errorf("%s[%d]: empty attempt list", name, i)
-		}
-	}
-	return nil
-}
-
-// Normalize returns an error iff the request is invalid.
-func (r *EnsureGraphDataReq) Normalize() error {
-	if r.ForExecution != nil {
-		if err := r.ForExecution.Normalize(); err != nil {
-			return err
-		}
-	}
-
-	if err := r.RawAttempts.Normalize(); err != nil {
-		return err
-	}
-
-	hasAttempts := false
-	if r.RawAttempts != nil {
-		for _, nums := range r.RawAttempts.To {
-			if len(nums.Nums) == 0 {
-				return errors.New("EnsureGraphDataReq.attempts must only include valid (non-0, non-empty) attempt numbers")
-			}
-			hasAttempts = true
-		}
-	}
-
-	if len(r.Quest) != len(r.QuestAttempt) {
-		return errors.New("mismatched quest_attempt v. quest lengths")
-	}
-
-	if len(r.TemplateQuest) != len(r.TemplateAttempt) {
-		return errors.New("mismatched template_attempt v. template_quest lengths")
-	}
-
-	if err := checkAttemptNums("template_attempts", r.TemplateAttempt); err != nil {
-		return err
-	}
-
-	for i, q := range r.TemplateQuest {
-		if err := q.Normalize(); err != nil {
-			return fmt.Errorf("template_quests[%d]: %s", i, err)
-		}
-	}
-
-	if err := checkAttemptNums("quest_attempt", r.QuestAttempt); err != nil {
-		return err
-	}
-
-	for i, desc := range r.Quest {
-		if err := desc.Normalize(); err != nil {
-			return fmt.Errorf("quest[%d]: %s", i, err)
-		}
-	}
-
-	if len(r.Quest) == 0 && len(r.TemplateQuest) == 0 && !hasAttempts {
-		return errors.New("EnsureGraphDataReq must have at least one of quests, template_quests and raw_attempts")
-	}
-
-	if r.Limit == nil {
-		r.Limit = &EnsureGraphDataReq_Limit{}
-	}
-	if r.Limit.MaxDataSize == 0 {
-		r.Limit.MaxDataSize = DefaultLimitMaxDataSize
-	}
-	if r.Limit.MaxDataSize > MaxLimitMaxDataSize {
-		r.Limit.MaxDataSize = MaxLimitMaxDataSize
-	}
-
-	if r.Include == nil {
-		r.Include = &EnsureGraphDataReq_Include{Attempt: &EnsureGraphDataReq_Include_Options{}}
-	} else if r.Include.Attempt == nil {
-		r.Include.Attempt = &EnsureGraphDataReq_Include_Options{}
-	}
-	return nil
-}
diff --git a/dm/api/service/v1/execution_data.go b/dm/api/service/v1/execution_data.go
deleted file mode 100644
index 79ab2cb..0000000
--- a/dm/api/service/v1/execution_data.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import "errors"
-
-// NewExecutionScheduling creates an Execution in the SCHEDULING state.
-func NewExecutionScheduling() *Execution {
-	return &Execution{
-		Data: &Execution_Data{
-			ExecutionType: &Execution_Data_Scheduling_{
-				&Execution_Data_Scheduling{}}}}
-}
-
-// NewExecutionRunning creates an Execution in the RUNNING state.
-func NewExecutionRunning() *Execution {
-	return &Execution{
-		Data: &Execution_Data{
-			ExecutionType: &Execution_Data_Running_{
-				&Execution_Data_Running{}}}}
-}
-
-// NewExecutionStopping creates an Execution in the STOPPING state.
-func NewExecutionStopping() *Execution {
-	return &Execution{
-		Data: &Execution_Data{
-			ExecutionType: &Execution_Data_Stopping_{
-				&Execution_Data_Stopping{}}}}
-}
-
-// NewExecutionFinished creates an Execution in the FINISHED state.
-func NewExecutionFinished(result *JsonResult) *Execution {
-	return &Execution{
-		Data: &Execution_Data{
-			ExecutionType: &Execution_Data_Finished_{
-				&Execution_Data_Finished{Data: result}}}}
-}
-
-// NewExecutionAbnormalFinish creates an Execution in the ABNORMAL_FINISH state.
-func NewExecutionAbnormalFinish(af *AbnormalFinish) *Execution {
-	return &Execution{
-		Data: &Execution_Data{
-			ExecutionType: &Execution_Data_AbnormalFinish{af}}}
-}
-
-// State computes the Execution_State for the current Execution_Data
-func (d *Execution_Data) State() Execution_State {
-	if d != nil {
-		switch d.ExecutionType.(type) {
-		case *Execution_Data_Scheduling_:
-			return Execution_SCHEDULING
-		case *Execution_Data_Running_:
-			return Execution_RUNNING
-		case *Execution_Data_Stopping_:
-			return Execution_STOPPING
-		case *Execution_Data_Finished_:
-			return Execution_FINISHED
-		case *Execution_Data_AbnormalFinish:
-			return Execution_ABNORMAL_FINISHED
-		}
-	}
-	return Execution_SCHEDULING
-}
-
-// Normalize returns an error iff the Execution_Auth has invalid form (e.g.
-// contains nils).
-func (a *Execution_Auth) Normalize() error {
-	if a == nil {
-		return errors.New("Execution_Auth is nil")
-	}
-	if a.Id == nil {
-		return errors.New("Execution_Auth.Id is nil")
-	}
-	return nil
-}
diff --git a/dm/api/service/v1/execution_state_evolve.go b/dm/api/service/v1/execution_state_evolve.go
deleted file mode 100644
index ad12128..0000000
--- a/dm/api/service/v1/execution_state_evolve.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"fmt"
-)
-
-// validExecutionStateEvolution defines all valid {From -> []To} state
-// transitions. The identity transition (X -> X) is implied, as long as X has an
-// entry in this mapping.
-var validExecutionStateEvolution = map[Execution_State][]Execution_State{
-	Execution_SCHEDULING: {
-		Execution_RUNNING,           // ActivateExecution
-		Execution_ABNORMAL_FINISHED, // cancel/timeout/err/etc.
-	},
-	Execution_RUNNING: {
-		Execution_STOPPING,          // FinishAttempt/EnsureGraphData
-		Execution_ABNORMAL_FINISHED, // cancel/timeout/err/etc.
-	},
-	Execution_STOPPING: {
-		Execution_FINISHED,          // got persistent state from distributor
-		Execution_ABNORMAL_FINISHED, // cancel/timeout/err/etc.
-	},
-
-	Execution_FINISHED:          {},
-	Execution_ABNORMAL_FINISHED: {},
-}
-
-// Evolve attempts to evolve the state of this Attempt. If the state
-// evolution is not allowed (e.g. invalid state transition), this returns an
-// error.
-func (s *Execution_State) Evolve(newState Execution_State) error {
-	nextStates := validExecutionStateEvolution[*s]
-	if nextStates == nil {
-		return fmt.Errorf("invalid state transition: no transitions defined for %s", *s)
-	}
-
-	if newState == *s {
-		return nil
-	}
-
-	for _, val := range nextStates {
-		if newState == val {
-			*s = newState
-			return nil
-		}
-	}
-
-	return fmt.Errorf("invalid state transition %v -> %v", *s, newState)
-}
-
-// MustEvolve is a panic'ing version of Evolve.
-func (s *Execution_State) MustEvolve(newState Execution_State) {
-	err := s.Evolve(newState)
-	if err != nil {
-		panic(err)
-	}
-}
-
-// Terminal returns true iff there are no valid evolutions from the current
-// state.
-func (s Execution_State) Terminal() bool {
-	return len(validExecutionStateEvolution[s]) == 0
-}
diff --git a/dm/api/service/v1/execution_state_evolve_test.go b/dm/api/service/v1/execution_state_evolve_test.go
deleted file mode 100644
index 5cf7788..0000000
--- a/dm/api/service/v1/execution_state_evolve_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestExecutionState(t *testing.T) {
-	t.Parallel()
-
-	Convey("Evolve", t, func() {
-		Convey("Identity", func() {
-			s := Execution_SCHEDULING
-			So(s.Evolve(Execution_SCHEDULING), ShouldBeNil)
-			So(s, ShouldEqual, Execution_SCHEDULING)
-		})
-
-		Convey("Transition", func() {
-			s := Execution_RUNNING
-			So(s.Evolve(Execution_STOPPING), ShouldBeNil)
-			So(s, ShouldEqual, Execution_STOPPING)
-		})
-
-		Convey("Invalid starting transistion", func() {
-			s := Execution_FINISHED
-			So(s.Evolve(Execution_SCHEDULING), ShouldErrLike, "invalid state transition FINISHED -> SCHEDULING")
-			So(s, ShouldEqual, Execution_FINISHED)
-		})
-
-		Convey("Invalid ending transistion", func() {
-			s := Execution_RUNNING
-			So(s.Evolve(Execution_SCHEDULING), ShouldErrLike, "invalid state transition RUNNING -> SCHEDULING")
-			So(s, ShouldEqual, Execution_RUNNING)
-		})
-
-		Convey("MustEvolve", func() {
-			s := Execution_FINISHED
-			So(func() { s.MustEvolve(Execution_SCHEDULING) }, ShouldPanic)
-		})
-	})
-}
diff --git a/dm/api/service/v1/finish_attempt.pb.go b/dm/api/service/v1/finish_attempt.pb.go
deleted file mode 100644
index c2ef08d..0000000
--- a/dm/api/service/v1/finish_attempt.pb.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/service/v1/finish_attempt.proto
-
-package dm
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// FinishAttemptReq sets the final result of an Attempt.
-type FinishAttemptReq struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// required
-	Auth *Execution_Auth `protobuf:"bytes,1,opt,name=auth,proto3" json:"auth,omitempty"`
-	// The result data for this Attempt. The `size` field is recalculated after
-	// the data field is normalized, and may be omitted.
-	Data *JsonResult `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
-}
-
-func (x *FinishAttemptReq) Reset() {
-	*x = FinishAttemptReq{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *FinishAttemptReq) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*FinishAttemptReq) ProtoMessage() {}
-
-func (x *FinishAttemptReq) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use FinishAttemptReq.ProtoReflect.Descriptor instead.
-func (*FinishAttemptReq) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *FinishAttemptReq) GetAuth() *Execution_Auth {
-	if x != nil {
-		return x.Auth
-	}
-	return nil
-}
-
-func (x *FinishAttemptReq) GetData() *JsonResult {
-	if x != nil {
-		return x.Data
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDesc = []byte{
-	0x0a, 0x3b, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x5f,
-	0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x64,
-	0x6d, 0x1a, 0x37, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f,
-	0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73,
-	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f,
-	0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5e, 0x0a, 0x10, 0x46, 0x69,
-	0x6e, 0x69, 0x73, 0x68, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x12, 0x26,
-	0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64,
-	0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x75, 0x74, 0x68,
-	0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x64, 0x6d, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x52, 0x65,
-	0x73, 0x75, 0x6c, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x6f,
-	0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75,
-	0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
-	0x65, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDescData = file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_goTypes = []interface{}{
-	(*FinishAttemptReq)(nil), // 0: dm.FinishAttemptReq
-	(*Execution_Auth)(nil),   // 1: dm.Execution.Auth
-	(*JsonResult)(nil),       // 2: dm.JsonResult
-}
-var file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_depIdxs = []int32{
-	1, // 0: dm.FinishAttemptReq.auth:type_name -> dm.Execution.Auth
-	2, // 1: dm.FinishAttemptReq.data:type_name -> dm.JsonResult
-	2, // [2:2] is the sub-list for method output_type
-	2, // [2:2] is the sub-list for method input_type
-	2, // [2:2] is the sub-list for extension type_name
-	2, // [2:2] is the sub-list for extension extendee
-	0, // [0:2] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_init() }
-func file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_init() {
-	if File_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_init()
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*FinishAttemptReq); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   1,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto = out.File
-	file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_depIdxs = nil
-}
diff --git a/dm/api/service/v1/finish_attempt.proto b/dm/api/service/v1/finish_attempt.proto
deleted file mode 100644
index aaa98bc..0000000
--- a/dm/api/service/v1/finish_attempt.proto
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/service/v1;dm";
-
-import "go.chromium.org/luci/dm/api/service/v1/graph_data.proto";
-
-package dm;
-
-// FinishAttemptReq sets the final result of an Attempt.
-message FinishAttemptReq {
-  // required
-  dm.Execution.Auth auth = 1;
-
-  // The result data for this Attempt. The `size` field is recalculated after
-  // the data field is normalized, and may be omitted.
-  JsonResult data = 2;
-}
diff --git a/dm/api/service/v1/finish_attempt_normalize.go b/dm/api/service/v1/finish_attempt_normalize.go
deleted file mode 100644
index 23fd824..0000000
--- a/dm/api/service/v1/finish_attempt_normalize.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import "errors"
-
-// Normalize returns an error iff the ActivateExecutionReq has bad form (nils,
-// insufficient activation token length, etc.
-func (a *FinishAttemptReq) Normalize() error {
-	if err := a.Auth.Normalize(); err != nil {
-		return err
-	}
-	if err := a.Data.Normalize(); err != nil {
-		return err
-	}
-	if a.Data == nil || len(a.Data.Object) == 0 {
-		return errors.New("data field is required")
-	}
-	return nil
-}
diff --git a/dm/api/service/v1/gen.go b/dm/api/service/v1/gen.go
deleted file mode 100644
index 32bef68..0000000
--- a/dm/api/service/v1/gen.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-//go:generate cproto
-//go:generate proto-gae -type Quest_Desc -type Quest_TemplateSpec -type AbnormalFinish -type Execution_Auth -type JsonResult -type Result
-//go:generate svcdec -type DepsServer
diff --git a/dm/api/service/v1/graph_data.pb.go b/dm/api/service/v1/graph_data.pb.go
deleted file mode 100644
index 925df0a..0000000
--- a/dm/api/service/v1/graph_data.pb.go
+++ /dev/null
@@ -1,3133 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/service/v1/graph_data.proto
-
-package dm
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	durationpb "google.golang.org/protobuf/types/known/durationpb"
-	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type AbnormalFinish_Status int32
-
-const (
-	// This status is invalid and should not be used intentionally.
-	//
-	// It is a placeholder to identify 0-initialized AbnormalFinish structures.
-	AbnormalFinish_INVALID AbnormalFinish_Status = 0
-	// This entity has a failed result.
-	//
-	// Executions: the distributor reported that the task executed and failed, OR
-	// the distributor reports success while the Execution is in the RUNNING
-	// state.
-	//
-	// Attempts: the last Execution had a FAILED Status.
-	//
-	// Retryable.
-	AbnormalFinish_FAILED AbnormalFinish_Status = 1
-	// This entity failed in a bad way.
-	//
-	// Executions: The distributor told us that the job died violently while in
-	// the SCHEDULING, RUNNING or STOPPING state.
-	//
-	// Attempts: the last Execution had a CRASHED Status.
-	//
-	// Retryable.
-	AbnormalFinish_CRASHED AbnormalFinish_Status = 2
-	// Waited too long for the job to start.
-	//
-	// Executions: the distributor couldn't start the job in time, OR DM failed
-	// to get a status update from the distributor in time (e.g. the state was
-	// SCHEDULING for too long).
-	//
-	// Attempts: the last Execution had an EXPIRED Status.
-	//
-	// Retryable.
-	AbnormalFinish_EXPIRED AbnormalFinish_Status = 3
-	// The job started, but took too long.
-	//
-	// Executions: the distributor started the job, but it couldn't complete in
-	// time, OR DM failed to get a status update from the distributor in time
-	// (e.g. the state was RUNNING for too long).
-	//
-	// Attempts: the last Execution had an TIMED_OUT Status.
-	//
-	// Retryable.
-	AbnormalFinish_TIMED_OUT AbnormalFinish_Status = 4
-	// The job was cancelled by an external entity (human, automated system).
-	//
-	// Executions: the distributor informing DM that the job was preemptively
-	// cancelled.
-	//
-	// Attempts: the last Execution had a CANCELLED Status, or this Attempt
-	// was cancelled via DM.
-	AbnormalFinish_CANCELLED AbnormalFinish_Status = 5
-	// The job was prevented from running by the distributor (quota, permissions,
-	// etc.)
-	//
-	// Executions: the distributor refused to run this job.
-	//
-	// Attempts: the last Execution had a REJECTED Status.
-	AbnormalFinish_REJECTED AbnormalFinish_Status = 6
-	// The job is unrecognized.
-	//
-	// Executions: the distributor doesn't know about this job, or has forgotten
-	// about it.
-	//
-	// Attempts: the last Execution had a MISSING Status.
-	AbnormalFinish_MISSING AbnormalFinish_Status = 7
-	// The distributor ran the job, but returned garbage.
-	//
-	// Executions: the distributor returned a nominally successful result, but
-	// the Data portion of the result wasn't able to be normalized.
-	//
-	// Attempts: the last Execution had a RESULT_MALFORMED Status.
-	AbnormalFinish_RESULT_MALFORMED AbnormalFinish_Status = 8
-)
-
-// Enum value maps for AbnormalFinish_Status.
-var (
-	AbnormalFinish_Status_name = map[int32]string{
-		0: "INVALID",
-		1: "FAILED",
-		2: "CRASHED",
-		3: "EXPIRED",
-		4: "TIMED_OUT",
-		5: "CANCELLED",
-		6: "REJECTED",
-		7: "MISSING",
-		8: "RESULT_MALFORMED",
-	}
-	AbnormalFinish_Status_value = map[string]int32{
-		"INVALID":          0,
-		"FAILED":           1,
-		"CRASHED":          2,
-		"EXPIRED":          3,
-		"TIMED_OUT":        4,
-		"CANCELLED":        5,
-		"REJECTED":         6,
-		"MISSING":          7,
-		"RESULT_MALFORMED": 8,
-	}
-)
-
-func (x AbnormalFinish_Status) Enum() *AbnormalFinish_Status {
-	p := new(AbnormalFinish_Status)
-	*p = x
-	return p
-}
-
-func (x AbnormalFinish_Status) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (AbnormalFinish_Status) Descriptor() protoreflect.EnumDescriptor {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes[0].Descriptor()
-}
-
-func (AbnormalFinish_Status) Type() protoreflect.EnumType {
-	return &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes[0]
-}
-
-func (x AbnormalFinish_Status) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Use AbnormalFinish_Status.Descriptor instead.
-func (AbnormalFinish_Status) EnumDescriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{0, 0}
-}
-
-type Attempt_State int32
-
-const (
-	// The Attempt is waiting to be Executed.
-	Attempt_SCHEDULING Attempt_State = 0
-	// The Attempt is currently waiting for its current Execution to finish.
-	Attempt_EXECUTING Attempt_State = 1
-	// The Attempt is waiting for dependent Attempts to be resolved.
-	Attempt_WAITING Attempt_State = 2
-	// The Attempt is in its final state.
-	Attempt_FINISHED Attempt_State = 3
-	// The Attempt is in an abnormal final state.
-	Attempt_ABNORMAL_FINISHED Attempt_State = 4
-)
-
-// Enum value maps for Attempt_State.
-var (
-	Attempt_State_name = map[int32]string{
-		0: "SCHEDULING",
-		1: "EXECUTING",
-		2: "WAITING",
-		3: "FINISHED",
-		4: "ABNORMAL_FINISHED",
-	}
-	Attempt_State_value = map[string]int32{
-		"SCHEDULING":        0,
-		"EXECUTING":         1,
-		"WAITING":           2,
-		"FINISHED":          3,
-		"ABNORMAL_FINISHED": 4,
-	}
-)
-
-func (x Attempt_State) Enum() *Attempt_State {
-	p := new(Attempt_State)
-	*p = x
-	return p
-}
-
-func (x Attempt_State) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (Attempt_State) Descriptor() protoreflect.EnumDescriptor {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes[1].Descriptor()
-}
-
-func (Attempt_State) Type() protoreflect.EnumType {
-	return &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes[1]
-}
-
-func (x Attempt_State) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Use Attempt_State.Descriptor instead.
-func (Attempt_State) EnumDescriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 0}
-}
-
-type Attempt_Partial_Result int32
-
-const (
-	// LOADED implies that the result was, in fact, loaded.
-	Attempt_Partial_LOADED Attempt_Partial_Result = 0
-	// NOT_LOADED is set if the result failed to load because there was
-	// a transient error or the request ran out of time.
-	Attempt_Partial_NOT_LOADED Attempt_Partial_Result = 1
-	// NOT_AUTHORIZED is set if the query was authenticated from an Execution
-	// whose Attempt doesn't depend on this one.
-	Attempt_Partial_NOT_AUTHORIZED Attempt_Partial_Result = 2
-	// DATA_SIZE_LIMIT is set if the max_data_size limit was reached.
-	Attempt_Partial_DATA_SIZE_LIMIT Attempt_Partial_Result = 3
-)
-
-// Enum value maps for Attempt_Partial_Result.
-var (
-	Attempt_Partial_Result_name = map[int32]string{
-		0: "LOADED",
-		1: "NOT_LOADED",
-		2: "NOT_AUTHORIZED",
-		3: "DATA_SIZE_LIMIT",
-	}
-	Attempt_Partial_Result_value = map[string]int32{
-		"LOADED":          0,
-		"NOT_LOADED":      1,
-		"NOT_AUTHORIZED":  2,
-		"DATA_SIZE_LIMIT": 3,
-	}
-)
-
-func (x Attempt_Partial_Result) Enum() *Attempt_Partial_Result {
-	p := new(Attempt_Partial_Result)
-	*p = x
-	return p
-}
-
-func (x Attempt_Partial_Result) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (Attempt_Partial_Result) Descriptor() protoreflect.EnumDescriptor {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes[2].Descriptor()
-}
-
-func (Attempt_Partial_Result) Type() protoreflect.EnumType {
-	return &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes[2]
-}
-
-func (x Attempt_Partial_Result) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Use Attempt_Partial_Result.Descriptor instead.
-func (Attempt_Partial_Result) EnumDescriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 3, 0}
-}
-
-type Execution_State int32
-
-const (
-	// The execution has been accepted by the distributor, but is not running
-	// yet.
-	Execution_SCHEDULING Execution_State = 0
-	// The execution is running (has activated with DM).
-	Execution_RUNNING Execution_State = 1
-	// The execution has been told to stop by DM, but we haven't heard from
-	// the distributor yet.
-	Execution_STOPPING Execution_State = 2
-	// The execution is in its final state.
-	Execution_FINISHED Execution_State = 3
-	// The execution is in an abnormal final state
-	Execution_ABNORMAL_FINISHED Execution_State = 4
-)
-
-// Enum value maps for Execution_State.
-var (
-	Execution_State_name = map[int32]string{
-		0: "SCHEDULING",
-		1: "RUNNING",
-		2: "STOPPING",
-		3: "FINISHED",
-		4: "ABNORMAL_FINISHED",
-	}
-	Execution_State_value = map[string]int32{
-		"SCHEDULING":        0,
-		"RUNNING":           1,
-		"STOPPING":          2,
-		"FINISHED":          3,
-		"ABNORMAL_FINISHED": 4,
-	}
-)
-
-func (x Execution_State) Enum() *Execution_State {
-	p := new(Execution_State)
-	*p = x
-	return p
-}
-
-func (x Execution_State) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (Execution_State) Descriptor() protoreflect.EnumDescriptor {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes[3].Descriptor()
-}
-
-func (Execution_State) Type() protoreflect.EnumType {
-	return &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes[3]
-}
-
-func (x Execution_State) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Use Execution_State.Descriptor instead.
-func (Execution_State) EnumDescriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 0}
-}
-
-type AbnormalFinish struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Status AbnormalFinish_Status `protobuf:"varint,1,opt,name=status,proto3,enum=dm.AbnormalFinish_Status" json:"status,omitempty"`
-	Reason string                `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"`
-}
-
-func (x *AbnormalFinish) Reset() {
-	*x = AbnormalFinish{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *AbnormalFinish) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AbnormalFinish) ProtoMessage() {}
-
-func (x *AbnormalFinish) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use AbnormalFinish.ProtoReflect.Descriptor instead.
-func (*AbnormalFinish) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *AbnormalFinish) GetStatus() AbnormalFinish_Status {
-	if x != nil {
-		return x.Status
-	}
-	return AbnormalFinish_INVALID
-}
-
-func (x *AbnormalFinish) GetReason() string {
-	if x != nil {
-		return x.Reason
-	}
-	return ""
-}
-
-type Quest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Id *Quest_ID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	// DNE is set to true if this Quest does not exist. None of the following
-	// fields are valid if this is set to true.
-	DNE  bool        `protobuf:"varint,2,opt,name=DNE,proto3" json:"DNE,omitempty"`
-	Data *Quest_Data `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
-	// key is the `id` field of the Attempt.ID
-	Attempts map[uint32]*Attempt `protobuf:"bytes,4,rep,name=attempts,proto3" json:"attempts,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	// Partial is true iff the request asked for QuestData, but wasn't able to
-	// completely fill it.
-	Partial bool `protobuf:"varint,16,opt,name=partial,proto3" json:"partial,omitempty"`
-}
-
-func (x *Quest) Reset() {
-	*x = Quest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Quest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Quest) ProtoMessage() {}
-
-func (x *Quest) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Quest.ProtoReflect.Descriptor instead.
-func (*Quest) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{1}
-}
-
-func (x *Quest) GetId() *Quest_ID {
-	if x != nil {
-		return x.Id
-	}
-	return nil
-}
-
-func (x *Quest) GetDNE() bool {
-	if x != nil {
-		return x.DNE
-	}
-	return false
-}
-
-func (x *Quest) GetData() *Quest_Data {
-	if x != nil {
-		return x.Data
-	}
-	return nil
-}
-
-func (x *Quest) GetAttempts() map[uint32]*Attempt {
-	if x != nil {
-		return x.Attempts
-	}
-	return nil
-}
-
-func (x *Quest) GetPartial() bool {
-	if x != nil {
-		return x.Partial
-	}
-	return false
-}
-
-// JsonResult represents a free-form JSON object. It has a maximum size of
-// 256KB normalized (no extra whitespace). DM will normalize incoming
-// JSONObjects before recalculating their size.
-type JsonResult struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Guaranteed to be a JSON object `{...}` or the empty string (if this is part
-	// of a Partial result from e.g. a WalkGraph RPC).
-	Object string `protobuf:"bytes,1,opt,name=object,proto3" json:"object,omitempty"`
-	// The length of data. If this message is non-nil, this will have a value even
-	// if object is empty (e.g. for a partial result). This is useful for query
-	// results where you either opt to not load the data (include.*.data ==
-	// false), or the response exceeds the size limit (so you can see how big the
-	// data would have been if the limit wasn't exceeded).
-	Size uint32 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
-	// The timestamp of when this JsonResult's contents expire. If omitted, it
-	// should be assumed that the contents never expire.
-	Expiration *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=expiration,proto3" json:"expiration,omitempty"`
-}
-
-func (x *JsonResult) Reset() {
-	*x = JsonResult{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *JsonResult) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*JsonResult) ProtoMessage() {}
-
-func (x *JsonResult) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use JsonResult.ProtoReflect.Descriptor instead.
-func (*JsonResult) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{2}
-}
-
-func (x *JsonResult) GetObject() string {
-	if x != nil {
-		return x.Object
-	}
-	return ""
-}
-
-func (x *JsonResult) GetSize() uint32 {
-	if x != nil {
-		return x.Size
-	}
-	return 0
-}
-
-func (x *JsonResult) GetExpiration() *timestamppb.Timestamp {
-	if x != nil {
-		return x.Expiration
-	}
-	return nil
-}
-
-// Result holds either data OR abnormal finish information.
-type Result struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Data           *JsonResult     `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
-	AbnormalFinish *AbnormalFinish `protobuf:"bytes,2,opt,name=abnormal_finish,json=abnormalFinish,proto3" json:"abnormal_finish,omitempty"`
-}
-
-func (x *Result) Reset() {
-	*x = Result{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[3]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Result) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Result) ProtoMessage() {}
-
-func (x *Result) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[3]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Result.ProtoReflect.Descriptor instead.
-func (*Result) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{3}
-}
-
-func (x *Result) GetData() *JsonResult {
-	if x != nil {
-		return x.Data
-	}
-	return nil
-}
-
-func (x *Result) GetAbnormalFinish() *AbnormalFinish {
-	if x != nil {
-		return x.AbnormalFinish
-	}
-	return nil
-}
-
-type Attempt struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Id *Attempt_ID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	// DNE is set to true if this Attempt does not exist. None of the following
-	// fields are valid if this is set to true.
-	DNE  bool          `protobuf:"varint,2,opt,name=DNE,proto3" json:"DNE,omitempty"`
-	Data *Attempt_Data `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
-	// key is the `id` field of the Execution.ID
-	Executions map[uint32]*Execution `protobuf:"bytes,4,rep,name=executions,proto3" json:"executions,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	FwdDeps    *AttemptList          `protobuf:"bytes,5,opt,name=fwd_deps,json=fwdDeps,proto3" json:"fwd_deps,omitempty"`
-	BackDeps   *AttemptList          `protobuf:"bytes,6,opt,name=back_deps,json=backDeps,proto3" json:"back_deps,omitempty"`
-	// Partial values are true iff the request asked for AttemptData, Executions
-	// or Deps, but wasn't able to completely fill them. If Partial is omitted,
-	// it means that no partial data exists in this Attempt.
-	Partial *Attempt_Partial `protobuf:"bytes,16,opt,name=partial,proto3" json:"partial,omitempty"`
-}
-
-func (x *Attempt) Reset() {
-	*x = Attempt{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[4]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Attempt) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Attempt) ProtoMessage() {}
-
-func (x *Attempt) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[4]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Attempt.ProtoReflect.Descriptor instead.
-func (*Attempt) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4}
-}
-
-func (x *Attempt) GetId() *Attempt_ID {
-	if x != nil {
-		return x.Id
-	}
-	return nil
-}
-
-func (x *Attempt) GetDNE() bool {
-	if x != nil {
-		return x.DNE
-	}
-	return false
-}
-
-func (x *Attempt) GetData() *Attempt_Data {
-	if x != nil {
-		return x.Data
-	}
-	return nil
-}
-
-func (x *Attempt) GetExecutions() map[uint32]*Execution {
-	if x != nil {
-		return x.Executions
-	}
-	return nil
-}
-
-func (x *Attempt) GetFwdDeps() *AttemptList {
-	if x != nil {
-		return x.FwdDeps
-	}
-	return nil
-}
-
-func (x *Attempt) GetBackDeps() *AttemptList {
-	if x != nil {
-		return x.BackDeps
-	}
-	return nil
-}
-
-func (x *Attempt) GetPartial() *Attempt_Partial {
-	if x != nil {
-		return x.Partial
-	}
-	return nil
-}
-
-type Execution struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Id   *Execution_ID   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Data *Execution_Data `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
-	// Partial is true iff the request asked for Executions, but wasn't able to
-	// completely fill them.
-	Partial bool `protobuf:"varint,16,opt,name=partial,proto3" json:"partial,omitempty"`
-}
-
-func (x *Execution) Reset() {
-	*x = Execution{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[5]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution) ProtoMessage() {}
-
-func (x *Execution) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[5]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution.ProtoReflect.Descriptor instead.
-func (*Execution) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5}
-}
-
-func (x *Execution) GetId() *Execution_ID {
-	if x != nil {
-		return x.Id
-	}
-	return nil
-}
-
-func (x *Execution) GetData() *Execution_Data {
-	if x != nil {
-		return x.Data
-	}
-	return nil
-}
-
-func (x *Execution) GetPartial() bool {
-	if x != nil {
-		return x.Partial
-	}
-	return false
-}
-
-// GraphData defines all of the DM graph data that may be returned from DM.
-//
-// Currently only WalkGraph returns GraphData, but in the future other APIs will
-// explore the graph in other ways, and they'll return this same data structure.
-//
-// The design of this message is intended to allow clients to easily accumulate
-// various GraphData from different sources in order to maintain an in-memory
-// cache of data that exists in DM, where that data is discovered across
-// multiple RPCs.
-type GraphData struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Quests is the main entry point for all the graph data.
-	// key is the `id` field of the QuestID
-	Quests map[string]*Quest `protobuf:"bytes,1,rep,name=quests,proto3" json:"quests,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	// HadErrors is set to true if the data represented here is a partial view
-	// of the requested data due to internal errors. The request may be repeated
-	// or the client may chose to make smaller queries into the portions of the
-	// graph that are missing.
-	//
-	// If HadErrors is set HadMore will also be set.
-	HadErrors bool `protobuf:"varint,2,opt,name=had_errors,json=hadErrors,proto3" json:"had_errors,omitempty"`
-	// HadMore is set to true if the request stopped short of the full query
-	// result set due to things like:
-	//   * max response size limit
-	//   * max time limit (e.g. WalkGraphReq.MaxTime) being hit
-	//   * non-terminal errors encountered during the request (HadErrors will also
-	//     be true in this case).
-	//
-	// Note that this is different than the Partial booleans: This refers
-	// specifically to situations when Queries do not run to completion.
-	HadMore bool `protobuf:"varint,3,opt,name=had_more,json=hadMore,proto3" json:"had_more,omitempty"`
-}
-
-func (x *GraphData) Reset() {
-	*x = GraphData{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[6]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *GraphData) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GraphData) ProtoMessage() {}
-
-func (x *GraphData) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[6]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GraphData.ProtoReflect.Descriptor instead.
-func (*GraphData) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{6}
-}
-
-func (x *GraphData) GetQuests() map[string]*Quest {
-	if x != nil {
-		return x.Quests
-	}
-	return nil
-}
-
-func (x *GraphData) GetHadErrors() bool {
-	if x != nil {
-		return x.HadErrors
-	}
-	return false
-}
-
-func (x *GraphData) GetHadMore() bool {
-	if x != nil {
-		return x.HadMore
-	}
-	return false
-}
-
-type Quest_ID struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-}
-
-func (x *Quest_ID) Reset() {
-	*x = Quest_ID{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[7]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Quest_ID) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Quest_ID) ProtoMessage() {}
-
-func (x *Quest_ID) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[7]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Quest_ID.ProtoReflect.Descriptor instead.
-func (*Quest_ID) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{1, 0}
-}
-
-func (x *Quest_ID) GetId() string {
-	if x != nil {
-		return x.Id
-	}
-	return ""
-}
-
-type Quest_Desc struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// This names a specific distributor configuration (or alias) in the
-	// service's distributors.cfg file. This will be used to look up the
-	// distributor's implementation and connection information when Attempts for
-	// this Quest are Executed.
-	DistributorConfigName string `protobuf:"bytes,1,opt,name=distributor_config_name,json=distributorConfigName,proto3" json:"distributor_config_name,omitempty"`
-	// A JSON object which corresponds to the input parameters for the job.
-	// These will be passed in a distributor-specific way to the job. This is
-	// a freeform JSON object, and must parse as such, but otherwise doesn't
-	// necessarily have a server-enforced schema.
-	//
-	// The distributor implementation in DM will not use the contents of these
-	// to make any scheduling decisions.
-	//
-	// The distributor MAY choose to validate some schema for these parameters.
-	Parameters string `protobuf:"bytes,2,opt,name=parameters,proto3" json:"parameters,omitempty"`
-	// A JSON object which corresponds to the distributor-specific parameters
-	// for the job.
-	//
-	// The distributor defines and validates the schema for these, and will use
-	// the values herein to make decisions about how the job is run. It is up to
-	// the distributor whether these values are passed on to the job, and if so
-	// in what form.
-	DistributorParameters string `protobuf:"bytes,3,opt,name=distributor_parameters,json=distributorParameters,proto3" json:"distributor_parameters,omitempty"`
-	// This is metadata which doesn't affect the functionality of the payload,
-	// but does affect how DM interacts with the distributor when scheduling
-	// Executions.
-	Meta *Quest_Desc_Meta `protobuf:"bytes,4,opt,name=meta,proto3" json:"meta,omitempty"`
-}
-
-func (x *Quest_Desc) Reset() {
-	*x = Quest_Desc{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[8]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Quest_Desc) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Quest_Desc) ProtoMessage() {}
-
-func (x *Quest_Desc) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[8]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Quest_Desc.ProtoReflect.Descriptor instead.
-func (*Quest_Desc) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{1, 1}
-}
-
-func (x *Quest_Desc) GetDistributorConfigName() string {
-	if x != nil {
-		return x.DistributorConfigName
-	}
-	return ""
-}
-
-func (x *Quest_Desc) GetParameters() string {
-	if x != nil {
-		return x.Parameters
-	}
-	return ""
-}
-
-func (x *Quest_Desc) GetDistributorParameters() string {
-	if x != nil {
-		return x.DistributorParameters
-	}
-	return ""
-}
-
-func (x *Quest_Desc) GetMeta() *Quest_Desc_Meta {
-	if x != nil {
-		return x.Meta
-	}
-	return nil
-}
-
-type Quest_TemplateSpec struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"`
-	Ref     string `protobuf:"bytes,2,opt,name=ref,proto3" json:"ref,omitempty"`
-	Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`
-	Name    string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"`
-}
-
-func (x *Quest_TemplateSpec) Reset() {
-	*x = Quest_TemplateSpec{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[9]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Quest_TemplateSpec) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Quest_TemplateSpec) ProtoMessage() {}
-
-func (x *Quest_TemplateSpec) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[9]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Quest_TemplateSpec.ProtoReflect.Descriptor instead.
-func (*Quest_TemplateSpec) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{1, 2}
-}
-
-func (x *Quest_TemplateSpec) GetProject() string {
-	if x != nil {
-		return x.Project
-	}
-	return ""
-}
-
-func (x *Quest_TemplateSpec) GetRef() string {
-	if x != nil {
-		return x.Ref
-	}
-	return ""
-}
-
-func (x *Quest_TemplateSpec) GetVersion() string {
-	if x != nil {
-		return x.Version
-	}
-	return ""
-}
-
-func (x *Quest_TemplateSpec) GetName() string {
-	if x != nil {
-		return x.Name
-	}
-	return ""
-}
-
-type Quest_Data struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Created *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=created,proto3" json:"created,omitempty"`
-	Desc    *Quest_Desc            `protobuf:"bytes,2,opt,name=desc,proto3" json:"desc,omitempty"`
-	BuiltBy []*Quest_TemplateSpec  `protobuf:"bytes,3,rep,name=built_by,json=builtBy,proto3" json:"built_by,omitempty"`
-}
-
-func (x *Quest_Data) Reset() {
-	*x = Quest_Data{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[10]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Quest_Data) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Quest_Data) ProtoMessage() {}
-
-func (x *Quest_Data) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[10]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Quest_Data.ProtoReflect.Descriptor instead.
-func (*Quest_Data) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{1, 3}
-}
-
-func (x *Quest_Data) GetCreated() *timestamppb.Timestamp {
-	if x != nil {
-		return x.Created
-	}
-	return nil
-}
-
-func (x *Quest_Data) GetDesc() *Quest_Desc {
-	if x != nil {
-		return x.Desc
-	}
-	return nil
-}
-
-func (x *Quest_Data) GetBuiltBy() []*Quest_TemplateSpec {
-	if x != nil {
-		return x.BuiltBy
-	}
-	return nil
-}
-
-type Quest_Desc_Meta struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// This names the user/service account for all Attempts on this quest. You
-	// must have permission to use this account when creating the Quest and/or
-	// Attempts.
-	AsAccount string `protobuf:"bytes,1,opt,name=as_account,json=asAccount,proto3" json:"as_account,omitempty"`
-	// This affects how DM will retry the job payload in various exceptional
-	// circumstances.
-	Retry    *Quest_Desc_Meta_Retry    `protobuf:"bytes,2,opt,name=retry,proto3" json:"retry,omitempty"`
-	Timeouts *Quest_Desc_Meta_Timeouts `protobuf:"bytes,3,opt,name=timeouts,proto3" json:"timeouts,omitempty"`
-}
-
-func (x *Quest_Desc_Meta) Reset() {
-	*x = Quest_Desc_Meta{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[12]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Quest_Desc_Meta) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Quest_Desc_Meta) ProtoMessage() {}
-
-func (x *Quest_Desc_Meta) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[12]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Quest_Desc_Meta.ProtoReflect.Descriptor instead.
-func (*Quest_Desc_Meta) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{1, 1, 0}
-}
-
-func (x *Quest_Desc_Meta) GetAsAccount() string {
-	if x != nil {
-		return x.AsAccount
-	}
-	return ""
-}
-
-func (x *Quest_Desc_Meta) GetRetry() *Quest_Desc_Meta_Retry {
-	if x != nil {
-		return x.Retry
-	}
-	return nil
-}
-
-func (x *Quest_Desc_Meta) GetTimeouts() *Quest_Desc_Meta_Timeouts {
-	if x != nil {
-		return x.Timeouts
-	}
-	return nil
-}
-
-// Retry specifies the number of times in a row that DM should re-Execute
-// an Attempt due to the provided abnormal result.
-//
-// NOTE: The proto tag numbers for these MUST be aligned with the
-// enumeration values of AbnormalFinish.Status!
-type Quest_Desc_Meta_Retry struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// The number of times in a row to retry Executions which have an
-	// ABNORMAL_FINISHED status of FAILED.
-	Failed uint32 `protobuf:"varint,1,opt,name=failed,proto3" json:"failed,omitempty"`
-	// The number of times in a row to retry Executions which have an
-	// ABNORMAL_FINISHED status of CRASHED.
-	Crashed uint32 `protobuf:"varint,2,opt,name=crashed,proto3" json:"crashed,omitempty"`
-	// The number of times in a row to retry Executions which have an
-	// ABNORMAL_FINISHED status of EXPIRED.
-	Expired uint32 `protobuf:"varint,3,opt,name=expired,proto3" json:"expired,omitempty"`
-	// The number of times in a row to retry Executions which have an
-	// ABNORMAL_FINISHED status of TIMED_OUT.
-	TimedOut uint32 `protobuf:"varint,4,opt,name=timed_out,json=timedOut,proto3" json:"timed_out,omitempty"`
-}
-
-func (x *Quest_Desc_Meta_Retry) Reset() {
-	*x = Quest_Desc_Meta_Retry{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[13]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Quest_Desc_Meta_Retry) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Quest_Desc_Meta_Retry) ProtoMessage() {}
-
-func (x *Quest_Desc_Meta_Retry) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[13]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Quest_Desc_Meta_Retry.ProtoReflect.Descriptor instead.
-func (*Quest_Desc_Meta_Retry) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{1, 1, 0, 0}
-}
-
-func (x *Quest_Desc_Meta_Retry) GetFailed() uint32 {
-	if x != nil {
-		return x.Failed
-	}
-	return 0
-}
-
-func (x *Quest_Desc_Meta_Retry) GetCrashed() uint32 {
-	if x != nil {
-		return x.Crashed
-	}
-	return 0
-}
-
-func (x *Quest_Desc_Meta_Retry) GetExpired() uint32 {
-	if x != nil {
-		return x.Expired
-	}
-	return 0
-}
-
-func (x *Quest_Desc_Meta_Retry) GetTimedOut() uint32 {
-	if x != nil {
-		return x.TimedOut
-	}
-	return 0
-}
-
-// Timing describes the amount of time that Executions for this Quest
-// should have, on the following timeline:
-//   Event: execution sent to distributor
-//     ^ "start" v
-//   Event: execution sends ActivateExecution
-//     ^ "run" v
-//   Event: execution sends halting RPC (either ActivateExecution or
-//     EnsureGraphData)
-//     ^ "stop" v
-//   Event: distributor gives execution result back to DM
-//
-// If the given timeout hits before the next event in the timeline, DM
-// will mark the Execution as TIMED_OUT, and the appropriate retry policy
-// will be applied.
-//
-// If a given timeout is unlimited, leave the duration unset or 0.
-type Quest_Desc_Meta_Timeouts struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Start *durationpb.Duration `protobuf:"bytes,1,opt,name=start,proto3" json:"start,omitempty"`
-	Run   *durationpb.Duration `protobuf:"bytes,2,opt,name=run,proto3" json:"run,omitempty"`
-	Stop  *durationpb.Duration `protobuf:"bytes,3,opt,name=stop,proto3" json:"stop,omitempty"`
-}
-
-func (x *Quest_Desc_Meta_Timeouts) Reset() {
-	*x = Quest_Desc_Meta_Timeouts{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[14]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Quest_Desc_Meta_Timeouts) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Quest_Desc_Meta_Timeouts) ProtoMessage() {}
-
-func (x *Quest_Desc_Meta_Timeouts) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[14]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Quest_Desc_Meta_Timeouts.ProtoReflect.Descriptor instead.
-func (*Quest_Desc_Meta_Timeouts) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{1, 1, 0, 1}
-}
-
-func (x *Quest_Desc_Meta_Timeouts) GetStart() *durationpb.Duration {
-	if x != nil {
-		return x.Start
-	}
-	return nil
-}
-
-func (x *Quest_Desc_Meta_Timeouts) GetRun() *durationpb.Duration {
-	if x != nil {
-		return x.Run
-	}
-	return nil
-}
-
-func (x *Quest_Desc_Meta_Timeouts) GetStop() *durationpb.Duration {
-	if x != nil {
-		return x.Stop
-	}
-	return nil
-}
-
-type Attempt_ID struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Quest string `protobuf:"bytes,1,opt,name=quest,proto3" json:"quest,omitempty"`
-	Id    uint32 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
-}
-
-func (x *Attempt_ID) Reset() {
-	*x = Attempt_ID{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[15]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Attempt_ID) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Attempt_ID) ProtoMessage() {}
-
-func (x *Attempt_ID) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[15]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Attempt_ID.ProtoReflect.Descriptor instead.
-func (*Attempt_ID) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 0}
-}
-
-func (x *Attempt_ID) GetQuest() string {
-	if x != nil {
-		return x.Quest
-	}
-	return ""
-}
-
-func (x *Attempt_ID) GetId() uint32 {
-	if x != nil {
-		return x.Id
-	}
-	return 0
-}
-
-type Attempt_Data struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Created       *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=created,proto3" json:"created,omitempty"`
-	Modified      *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=modified,proto3" json:"modified,omitempty"`
-	NumExecutions uint32                 `protobuf:"varint,3,opt,name=num_executions,json=numExecutions,proto3" json:"num_executions,omitempty"`
-	// Types that are assignable to AttemptType:
-	//	*Attempt_Data_Scheduling_
-	//	*Attempt_Data_Executing_
-	//	*Attempt_Data_Waiting_
-	//	*Attempt_Data_Finished_
-	//	*Attempt_Data_AbnormalFinish
-	AttemptType isAttempt_Data_AttemptType `protobuf_oneof:"attempt_type"`
-}
-
-func (x *Attempt_Data) Reset() {
-	*x = Attempt_Data{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[16]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Attempt_Data) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Attempt_Data) ProtoMessage() {}
-
-func (x *Attempt_Data) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[16]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Attempt_Data.ProtoReflect.Descriptor instead.
-func (*Attempt_Data) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 1}
-}
-
-func (x *Attempt_Data) GetCreated() *timestamppb.Timestamp {
-	if x != nil {
-		return x.Created
-	}
-	return nil
-}
-
-func (x *Attempt_Data) GetModified() *timestamppb.Timestamp {
-	if x != nil {
-		return x.Modified
-	}
-	return nil
-}
-
-func (x *Attempt_Data) GetNumExecutions() uint32 {
-	if x != nil {
-		return x.NumExecutions
-	}
-	return 0
-}
-
-func (m *Attempt_Data) GetAttemptType() isAttempt_Data_AttemptType {
-	if m != nil {
-		return m.AttemptType
-	}
-	return nil
-}
-
-func (x *Attempt_Data) GetScheduling() *Attempt_Data_Scheduling {
-	if x, ok := x.GetAttemptType().(*Attempt_Data_Scheduling_); ok {
-		return x.Scheduling
-	}
-	return nil
-}
-
-func (x *Attempt_Data) GetExecuting() *Attempt_Data_Executing {
-	if x, ok := x.GetAttemptType().(*Attempt_Data_Executing_); ok {
-		return x.Executing
-	}
-	return nil
-}
-
-func (x *Attempt_Data) GetWaiting() *Attempt_Data_Waiting {
-	if x, ok := x.GetAttemptType().(*Attempt_Data_Waiting_); ok {
-		return x.Waiting
-	}
-	return nil
-}
-
-func (x *Attempt_Data) GetFinished() *Attempt_Data_Finished {
-	if x, ok := x.GetAttemptType().(*Attempt_Data_Finished_); ok {
-		return x.Finished
-	}
-	return nil
-}
-
-func (x *Attempt_Data) GetAbnormalFinish() *AbnormalFinish {
-	if x, ok := x.GetAttemptType().(*Attempt_Data_AbnormalFinish); ok {
-		return x.AbnormalFinish
-	}
-	return nil
-}
-
-type isAttempt_Data_AttemptType interface {
-	isAttempt_Data_AttemptType()
-}
-
-type Attempt_Data_Scheduling_ struct {
-	Scheduling *Attempt_Data_Scheduling `protobuf:"bytes,5,opt,name=scheduling,proto3,oneof"`
-}
-
-type Attempt_Data_Executing_ struct {
-	Executing *Attempt_Data_Executing `protobuf:"bytes,6,opt,name=executing,proto3,oneof"`
-}
-
-type Attempt_Data_Waiting_ struct {
-	Waiting *Attempt_Data_Waiting `protobuf:"bytes,7,opt,name=waiting,proto3,oneof"`
-}
-
-type Attempt_Data_Finished_ struct {
-	Finished *Attempt_Data_Finished `protobuf:"bytes,8,opt,name=finished,proto3,oneof"`
-}
-
-type Attempt_Data_AbnormalFinish struct {
-	AbnormalFinish *AbnormalFinish `protobuf:"bytes,9,opt,name=abnormal_finish,json=abnormalFinish,proto3,oneof"`
-}
-
-func (*Attempt_Data_Scheduling_) isAttempt_Data_AttemptType() {}
-
-func (*Attempt_Data_Executing_) isAttempt_Data_AttemptType() {}
-
-func (*Attempt_Data_Waiting_) isAttempt_Data_AttemptType() {}
-
-func (*Attempt_Data_Finished_) isAttempt_Data_AttemptType() {}
-
-func (*Attempt_Data_AbnormalFinish) isAttempt_Data_AttemptType() {}
-
-type Attempt_Partial struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Data is true iff the AttemptData should have been filled, but wasn't
-	Data bool `protobuf:"varint,1,opt,name=data,proto3" json:"data,omitempty"`
-	// Executions is true iff the Executions were requested, but not all of
-	// them could be loaded.
-	Executions bool `protobuf:"varint,2,opt,name=executions,proto3" json:"executions,omitempty"`
-	// FwdDeps is true iff FwdDeps were requested, but not all of them could be
-	// loaded.
-	FwdDeps bool `protobuf:"varint,3,opt,name=fwd_deps,json=fwdDeps,proto3" json:"fwd_deps,omitempty"`
-	// BackDeps is true iff BackDeps were requested, but not all of them could be
-	// loaded.
-	BackDeps bool `protobuf:"varint,4,opt,name=back_deps,json=backDeps,proto3" json:"back_deps,omitempty"`
-	// result is set if AttemptResults were requested, and the attempt_type is
-	// Finished, but for some reason the result but wasn't loaded.
-	Result Attempt_Partial_Result `protobuf:"varint,5,opt,name=result,proto3,enum=dm.Attempt_Partial_Result" json:"result,omitempty"`
-}
-
-func (x *Attempt_Partial) Reset() {
-	*x = Attempt_Partial{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[18]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Attempt_Partial) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Attempt_Partial) ProtoMessage() {}
-
-func (x *Attempt_Partial) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[18]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Attempt_Partial.ProtoReflect.Descriptor instead.
-func (*Attempt_Partial) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 3}
-}
-
-func (x *Attempt_Partial) GetData() bool {
-	if x != nil {
-		return x.Data
-	}
-	return false
-}
-
-func (x *Attempt_Partial) GetExecutions() bool {
-	if x != nil {
-		return x.Executions
-	}
-	return false
-}
-
-func (x *Attempt_Partial) GetFwdDeps() bool {
-	if x != nil {
-		return x.FwdDeps
-	}
-	return false
-}
-
-func (x *Attempt_Partial) GetBackDeps() bool {
-	if x != nil {
-		return x.BackDeps
-	}
-	return false
-}
-
-func (x *Attempt_Partial) GetResult() Attempt_Partial_Result {
-	if x != nil {
-		return x.Result
-	}
-	return Attempt_Partial_LOADED
-}
-
-// This attempt is ready to be Executed, but hasn't been sent to the
-// distributor yet.
-type Attempt_Data_Scheduling struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-}
-
-func (x *Attempt_Data_Scheduling) Reset() {
-	*x = Attempt_Data_Scheduling{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[19]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Attempt_Data_Scheduling) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Attempt_Data_Scheduling) ProtoMessage() {}
-
-func (x *Attempt_Data_Scheduling) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[19]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Attempt_Data_Scheduling.ProtoReflect.Descriptor instead.
-func (*Attempt_Data_Scheduling) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 1, 0}
-}
-
-// This attempt has a live Execution (with the specified ID). Check the
-// Execution state for more information.
-type Attempt_Data_Executing struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	CurExecutionId uint32 `protobuf:"varint,1,opt,name=cur_execution_id,json=curExecutionId,proto3" json:"cur_execution_id,omitempty"`
-}
-
-func (x *Attempt_Data_Executing) Reset() {
-	*x = Attempt_Data_Executing{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[20]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Attempt_Data_Executing) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Attempt_Data_Executing) ProtoMessage() {}
-
-func (x *Attempt_Data_Executing) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[20]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Attempt_Data_Executing.ProtoReflect.Descriptor instead.
-func (*Attempt_Data_Executing) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 1, 1}
-}
-
-func (x *Attempt_Data_Executing) GetCurExecutionId() uint32 {
-	if x != nil {
-		return x.CurExecutionId
-	}
-	return 0
-}
-
-// This attempt's last Execution stopped by adding dependencies.
-type Attempt_Data_Waiting struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	NumWaiting uint32 `protobuf:"varint,1,opt,name=num_waiting,json=numWaiting,proto3" json:"num_waiting,omitempty"`
-}
-
-func (x *Attempt_Data_Waiting) Reset() {
-	*x = Attempt_Data_Waiting{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[21]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Attempt_Data_Waiting) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Attempt_Data_Waiting) ProtoMessage() {}
-
-func (x *Attempt_Data_Waiting) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[21]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Attempt_Data_Waiting.ProtoReflect.Descriptor instead.
-func (*Attempt_Data_Waiting) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 1, 2}
-}
-
-func (x *Attempt_Data_Waiting) GetNumWaiting() uint32 {
-	if x != nil {
-		return x.NumWaiting
-	}
-	return 0
-}
-
-// This attempt is complete.
-type Attempt_Data_Finished struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// The result of the Attempt. To obtain the distributor specific result
-	// for the last execution, make sure to include at least one Execution in
-	// your query.
-	//
-	// Only if `include.attempt.data == true`, will the response include
-	// data.object.
-	Data *JsonResult `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
-}
-
-func (x *Attempt_Data_Finished) Reset() {
-	*x = Attempt_Data_Finished{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[22]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Attempt_Data_Finished) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Attempt_Data_Finished) ProtoMessage() {}
-
-func (x *Attempt_Data_Finished) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[22]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Attempt_Data_Finished.ProtoReflect.Descriptor instead.
-func (*Attempt_Data_Finished) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{4, 1, 3}
-}
-
-func (x *Attempt_Data_Finished) GetData() *JsonResult {
-	if x != nil {
-		return x.Data
-	}
-	return nil
-}
-
-// Execution_Auth is a tuple of the requesting ExecutionID and the activated
-// Execution Token (see the ActivateExecution rpc).
-type Execution_Auth struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Id    *Execution_ID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Token []byte        `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
-}
-
-func (x *Execution_Auth) Reset() {
-	*x = Execution_Auth{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[23]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution_Auth) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution_Auth) ProtoMessage() {}
-
-func (x *Execution_Auth) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[23]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution_Auth.ProtoReflect.Descriptor instead.
-func (*Execution_Auth) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 0}
-}
-
-func (x *Execution_Auth) GetId() *Execution_ID {
-	if x != nil {
-		return x.Id
-	}
-	return nil
-}
-
-func (x *Execution_Auth) GetToken() []byte {
-	if x != nil {
-		return x.Token
-	}
-	return nil
-}
-
-type Execution_ID struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Quest   string `protobuf:"bytes,1,opt,name=quest,proto3" json:"quest,omitempty"`
-	Attempt uint32 `protobuf:"varint,2,opt,name=attempt,proto3" json:"attempt,omitempty"`
-	Id      uint32 `protobuf:"varint,3,opt,name=id,proto3" json:"id,omitempty"`
-}
-
-func (x *Execution_ID) Reset() {
-	*x = Execution_ID{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[24]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution_ID) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution_ID) ProtoMessage() {}
-
-func (x *Execution_ID) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[24]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution_ID.ProtoReflect.Descriptor instead.
-func (*Execution_ID) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 1}
-}
-
-func (x *Execution_ID) GetQuest() string {
-	if x != nil {
-		return x.Quest
-	}
-	return ""
-}
-
-func (x *Execution_ID) GetAttempt() uint32 {
-	if x != nil {
-		return x.Attempt
-	}
-	return 0
-}
-
-func (x *Execution_ID) GetId() uint32 {
-	if x != nil {
-		return x.Id
-	}
-	return 0
-}
-
-type Execution_Data struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Created         *timestamppb.Timestamp          `protobuf:"bytes,1,opt,name=created,proto3" json:"created,omitempty"`
-	Modified        *timestamppb.Timestamp          `protobuf:"bytes,2,opt,name=modified,proto3" json:"modified,omitempty"`
-	DistributorInfo *Execution_Data_DistributorInfo `protobuf:"bytes,3,opt,name=distributor_info,json=distributorInfo,proto3" json:"distributor_info,omitempty"`
-	// Types that are assignable to ExecutionType:
-	//	*Execution_Data_Scheduling_
-	//	*Execution_Data_Running_
-	//	*Execution_Data_Stopping_
-	//	*Execution_Data_Finished_
-	//	*Execution_Data_AbnormalFinish
-	ExecutionType isExecution_Data_ExecutionType `protobuf_oneof:"execution_type"`
-}
-
-func (x *Execution_Data) Reset() {
-	*x = Execution_Data{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[25]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution_Data) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution_Data) ProtoMessage() {}
-
-func (x *Execution_Data) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[25]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution_Data.ProtoReflect.Descriptor instead.
-func (*Execution_Data) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 2}
-}
-
-func (x *Execution_Data) GetCreated() *timestamppb.Timestamp {
-	if x != nil {
-		return x.Created
-	}
-	return nil
-}
-
-func (x *Execution_Data) GetModified() *timestamppb.Timestamp {
-	if x != nil {
-		return x.Modified
-	}
-	return nil
-}
-
-func (x *Execution_Data) GetDistributorInfo() *Execution_Data_DistributorInfo {
-	if x != nil {
-		return x.DistributorInfo
-	}
-	return nil
-}
-
-func (m *Execution_Data) GetExecutionType() isExecution_Data_ExecutionType {
-	if m != nil {
-		return m.ExecutionType
-	}
-	return nil
-}
-
-func (x *Execution_Data) GetScheduling() *Execution_Data_Scheduling {
-	if x, ok := x.GetExecutionType().(*Execution_Data_Scheduling_); ok {
-		return x.Scheduling
-	}
-	return nil
-}
-
-func (x *Execution_Data) GetRunning() *Execution_Data_Running {
-	if x, ok := x.GetExecutionType().(*Execution_Data_Running_); ok {
-		return x.Running
-	}
-	return nil
-}
-
-func (x *Execution_Data) GetStopping() *Execution_Data_Stopping {
-	if x, ok := x.GetExecutionType().(*Execution_Data_Stopping_); ok {
-		return x.Stopping
-	}
-	return nil
-}
-
-func (x *Execution_Data) GetFinished() *Execution_Data_Finished {
-	if x, ok := x.GetExecutionType().(*Execution_Data_Finished_); ok {
-		return x.Finished
-	}
-	return nil
-}
-
-func (x *Execution_Data) GetAbnormalFinish() *AbnormalFinish {
-	if x, ok := x.GetExecutionType().(*Execution_Data_AbnormalFinish); ok {
-		return x.AbnormalFinish
-	}
-	return nil
-}
-
-type isExecution_Data_ExecutionType interface {
-	isExecution_Data_ExecutionType()
-}
-
-type Execution_Data_Scheduling_ struct {
-	Scheduling *Execution_Data_Scheduling `protobuf:"bytes,4,opt,name=scheduling,proto3,oneof"`
-}
-
-type Execution_Data_Running_ struct {
-	Running *Execution_Data_Running `protobuf:"bytes,5,opt,name=running,proto3,oneof"`
-}
-
-type Execution_Data_Stopping_ struct {
-	Stopping *Execution_Data_Stopping `protobuf:"bytes,6,opt,name=stopping,proto3,oneof"`
-}
-
-type Execution_Data_Finished_ struct {
-	Finished *Execution_Data_Finished `protobuf:"bytes,7,opt,name=finished,proto3,oneof"`
-}
-
-type Execution_Data_AbnormalFinish struct {
-	AbnormalFinish *AbnormalFinish `protobuf:"bytes,8,opt,name=abnormal_finish,json=abnormalFinish,proto3,oneof"`
-}
-
-func (*Execution_Data_Scheduling_) isExecution_Data_ExecutionType() {}
-
-func (*Execution_Data_Running_) isExecution_Data_ExecutionType() {}
-
-func (*Execution_Data_Stopping_) isExecution_Data_ExecutionType() {}
-
-func (*Execution_Data_Finished_) isExecution_Data_ExecutionType() {}
-
-func (*Execution_Data_AbnormalFinish) isExecution_Data_ExecutionType() {}
-
-type Execution_Data_DistributorInfo struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	ConfigName    string `protobuf:"bytes,1,opt,name=config_name,json=configName,proto3" json:"config_name,omitempty"`
-	ConfigVersion string `protobuf:"bytes,2,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"`
-	Token         string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
-	Url           string `protobuf:"bytes,4,opt,name=url,proto3" json:"url,omitempty"`
-}
-
-func (x *Execution_Data_DistributorInfo) Reset() {
-	*x = Execution_Data_DistributorInfo{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[26]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution_Data_DistributorInfo) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution_Data_DistributorInfo) ProtoMessage() {}
-
-func (x *Execution_Data_DistributorInfo) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[26]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution_Data_DistributorInfo.ProtoReflect.Descriptor instead.
-func (*Execution_Data_DistributorInfo) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 2, 0}
-}
-
-func (x *Execution_Data_DistributorInfo) GetConfigName() string {
-	if x != nil {
-		return x.ConfigName
-	}
-	return ""
-}
-
-func (x *Execution_Data_DistributorInfo) GetConfigVersion() string {
-	if x != nil {
-		return x.ConfigVersion
-	}
-	return ""
-}
-
-func (x *Execution_Data_DistributorInfo) GetToken() string {
-	if x != nil {
-		return x.Token
-	}
-	return ""
-}
-
-func (x *Execution_Data_DistributorInfo) GetUrl() string {
-	if x != nil {
-		return x.Url
-	}
-	return ""
-}
-
-type Execution_Data_Scheduling struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-}
-
-func (x *Execution_Data_Scheduling) Reset() {
-	*x = Execution_Data_Scheduling{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[27]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution_Data_Scheduling) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution_Data_Scheduling) ProtoMessage() {}
-
-func (x *Execution_Data_Scheduling) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[27]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution_Data_Scheduling.ProtoReflect.Descriptor instead.
-func (*Execution_Data_Scheduling) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 2, 1}
-}
-
-type Execution_Data_Running struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-}
-
-func (x *Execution_Data_Running) Reset() {
-	*x = Execution_Data_Running{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[28]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution_Data_Running) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution_Data_Running) ProtoMessage() {}
-
-func (x *Execution_Data_Running) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[28]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution_Data_Running.ProtoReflect.Descriptor instead.
-func (*Execution_Data_Running) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 2, 2}
-}
-
-type Execution_Data_Stopping struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-}
-
-func (x *Execution_Data_Stopping) Reset() {
-	*x = Execution_Data_Stopping{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[29]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution_Data_Stopping) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution_Data_Stopping) ProtoMessage() {}
-
-func (x *Execution_Data_Stopping) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[29]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution_Data_Stopping.ProtoReflect.Descriptor instead.
-func (*Execution_Data_Stopping) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 2, 3}
-}
-
-type Execution_Data_Finished struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Data *JsonResult `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
-}
-
-func (x *Execution_Data_Finished) Reset() {
-	*x = Execution_Data_Finished{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[30]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Execution_Data_Finished) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Execution_Data_Finished) ProtoMessage() {}
-
-func (x *Execution_Data_Finished) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[30]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Execution_Data_Finished.ProtoReflect.Descriptor instead.
-func (*Execution_Data_Finished) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP(), []int{5, 2, 4}
-}
-
-func (x *Execution_Data_Finished) GetData() *JsonResult {
-	if x != nil {
-		return x.Data
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_service_v1_graph_data_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDesc = []byte{
-	0x0a, 0x37, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x64,
-	0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x64, 0x6d, 0x1a, 0x1e, 0x67,
-	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64,
-	0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67,
-	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x22, 0xe8, 0x01, 0x0a, 0x0e, 0x41, 0x62, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x46,
-	0x69, 0x6e, 0x69, 0x73, 0x68, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x62, 0x6e, 0x6f, 0x72,
-	0x6d, 0x61, 0x6c, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
-	0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73,
-	0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e,
-	0x22, 0x8a, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x49,
-	0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c,
-	0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x41, 0x53, 0x48, 0x45, 0x44, 0x10,
-	0x02, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, 0x50, 0x49, 0x52, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0d,
-	0x0a, 0x09, 0x54, 0x49, 0x4d, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x0d, 0x0a,
-	0x09, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08,
-	0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x49,
-	0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x53, 0x55, 0x4c,
-	0x54, 0x5f, 0x4d, 0x41, 0x4c, 0x46, 0x4f, 0x52, 0x4d, 0x45, 0x44, 0x10, 0x08, 0x22, 0xea, 0x08,
-	0x0a, 0x05, 0x51, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x49,
-	0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x44, 0x4e, 0x45, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x08, 0x52, 0x03, 0x44, 0x4e, 0x45, 0x12, 0x22, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74,
-	0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x08, 0x61,
-	0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e,
-	0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74,
-	0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73,
-	0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28,
-	0x08, 0x52, 0x07, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x1a, 0x14, 0x0a, 0x02, 0x49, 0x44,
-	0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
-	0x1a, 0xdd, 0x04, 0x0a, 0x04, 0x44, 0x65, 0x73, 0x63, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73,
-	0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
-	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x69, 0x73, 0x74,
-	0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4e, 0x61, 0x6d,
-	0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
-	0x73, 0x12, 0x35, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72,
-	0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x15, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x50, 0x61,
-	0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x27, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61,
-	0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73,
-	0x74, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74,
-	0x61, 0x1a, 0x9c, 0x03, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73,
-	0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
-	0x61, 0x73, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x72, 0x65, 0x74,
-	0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75,
-	0x65, 0x73, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x52, 0x65,
-	0x74, 0x72, 0x79, 0x52, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x12, 0x38, 0x0a, 0x08, 0x74, 0x69,
-	0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x64,
-	0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x2e, 0x4d, 0x65, 0x74,
-	0x61, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65,
-	0x6f, 0x75, 0x74, 0x73, 0x1a, 0x70, 0x0a, 0x05, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x16, 0x0a,
-	0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x66,
-	0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x61, 0x73, 0x68, 0x65, 0x64,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x72, 0x61, 0x73, 0x68, 0x65, 0x64, 0x12,
-	0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
-	0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x69, 0x6d,
-	0x65, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x74, 0x69,
-	0x6d, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x1a, 0x97, 0x01, 0x0a, 0x08, 0x54, 0x69, 0x6d, 0x65, 0x6f,
-	0x75, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73,
-	0x74, 0x61, 0x72, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x72, 0x75, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x72, 0x75,
-	0x6e, 0x12, 0x2d, 0x0a, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
-	0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70,
-	0x1a, 0x68, 0x0a, 0x0c, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, 0x70, 0x65, 0x63,
-	0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65,
-	0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x18, 0x0a, 0x07,
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76,
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x93, 0x01, 0x0a, 0x04, 0x44,
-	0x61, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
-	0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x04, 0x64, 0x65, 0x73,
-	0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65,
-	0x73, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x12, 0x31, 0x0a,
-	0x08, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x16, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c,
-	0x61, 0x74, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x42, 0x79,
-	0x1a, 0x48, 0x0a, 0x0d, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03,
-	0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52,
-	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x74, 0x0a, 0x0a, 0x4a, 0x73,
-	0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65,
-	0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
-	0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04,
-	0x73, 0x69, 0x7a, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
-	0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x22, 0x69, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x22, 0x0a, 0x04, 0x64, 0x61,
-	0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x64, 0x6d, 0x2e, 0x4a, 0x73,
-	0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3b,
-	0x0a, 0x0f, 0x61, 0x62, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73,
-	0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x62, 0x6e,
-	0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x52, 0x0e, 0x61, 0x62, 0x6e,
-	0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x22, 0xee, 0x0a, 0x0a, 0x07,
-	0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x1e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74,
-	0x2e, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x44, 0x4e, 0x45, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x44, 0x4e, 0x45, 0x12, 0x24, 0x0a, 0x04, 0x64, 0x61, 0x74,
-	0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74,
-	0x65, 0x6d, 0x70, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12,
-	0x3b, 0x0a, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74,
-	0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x0a, 0x08,
-	0x66, 0x77, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f,
-	0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52,
-	0x07, 0x66, 0x77, 0x64, 0x44, 0x65, 0x70, 0x73, 0x12, 0x2c, 0x0a, 0x09, 0x62, 0x61, 0x63, 0x6b,
-	0x5f, 0x64, 0x65, 0x70, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x6d,
-	0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x62, 0x61,
-	0x63, 0x6b, 0x44, 0x65, 0x70, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61,
-	0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74,
-	0x65, 0x6d, 0x70, 0x74, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x07, 0x70, 0x61,
-	0x72, 0x74, 0x69, 0x61, 0x6c, 0x1a, 0x2a, 0x0a, 0x02, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69,
-	0x64, 0x1a, 0xf5, 0x04, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x72,
-	0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
-	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
-	0x12, 0x36, 0x0a, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08,
-	0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f,
-	0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
-	0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
-	0x3d, 0x0a, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74,
-	0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67,
-	0x48, 0x00, 0x52, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x3a,
-	0x0a, 0x09, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x1a, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x2e, 0x44,
-	0x61, 0x74, 0x61, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52,
-	0x09, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x07, 0x77, 0x61,
-	0x69, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x6d,
-	0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x61,
-	0x69, 0x74, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x07, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67,
-	0x12, 0x37, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x2e,
-	0x44, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x48, 0x00, 0x52,
-	0x08, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x0f, 0x61, 0x62, 0x6e,
-	0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x18, 0x09, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x62, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c,
-	0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x48, 0x00, 0x52, 0x0e, 0x61, 0x62, 0x6e, 0x6f, 0x72, 0x6d,
-	0x61, 0x6c, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x1a, 0x0c, 0x0a, 0x0a, 0x53, 0x63, 0x68, 0x65,
-	0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x1a, 0x35, 0x0a, 0x09, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
-	0x69, 0x6e, 0x67, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x75, 0x72, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75,
-	0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x63,
-	0x75, 0x72, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x1a, 0x2a, 0x0a,
-	0x07, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x75, 0x6d, 0x5f,
-	0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6e,
-	0x75, 0x6d, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x2e, 0x0a, 0x08, 0x46, 0x69, 0x6e,
-	0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x64, 0x6d, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x52, 0x65, 0x73,
-	0x75, 0x6c, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x0e, 0x0a, 0x0c, 0x61, 0x74, 0x74,
-	0x65, 0x6d, 0x70, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x1a, 0x4c, 0x0a, 0x0f, 0x45, 0x78, 0x65,
-	0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
-	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x23,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
-	0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xf8, 0x01, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x74,
-	0x69, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x08, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75,
-	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x78, 0x65,
-	0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x77, 0x64, 0x5f, 0x64,
-	0x65, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x66, 0x77, 0x64, 0x44, 0x65,
-	0x70, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x70, 0x73, 0x18,
-	0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x62, 0x61, 0x63, 0x6b, 0x44, 0x65, 0x70, 0x73, 0x12,
-	0x32, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32,
-	0x1a, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x2e, 0x50, 0x61, 0x72,
-	0x74, 0x69, 0x61, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73,
-	0x75, 0x6c, 0x74, 0x22, 0x4d, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x0a, 0x0a,
-	0x06, 0x4c, 0x4f, 0x41, 0x44, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x4f, 0x54,
-	0x5f, 0x4c, 0x4f, 0x41, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4e, 0x4f, 0x54,
-	0x5f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a,
-	0x0f, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54,
-	0x10, 0x03, 0x22, 0x58, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x53,
-	0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x45,
-	0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41,
-	0x49, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x49, 0x4e, 0x49, 0x53,
-	0x48, 0x45, 0x44, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x42, 0x4e, 0x4f, 0x52, 0x4d, 0x41,
-	0x4c, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x04, 0x22, 0xad, 0x08, 0x0a,
-	0x09, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x02, 0x69, 0x64,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63,
-	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x04,
-	0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x6d, 0x2e,
-	0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04,
-	0x64, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x18,
-	0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x1a, 0x3e,
-	0x0a, 0x04, 0x41, 0x75, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x10, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
-	0x6e, 0x2e, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65,
-	0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x44,
-	0x0a, 0x02, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x74,
-	0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x61, 0x74, 0x74,
-	0x65, 0x6d, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
-	0x52, 0x02, 0x69, 0x64, 0x1a, 0xdc, 0x05, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x34, 0x0a,
-	0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
-	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
-	0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61,
-	0x74, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
-	0x70, 0x52, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x4d, 0x0a, 0x10, 0x64,
-	0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75,
-	0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69,
-	0x62, 0x75, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x74, 0x72,
-	0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3f, 0x0a, 0x0a, 0x73, 0x63,
-	0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d,
-	0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x61,
-	0x74, 0x61, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52,
-	0x0a, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, 0x07, 0x72,
-	0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x64,
-	0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x61, 0x74, 0x61,
-	0x2e, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x6e,
-	0x69, 0x6e, 0x67, 0x12, 0x39, 0x0a, 0x08, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18,
-	0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75,
-	0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x70, 0x69,
-	0x6e, 0x67, 0x48, 0x00, 0x52, 0x08, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x39,
-	0x0a, 0x08, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x1b, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
-	0x44, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x48, 0x00, 0x52,
-	0x08, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x0f, 0x61, 0x62, 0x6e,
-	0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x18, 0x08, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x62, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c,
-	0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x48, 0x00, 0x52, 0x0e, 0x61, 0x62, 0x6e, 0x6f, 0x72, 0x6d,
-	0x61, 0x6c, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x1a, 0x81, 0x01, 0x0a, 0x0f, 0x44, 0x69, 0x73,
-	0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0b,
-	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a,
-	0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72,
-	0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72,
-	0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x1a, 0x0c, 0x0a, 0x0a,
-	0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x1a, 0x09, 0x0a, 0x07, 0x52, 0x75,
-	0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x1a, 0x0a, 0x0a, 0x08, 0x53, 0x74, 0x6f, 0x70, 0x70, 0x69, 0x6e,
-	0x67, 0x1a, 0x2e, 0x0a, 0x08, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x22, 0x0a,
-	0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x64, 0x6d,
-	0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74,
-	0x61, 0x42, 0x10, 0x0a, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74,
-	0x79, 0x70, 0x65, 0x22, 0x57, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a,
-	0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07,
-	0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x4f,
-	0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x49, 0x4e, 0x49, 0x53,
-	0x48, 0x45, 0x44, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x42, 0x4e, 0x4f, 0x52, 0x4d, 0x41,
-	0x4c, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x04, 0x22, 0xbe, 0x01, 0x0a,
-	0x09, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x06, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x6d, 0x2e,
-	0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x51, 0x75, 0x65, 0x73, 0x74, 0x73,
-	0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x1d, 0x0a,
-	0x0a, 0x68, 0x61, 0x64, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x08, 0x52, 0x09, 0x68, 0x61, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x19, 0x0a, 0x08,
-	0x68, 0x61, 0x64, 0x5f, 0x6d, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
-	0x68, 0x61, 0x64, 0x4d, 0x6f, 0x72, 0x65, 0x1a, 0x44, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x73, 0x74,
-	0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
-	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x64, 0x6d, 0x2e, 0x51, 0x75, 0x65,
-	0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x2b, 0x5a,
-	0x29, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67,
-	0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72,
-	0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescData = file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
-var file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes = make([]protoimpl.MessageInfo, 32)
-var file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_goTypes = []interface{}{
-	(AbnormalFinish_Status)(0),             // 0: dm.AbnormalFinish.Status
-	(Attempt_State)(0),                     // 1: dm.Attempt.State
-	(Attempt_Partial_Result)(0),            // 2: dm.Attempt.Partial.Result
-	(Execution_State)(0),                   // 3: dm.Execution.State
-	(*AbnormalFinish)(nil),                 // 4: dm.AbnormalFinish
-	(*Quest)(nil),                          // 5: dm.Quest
-	(*JsonResult)(nil),                     // 6: dm.JsonResult
-	(*Result)(nil),                         // 7: dm.Result
-	(*Attempt)(nil),                        // 8: dm.Attempt
-	(*Execution)(nil),                      // 9: dm.Execution
-	(*GraphData)(nil),                      // 10: dm.GraphData
-	(*Quest_ID)(nil),                       // 11: dm.Quest.ID
-	(*Quest_Desc)(nil),                     // 12: dm.Quest.Desc
-	(*Quest_TemplateSpec)(nil),             // 13: dm.Quest.TemplateSpec
-	(*Quest_Data)(nil),                     // 14: dm.Quest.Data
-	nil,                                    // 15: dm.Quest.AttemptsEntry
-	(*Quest_Desc_Meta)(nil),                // 16: dm.Quest.Desc.Meta
-	(*Quest_Desc_Meta_Retry)(nil),          // 17: dm.Quest.Desc.Meta.Retry
-	(*Quest_Desc_Meta_Timeouts)(nil),       // 18: dm.Quest.Desc.Meta.Timeouts
-	(*Attempt_ID)(nil),                     // 19: dm.Attempt.ID
-	(*Attempt_Data)(nil),                   // 20: dm.Attempt.Data
-	nil,                                    // 21: dm.Attempt.ExecutionsEntry
-	(*Attempt_Partial)(nil),                // 22: dm.Attempt.Partial
-	(*Attempt_Data_Scheduling)(nil),        // 23: dm.Attempt.Data.Scheduling
-	(*Attempt_Data_Executing)(nil),         // 24: dm.Attempt.Data.Executing
-	(*Attempt_Data_Waiting)(nil),           // 25: dm.Attempt.Data.Waiting
-	(*Attempt_Data_Finished)(nil),          // 26: dm.Attempt.Data.Finished
-	(*Execution_Auth)(nil),                 // 27: dm.Execution.Auth
-	(*Execution_ID)(nil),                   // 28: dm.Execution.ID
-	(*Execution_Data)(nil),                 // 29: dm.Execution.Data
-	(*Execution_Data_DistributorInfo)(nil), // 30: dm.Execution.Data.DistributorInfo
-	(*Execution_Data_Scheduling)(nil),      // 31: dm.Execution.Data.Scheduling
-	(*Execution_Data_Running)(nil),         // 32: dm.Execution.Data.Running
-	(*Execution_Data_Stopping)(nil),        // 33: dm.Execution.Data.Stopping
-	(*Execution_Data_Finished)(nil),        // 34: dm.Execution.Data.Finished
-	nil,                                    // 35: dm.GraphData.QuestsEntry
-	(*timestamppb.Timestamp)(nil),          // 36: google.protobuf.Timestamp
-	(*AttemptList)(nil),                    // 37: dm.AttemptList
-	(*durationpb.Duration)(nil),            // 38: google.protobuf.Duration
-}
-var file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_depIdxs = []int32{
-	0,  // 0: dm.AbnormalFinish.status:type_name -> dm.AbnormalFinish.Status
-	11, // 1: dm.Quest.id:type_name -> dm.Quest.ID
-	14, // 2: dm.Quest.data:type_name -> dm.Quest.Data
-	15, // 3: dm.Quest.attempts:type_name -> dm.Quest.AttemptsEntry
-	36, // 4: dm.JsonResult.expiration:type_name -> google.protobuf.Timestamp
-	6,  // 5: dm.Result.data:type_name -> dm.JsonResult
-	4,  // 6: dm.Result.abnormal_finish:type_name -> dm.AbnormalFinish
-	19, // 7: dm.Attempt.id:type_name -> dm.Attempt.ID
-	20, // 8: dm.Attempt.data:type_name -> dm.Attempt.Data
-	21, // 9: dm.Attempt.executions:type_name -> dm.Attempt.ExecutionsEntry
-	37, // 10: dm.Attempt.fwd_deps:type_name -> dm.AttemptList
-	37, // 11: dm.Attempt.back_deps:type_name -> dm.AttemptList
-	22, // 12: dm.Attempt.partial:type_name -> dm.Attempt.Partial
-	28, // 13: dm.Execution.id:type_name -> dm.Execution.ID
-	29, // 14: dm.Execution.data:type_name -> dm.Execution.Data
-	35, // 15: dm.GraphData.quests:type_name -> dm.GraphData.QuestsEntry
-	16, // 16: dm.Quest.Desc.meta:type_name -> dm.Quest.Desc.Meta
-	36, // 17: dm.Quest.Data.created:type_name -> google.protobuf.Timestamp
-	12, // 18: dm.Quest.Data.desc:type_name -> dm.Quest.Desc
-	13, // 19: dm.Quest.Data.built_by:type_name -> dm.Quest.TemplateSpec
-	8,  // 20: dm.Quest.AttemptsEntry.value:type_name -> dm.Attempt
-	17, // 21: dm.Quest.Desc.Meta.retry:type_name -> dm.Quest.Desc.Meta.Retry
-	18, // 22: dm.Quest.Desc.Meta.timeouts:type_name -> dm.Quest.Desc.Meta.Timeouts
-	38, // 23: dm.Quest.Desc.Meta.Timeouts.start:type_name -> google.protobuf.Duration
-	38, // 24: dm.Quest.Desc.Meta.Timeouts.run:type_name -> google.protobuf.Duration
-	38, // 25: dm.Quest.Desc.Meta.Timeouts.stop:type_name -> google.protobuf.Duration
-	36, // 26: dm.Attempt.Data.created:type_name -> google.protobuf.Timestamp
-	36, // 27: dm.Attempt.Data.modified:type_name -> google.protobuf.Timestamp
-	23, // 28: dm.Attempt.Data.scheduling:type_name -> dm.Attempt.Data.Scheduling
-	24, // 29: dm.Attempt.Data.executing:type_name -> dm.Attempt.Data.Executing
-	25, // 30: dm.Attempt.Data.waiting:type_name -> dm.Attempt.Data.Waiting
-	26, // 31: dm.Attempt.Data.finished:type_name -> dm.Attempt.Data.Finished
-	4,  // 32: dm.Attempt.Data.abnormal_finish:type_name -> dm.AbnormalFinish
-	9,  // 33: dm.Attempt.ExecutionsEntry.value:type_name -> dm.Execution
-	2,  // 34: dm.Attempt.Partial.result:type_name -> dm.Attempt.Partial.Result
-	6,  // 35: dm.Attempt.Data.Finished.data:type_name -> dm.JsonResult
-	28, // 36: dm.Execution.Auth.id:type_name -> dm.Execution.ID
-	36, // 37: dm.Execution.Data.created:type_name -> google.protobuf.Timestamp
-	36, // 38: dm.Execution.Data.modified:type_name -> google.protobuf.Timestamp
-	30, // 39: dm.Execution.Data.distributor_info:type_name -> dm.Execution.Data.DistributorInfo
-	31, // 40: dm.Execution.Data.scheduling:type_name -> dm.Execution.Data.Scheduling
-	32, // 41: dm.Execution.Data.running:type_name -> dm.Execution.Data.Running
-	33, // 42: dm.Execution.Data.stopping:type_name -> dm.Execution.Data.Stopping
-	34, // 43: dm.Execution.Data.finished:type_name -> dm.Execution.Data.Finished
-	4,  // 44: dm.Execution.Data.abnormal_finish:type_name -> dm.AbnormalFinish
-	6,  // 45: dm.Execution.Data.Finished.data:type_name -> dm.JsonResult
-	5,  // 46: dm.GraphData.QuestsEntry.value:type_name -> dm.Quest
-	47, // [47:47] is the sub-list for method output_type
-	47, // [47:47] is the sub-list for method input_type
-	47, // [47:47] is the sub-list for extension type_name
-	47, // [47:47] is the sub-list for extension extendee
-	0,  // [0:47] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_init() }
-func file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_init() {
-	if File_go_chromium_org_luci_dm_api_service_v1_graph_data_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_init()
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*AbnormalFinish); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Quest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*JsonResult); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Result); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Attempt); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GraphData); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Quest_ID); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Quest_Desc); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Quest_TemplateSpec); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Quest_Data); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Quest_Desc_Meta); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Quest_Desc_Meta_Retry); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Quest_Desc_Meta_Timeouts); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Attempt_ID); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Attempt_Data); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Attempt_Partial); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Attempt_Data_Scheduling); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Attempt_Data_Executing); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Attempt_Data_Waiting); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Attempt_Data_Finished); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution_Auth); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution_ID); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution_Data); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution_Data_DistributorInfo); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution_Data_Scheduling); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution_Data_Running); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution_Data_Stopping); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Execution_Data_Finished); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[16].OneofWrappers = []interface{}{
-		(*Attempt_Data_Scheduling_)(nil),
-		(*Attempt_Data_Executing_)(nil),
-		(*Attempt_Data_Waiting_)(nil),
-		(*Attempt_Data_Finished_)(nil),
-		(*Attempt_Data_AbnormalFinish)(nil),
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes[25].OneofWrappers = []interface{}{
-		(*Execution_Data_Scheduling_)(nil),
-		(*Execution_Data_Running_)(nil),
-		(*Execution_Data_Stopping_)(nil),
-		(*Execution_Data_Finished_)(nil),
-		(*Execution_Data_AbnormalFinish)(nil),
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDesc,
-			NumEnums:      4,
-			NumMessages:   32,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_depIdxs,
-		EnumInfos:         file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_enumTypes,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_service_v1_graph_data_proto = out.File
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_depIdxs = nil
-}
diff --git a/dm/api/service/v1/graph_data.proto b/dm/api/service/v1/graph_data.proto
deleted file mode 100644
index e599c28..0000000
--- a/dm/api/service/v1/graph_data.proto
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/service/v1;dm";
-
-import "google/protobuf/duration.proto";
-import "google/protobuf/timestamp.proto";
-
-import "go.chromium.org/luci/dm/api/service/v1/types.proto";
-
-package dm;
-
-message AbnormalFinish {
-  enum Status {
-    // This status is invalid and should not be used intentionally.
-    //
-    // It is a placeholder to identify 0-initialized AbnormalFinish structures.
-    INVALID = 0;
-
-    // This entity has a failed result.
-    //
-    // Executions: the distributor reported that the task executed and failed, OR
-    // the distributor reports success while the Execution is in the RUNNING
-    // state.
-    //
-    // Attempts: the last Execution had a FAILED Status.
-    //
-    // Retryable.
-    FAILED = 1;
-
-    // This entity failed in a bad way.
-    //
-    // Executions: The distributor told us that the job died violently while in
-    // the SCHEDULING, RUNNING or STOPPING state.
-    //
-    // Attempts: the last Execution had a CRASHED Status.
-    //
-    // Retryable.
-    CRASHED = 2;
-
-    // Waited too long for the job to start.
-    //
-    // Executions: the distributor couldn't start the job in time, OR DM failed
-    // to get a status update from the distributor in time (e.g. the state was
-    // SCHEDULING for too long).
-    //
-    // Attempts: the last Execution had an EXPIRED Status.
-    //
-    // Retryable.
-    EXPIRED = 3;
-
-    // The job started, but took too long.
-    //
-    // Executions: the distributor started the job, but it couldn't complete in
-    // time, OR DM failed to get a status update from the distributor in time
-    // (e.g. the state was RUNNING for too long).
-    //
-    // Attempts: the last Execution had an TIMED_OUT Status.
-    //
-    // Retryable.
-    TIMED_OUT = 4;
-
-    // The job was cancelled by an external entity (human, automated system).
-    //
-    // Executions: the distributor informing DM that the job was preemptively
-    // cancelled.
-    //
-    // Attempts: the last Execution had a CANCELLED Status, or this Attempt
-    // was cancelled via DM.
-    CANCELLED = 5;
-
-    // The job was prevented from running by the distributor (quota, permissions,
-    // etc.)
-    //
-    // Executions: the distributor refused to run this job.
-    //
-    // Attempts: the last Execution had a REJECTED Status.
-    REJECTED = 6;
-
-    // The job is unrecognized.
-    //
-    // Executions: the distributor doesn't know about this job, or has forgotten
-    // about it.
-    //
-    // Attempts: the last Execution had a MISSING Status.
-    MISSING = 7;
-
-    // The distributor ran the job, but returned garbage.
-    //
-    // Executions: the distributor returned a nominally successful result, but
-    // the Data portion of the result wasn't able to be normalized.
-    //
-    // Attempts: the last Execution had a RESULT_MALFORMED Status.
-    RESULT_MALFORMED = 8;
-  }
-
-  Status status = 1;
-  string reason = 2;
-}
-
-message Quest {
-  message ID {
-    string id = 1;
-  }
-  ID id = 1;
-
-  // DNE is set to true if this Quest does not exist. None of the following
-  // fields are valid if this is set to true.
-  bool DNE = 2;
-
-  message Desc {
-    // TODO(iannucci): have a 'simple_idempotent' quest mode which:
-    //   * isn't allowed/expected to call any API methods (ActivateExecution,
-    //   EnsureGraphData, or WalkGraph)
-    //   * only provides data back through the distributor-specific 'state'
-    //   field.
-    //
-    // Examples of use for this would be:
-    //   * simple test binaries that run/output to an ISOLATED_OUTDIR
-    //   * testing / ad-hoc bash scripts
-
-    // This names a specific distributor configuration (or alias) in the
-    // service's distributors.cfg file. This will be used to look up the
-    // distributor's implementation and connection information when Attempts for
-    // this Quest are Executed.
-    string distributor_config_name = 1;
-
-    // A JSON object which corresponds to the input parameters for the job.
-    // These will be passed in a distributor-specific way to the job. This is
-    // a freeform JSON object, and must parse as such, but otherwise doesn't
-    // necessarily have a server-enforced schema.
-    //
-    // The distributor implementation in DM will not use the contents of these
-    // to make any scheduling decisions.
-    //
-    // The distributor MAY choose to validate some schema for these parameters.
-    string parameters = 2;
-
-    // A JSON object which corresponds to the distributor-specific parameters
-    // for the job.
-    //
-    // The distributor defines and validates the schema for these, and will use
-    // the values herein to make decisions about how the job is run. It is up to
-    // the distributor whether these values are passed on to the job, and if so
-    // in what form.
-    string distributor_parameters = 3;
-
-    message Meta {
-      // This names the user/service account for all Attempts on this quest. You
-      // must have permission to use this account when creating the Quest and/or
-      // Attempts.
-      string as_account = 1;
-
-      // Retry specifies the number of times in a row that DM should re-Execute
-      // an Attempt due to the provided abnormal result.
-      //
-      // NOTE: The proto tag numbers for these MUST be aligned with the
-      // enumeration values of AbnormalFinish.Status!
-      message Retry {
-        // The number of times in a row to retry Executions which have an
-        // ABNORMAL_FINISHED status of FAILED.
-        uint32 failed = 1;
-
-        // The number of times in a row to retry Executions which have an
-        // ABNORMAL_FINISHED status of CRASHED.
-        uint32 crashed = 2;
-
-        // The number of times in a row to retry Executions which have an
-        // ABNORMAL_FINISHED status of EXPIRED.
-        uint32 expired = 3;
-
-        // The number of times in a row to retry Executions which have an
-        // ABNORMAL_FINISHED status of TIMED_OUT.
-        uint32 timed_out = 4;
-      }
-
-      // This affects how DM will retry the job payload in various exceptional
-      // circumstances.
-      Retry retry = 2;
-
-      // Timing describes the amount of time that Executions for this Quest
-      // should have, on the following timeline:
-      //   Event: execution sent to distributor
-      //     ^ "start" v
-      //   Event: execution sends ActivateExecution
-      //     ^ "run" v
-      //   Event: execution sends halting RPC (either ActivateExecution or
-      //     EnsureGraphData)
-      //     ^ "stop" v
-      //   Event: distributor gives execution result back to DM
-      //
-      // If the given timeout hits before the next event in the timeline, DM
-      // will mark the Execution as TIMED_OUT, and the appropriate retry policy
-      // will be applied.
-      //
-      // If a given timeout is unlimited, leave the duration unset or 0.
-      message Timeouts {
-        google.protobuf.Duration start = 1;
-        google.protobuf.Duration run = 2;
-        google.protobuf.Duration stop = 3;
-      }
-
-      Timeouts timeouts = 3;
-    }
-
-    // This is metadata which doesn't affect the functionality of the payload,
-    // but does affect how DM interacts with the distributor when scheduling
-    // Executions.
-    Meta meta = 4;
-  }
-
-  message TemplateSpec {
-    string project = 1;
-    string ref = 2;
-    string version = 3;
-    string name = 4;
-  }
-
-  message Data {
-    google.protobuf.Timestamp created = 1;
-    dm.Quest.Desc desc = 2;
-    repeated dm.Quest.TemplateSpec built_by = 3;
-  }
-  Data data = 3;
-
-  // key is the `id` field of the Attempt.ID
-  map<uint32, Attempt> attempts = 4;
-
-  // Partial is true iff the request asked for QuestData, but wasn't able to
-  // completely fill it.
-  bool partial = 16;
-}
-
-// JsonResult represents a free-form JSON object. It has a maximum size of
-// 256KB normalized (no extra whitespace). DM will normalize incoming
-// JSONObjects before recalculating their size.
-message JsonResult {
-  // Guaranteed to be a JSON object `{...}` or the empty string (if this is part
-  // of a Partial result from e.g. a WalkGraph RPC).
-  string object = 1;
-
-  // The length of data. If this message is non-nil, this will have a value even
-  // if object is empty (e.g. for a partial result). This is useful for query
-  // results where you either opt to not load the data (include.*.data ==
-  // false), or the response exceeds the size limit (so you can see how big the
-  // data would have been if the limit wasn't exceeded).
-  uint32 size = 2;
-
-  // The timestamp of when this JsonResult's contents expire. If omitted, it
-  // should be assumed that the contents never expire.
-  google.protobuf.Timestamp expiration = 3;
-}
-
-// Result holds either data OR abnormal finish information.
-message Result {
-  JsonResult data = 1;
-  AbnormalFinish abnormal_finish = 2;
-}
-
-message Attempt {
-  message ID {
-    string quest = 1;
-    uint32 id = 2;
-  }
-  ID id = 1;
-
-  // DNE is set to true if this Attempt does not exist. None of the following
-  // fields are valid if this is set to true.
-  bool DNE = 2;
-
-  enum State {
-    // The Attempt is waiting to be Executed.
-    SCHEDULING = 0;
-
-    // The Attempt is currently waiting for its current Execution to finish.
-    EXECUTING = 1;
-
-    // The Attempt is waiting for dependent Attempts to be resolved.
-    WAITING = 2;
-
-    // The Attempt is in its final state.
-    FINISHED = 3;
-
-    // The Attempt is in an abnormal final state.
-    ABNORMAL_FINISHED = 4;
-  }
-
-  message Data {
-    google.protobuf.Timestamp created = 1;
-    google.protobuf.Timestamp modified = 2;
-    uint32 num_executions = 3;
-
-    // This attempt is ready to be Executed, but hasn't been sent to the
-    // distributor yet.
-    message Scheduling {}
-
-    // This attempt has a live Execution (with the specified ID). Check the
-    // Execution state for more information.
-    message Executing {
-      uint32 cur_execution_id = 1;
-    }
-
-    // This attempt's last Execution stopped by adding dependencies.
-    message Waiting {
-      uint32 num_waiting = 1;
-    }
-
-    // This attempt is complete.
-    message Finished {
-      // The result of the Attempt. To obtain the distributor specific result
-      // for the last execution, make sure to include at least one Execution in
-      // your query.
-      //
-      // Only if `include.attempt.data == true`, will the response include
-      // data.object.
-      JsonResult data = 1;
-    }
-
-    oneof attempt_type {
-      Scheduling scheduling = 5;
-      Executing executing = 6;
-      Waiting waiting = 7;
-      Finished finished = 8;
-      AbnormalFinish abnormal_finish = 9;
-    }
-  }
-  Data data = 3;
-
-  // key is the `id` field of the Execution.ID
-  map<uint32, Execution> executions = 4;
-
-  dm.AttemptList fwd_deps = 5;
-  dm.AttemptList back_deps = 6;
-
-  message Partial {
-    // Data is true iff the AttemptData should have been filled, but wasn't
-    bool data = 1;
-
-    // Executions is true iff the Executions were requested, but not all of
-    // them could be loaded.
-    bool executions = 2;
-
-    // FwdDeps is true iff FwdDeps were requested, but not all of them could be
-    // loaded.
-    bool fwd_deps = 3;
-
-    // BackDeps is true iff BackDeps were requested, but not all of them could be
-    // loaded.
-    bool back_deps = 4;
-
-    enum Result {
-      // LOADED implies that the result was, in fact, loaded.
-      LOADED = 0;
-
-      // NOT_LOADED is set if the result failed to load because there was
-      // a transient error or the request ran out of time.
-      NOT_LOADED = 1;
-
-      // NOT_AUTHORIZED is set if the query was authenticated from an Execution
-      // whose Attempt doesn't depend on this one.
-      NOT_AUTHORIZED = 2;
-
-      // DATA_SIZE_LIMIT is set if the max_data_size limit was reached.
-      DATA_SIZE_LIMIT = 3;
-    }
-    // result is set if AttemptResults were requested, and the attempt_type is
-    // Finished, but for some reason the result but wasn't loaded.
-    Result result = 5;
-  }
-  // Partial values are true iff the request asked for AttemptData, Executions
-  // or Deps, but wasn't able to completely fill them. If Partial is omitted,
-  // it means that no partial data exists in this Attempt.
-  Partial partial = 16;
-}
-
-message Execution {
-  // Execution_Auth is a tuple of the requesting ExecutionID and the activated
-  // Execution Token (see the ActivateExecution rpc).
-  message Auth {
-    dm.Execution.ID id = 1;
-    bytes token = 2;
-  }
-
-  message ID {
-    string quest = 1;
-    uint32 attempt = 2;
-    uint32 id = 3;
-  }
-  ID id = 1;
-
-  enum State {
-    // The execution has been accepted by the distributor, but is not running
-    // yet.
-    SCHEDULING = 0;
-
-    // The execution is running (has activated with DM).
-    RUNNING = 1;
-
-    // The execution has been told to stop by DM, but we haven't heard from
-    // the distributor yet.
-    STOPPING = 2;
-
-    // The execution is in its final state.
-    FINISHED = 3;
-
-    // The execution is in an abnormal final state
-    ABNORMAL_FINISHED = 4;
-  }
-
-  message Data {
-    google.protobuf.Timestamp created = 1;
-    google.protobuf.Timestamp modified = 2;
-
-    message DistributorInfo {
-      string config_name = 1;
-      string config_version = 2;
-      string token = 3;
-      string url = 4;
-    }
-    DistributorInfo distributor_info = 3;
-
-    message Scheduling {}
-
-    message Running {}
-
-    message Stopping {}
-
-    message Finished {
-      JsonResult data = 1;
-    }
-
-    oneof execution_type {
-      Scheduling scheduling = 4;
-      Running running = 5;
-      Stopping stopping = 6;
-      Finished finished = 7;
-      AbnormalFinish abnormal_finish = 8;
-    }
-  }
-  Data data = 2;
-
-  // Partial is true iff the request asked for Executions, but wasn't able to
-  // completely fill them.
-  bool partial = 16;
-}
-
-// GraphData defines all of the DM graph data that may be returned from DM.
-//
-// Currently only WalkGraph returns GraphData, but in the future other APIs will
-// explore the graph in other ways, and they'll return this same data structure.
-//
-// The design of this message is intended to allow clients to easily accumulate
-// various GraphData from different sources in order to maintain an in-memory
-// cache of data that exists in DM, where that data is discovered across
-// multiple RPCs.
-message GraphData {
-  // Quests is the main entry point for all the graph data.
-  // key is the `id` field of the QuestID
-  map<string, Quest> quests = 1;
-
-  // HadErrors is set to true if the data represented here is a partial view
-  // of the requested data due to internal errors. The request may be repeated
-  // or the client may chose to make smaller queries into the portions of the
-  // graph that are missing.
-  //
-  // If HadErrors is set HadMore will also be set.
-  bool had_errors = 2;
-
-  // HadMore is set to true if the request stopped short of the full query
-  // result set due to things like:
-  //   * max response size limit
-  //   * max time limit (e.g. WalkGraphReq.MaxTime) being hit
-  //   * non-terminal errors encountered during the request (HadErrors will also
-  //     be true in this case).
-  //
-  // Note that this is different than the Partial booleans: This refers
-  // specifically to situations when Queries do not run to completion.
-  bool had_more = 3;
-}
-
diff --git a/dm/api/service/v1/graph_data_abnormal_finish.go b/dm/api/service/v1/graph_data_abnormal_finish.go
deleted file mode 100644
index 3cfc9cf..0000000
--- a/dm/api/service/v1/graph_data_abnormal_finish.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-// CouldRetry returns true iff this status code is retryable.
-func (s AbnormalFinish_Status) CouldRetry() bool {
-	switch s {
-	case AbnormalFinish_FAILED, AbnormalFinish_CRASHED,
-		AbnormalFinish_EXPIRED, AbnormalFinish_TIMED_OUT:
-
-		return true
-	}
-	return false
-}
diff --git a/dm/api/service/v1/graph_data_purge_timestamps.go b/dm/api/service/v1/graph_data_purge_timestamps.go
deleted file mode 100644
index 8e92d05..0000000
--- a/dm/api/service/v1/graph_data_purge_timestamps.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-// TimestampPurger is for testing: invoking this on a struct in this package
-// will remove all timestamps from it. This is useful for testing where the
-// timestamps are frequently just noise.
-type TimestampPurger interface {
-	PurgeTimestamps()
-}
-
-// PurgeTimestamps implements TimestampPurger.
-func (g *GraphData) PurgeTimestamps() {
-	if g == nil {
-		return
-	}
-	for _, q := range g.Quests {
-		q.PurgeTimestamps()
-	}
-}
-
-// PurgeTimestamps implements TimestampPurger.
-func (q *Quest) PurgeTimestamps() {
-	if q == nil {
-		return
-	}
-	q.Data.PurgeTimestamps()
-	for _, a := range q.Attempts {
-		a.PurgeTimestamps()
-	}
-}
-
-// PurgeTimestamps implements TimestampPurger.
-func (qd *Quest_Data) PurgeTimestamps() {
-	if qd == nil {
-		return
-	}
-	qd.Created = nil
-}
-
-// PurgeTimestamps implements TimestampPurger.
-func (a *Attempt) PurgeTimestamps() {
-	if a == nil {
-		return
-	}
-	a.Data.PurgeTimestamps()
-
-	for _, e := range a.Executions {
-		e.PurgeTimestamps()
-	}
-}
-
-// PurgeTimestamps implements TimestampPurger.
-func (ad *Attempt_Data) PurgeTimestamps() {
-	if ad == nil {
-		return
-	}
-	ad.Created = nil
-	ad.Modified = nil
-	if p, _ := ad.AttemptType.(TimestampPurger); p != nil {
-		p.PurgeTimestamps()
-	}
-}
-
-// PurgeTimestamps implements TimestampPurger.
-func (f *Attempt_Data_Finished_) PurgeTimestamps() {
-	if f.Finished.GetData() == nil {
-		return
-	}
-	f.Finished.Data.Expiration = nil
-}
-
-// PurgeTimestamps implements TimestampPurger.
-func (e *Execution) PurgeTimestamps() {
-	if e == nil {
-		return
-	}
-	e.Data.PurgeTimestamps()
-}
-
-// PurgeTimestamps implements TimestampPurger.
-func (ed *Execution_Data) PurgeTimestamps() {
-	if ed == nil {
-		return
-	}
-	ed.Created = nil
-	ed.Modified = nil
-}
diff --git a/dm/api/service/v1/graph_data_query.go b/dm/api/service/v1/graph_data_query.go
deleted file mode 100644
index 48faa2e..0000000
--- a/dm/api/service/v1/graph_data_query.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-// ToQuery generates a new GraphQuery.
-//
-// This generates a GraphQuery that queries for any Attempts which are marked as
-// Partial in the current GraphData.
-func (g *GraphData) ToQuery() (ret *GraphQuery) {
-	partials := map[string][]uint32{}
-	for qid, qst := range g.Quests {
-		// TODO(iannucci): handle q.Partial explicitly?
-		for aid, atmpt := range qst.Attempts {
-			if atmpt.Partial.Any() {
-				partials[qid] = append(partials[qid], aid)
-			}
-		}
-	}
-
-	if len(partials) > 0 {
-		ret = &GraphQuery{AttemptList: NewAttemptList(partials)}
-	}
-	return
-}
diff --git a/dm/api/service/v1/graph_data_update.go b/dm/api/service/v1/graph_data_update.go
deleted file mode 100644
index 0e2a6dc..0000000
--- a/dm/api/service/v1/graph_data_update.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"github.com/xtgo/set"
-)
-
-// UpdateWith updates this GraphData with all of the data contained in other.
-// Assumes that any mutable data in other is more up-to-date than the data in g.
-func (g *GraphData) UpdateWith(other *GraphData) {
-	for qid, q := range other.Quests {
-		if curQ, ok := g.Quests[qid]; !ok {
-			g.Quests[qid] = q
-		} else {
-			curQ.UpdateWith(q)
-		}
-	}
-}
-
-// UpdateWith updates this Quest with data from other.
-func (q *Quest) UpdateWith(o *Quest) {
-	if q.Data == nil {
-		q.Data = o.Data
-		q.Partial = false
-	} else if !o.Partial {
-		q.Data.UpdateWith(o.Data)
-		q.Partial = false
-	}
-	if q.Id == nil {
-		q.Id = o.Id
-	}
-	for aid, a := range o.Attempts {
-		if curA, ok := q.Attempts[aid]; !ok {
-			q.Attempts[aid] = a
-		} else {
-			curA.UpdateWith(a)
-		}
-	}
-}
-
-// UpdateWith updates this Quest_Data with data from other.
-func (q *Quest_Data) UpdateWith(other *Quest_Data) {
-	pivot := len(q.BuiltBy)
-	q.BuiltBy = append(q.BuiltBy, other.BuiltBy...)
-	q.BuiltBy = q.BuiltBy[:set.Union(QuestTemplateSpecs(q.BuiltBy), pivot)]
-}
-
-// UpdateWith updates this Attempt with data from other.
-func (a *Attempt) UpdateWith(other *Attempt) {
-	if a.Partial == nil {
-		a.Partial = &Attempt_Partial{}
-	}
-
-	if a.Data == nil {
-		a.Data = other.Data
-		a.Partial.Data = false
-	} else if other.Partial != nil && !other.Partial.Data {
-		a.Data.UpdateWith(other.Data)
-		a.Partial.Data = false
-	}
-
-	if a.Id == nil {
-		a.Id = other.Id
-	}
-
-	for eid, e := range other.Executions {
-		if curE, ok := a.Executions[eid]; !ok {
-			a.Executions[eid] = e
-		} else {
-			curE.UpdateWith(e)
-		}
-	}
-
-	if a.FwdDeps == nil {
-		a.FwdDeps = other.FwdDeps
-	} else {
-		a.FwdDeps.UpdateWith(other.FwdDeps)
-	}
-
-	if a.BackDeps == nil {
-		a.BackDeps = other.BackDeps
-	} else {
-		a.BackDeps.UpdateWith(other.BackDeps)
-	}
-}
-
-// UpdateWith updates this Attempt_Data with data from other.
-func (a *Attempt_Data) UpdateWith(other *Attempt_Data) {
-	if a.Created == nil {
-		a.Created = other.Created
-	}
-	if other.Modified != nil {
-		a.Modified = other.Modified
-	}
-	a.NumExecutions = other.NumExecutions
-	if other.AttemptType != nil {
-		a.AttemptType = other.AttemptType
-	}
-}
-
-// UpdateWith updates this Execution with data from other.
-func (e *Execution) UpdateWith(other *Execution) {
-	if e.Id == nil {
-		e.Id = other.Id
-	}
-	if e.Data == nil {
-		e.Data = other.Data
-		e.Partial = false
-	} else if !other.Partial {
-		e.Data.UpdateWith(other.Data)
-		e.Partial = false
-	}
-}
-
-// UpdateWith updates this Execution_Data with data from other.
-func (e *Execution_Data) UpdateWith(other *Execution_Data) {
-	if e.Created == nil {
-		e.Created = other.Created
-	}
-	if other.Modified != nil {
-		e.Modified = other.Modified
-	}
-	if other.DistributorInfo != nil {
-		e.DistributorInfo = other.DistributorInfo
-	}
-	if other.ExecutionType != nil {
-		e.ExecutionType = other.ExecutionType
-	}
-}
diff --git a/dm/api/service/v1/graph_query.pb.go b/dm/api/service/v1/graph_query.pb.go
deleted file mode 100644
index e126b38..0000000
--- a/dm/api/service/v1/graph_query.pb.go
+++ /dev/null
@@ -1,541 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/service/v1/graph_query.proto
-
-package dm
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type GraphQuery_Search_Domain int32
-
-const (
-	GraphQuery_Search_QUEST   GraphQuery_Search_Domain = 0
-	GraphQuery_Search_ATTEMPT GraphQuery_Search_Domain = 1
-)
-
-// Enum value maps for GraphQuery_Search_Domain.
-var (
-	GraphQuery_Search_Domain_name = map[int32]string{
-		0: "QUEST",
-		1: "ATTEMPT",
-	}
-	GraphQuery_Search_Domain_value = map[string]int32{
-		"QUEST":   0,
-		"ATTEMPT": 1,
-	}
-)
-
-func (x GraphQuery_Search_Domain) Enum() *GraphQuery_Search_Domain {
-	p := new(GraphQuery_Search_Domain)
-	*p = x
-	return p
-}
-
-func (x GraphQuery_Search_Domain) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (GraphQuery_Search_Domain) Descriptor() protoreflect.EnumDescriptor {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_enumTypes[0].Descriptor()
-}
-
-func (GraphQuery_Search_Domain) Type() protoreflect.EnumType {
-	return &file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_enumTypes[0]
-}
-
-func (x GraphQuery_Search_Domain) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Use GraphQuery_Search_Domain.Descriptor instead.
-func (GraphQuery_Search_Domain) EnumDescriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescGZIP(), []int{0, 1, 0}
-}
-
-// GraphQuery represents a single query into the state of DM's dependency graph.
-// It's a required parameter for WalkGraphReq.
-type GraphQuery struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// AttemptList allows you to list one or more specific attempts as the result
-	// of the query. If a quest contains the attempt number 0, or is empty, it
-	// means 'all attempts for this quest'.
-	AttemptList *AttemptList `protobuf:"bytes,1,opt,name=attempt_list,json=attemptList,proto3" json:"attempt_list,omitempty"`
-	// attempt_range allows you to list a range of attempts in a single quest.
-	// low must be > 0, and high must be > low. The range is [low, high). High may
-	// be higher than the highest attempt, and low may be lower than the lowest
-	// attempt (but not 0).
-	AttemptRange []*GraphQuery_AttemptRange `protobuf:"bytes,2,rep,name=attempt_range,json=attemptRange,proto3" json:"attempt_range,omitempty"`
-	Search       []*GraphQuery_Search       `protobuf:"bytes,3,rep,name=search,proto3" json:"search,omitempty"`
-}
-
-func (x *GraphQuery) Reset() {
-	*x = GraphQuery{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *GraphQuery) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GraphQuery) ProtoMessage() {}
-
-func (x *GraphQuery) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GraphQuery.ProtoReflect.Descriptor instead.
-func (*GraphQuery) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *GraphQuery) GetAttemptList() *AttemptList {
-	if x != nil {
-		return x.AttemptList
-	}
-	return nil
-}
-
-func (x *GraphQuery) GetAttemptRange() []*GraphQuery_AttemptRange {
-	if x != nil {
-		return x.AttemptRange
-	}
-	return nil
-}
-
-func (x *GraphQuery) GetSearch() []*GraphQuery_Search {
-	if x != nil {
-		return x.Search
-	}
-	return nil
-}
-
-type GraphQuery_AttemptRange struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Quest string `protobuf:"bytes,1,opt,name=quest,proto3" json:"quest,omitempty"`
-	Low   uint32 `protobuf:"varint,2,opt,name=low,proto3" json:"low,omitempty"`
-	High  uint32 `protobuf:"varint,3,opt,name=high,proto3" json:"high,omitempty"`
-}
-
-func (x *GraphQuery_AttemptRange) Reset() {
-	*x = GraphQuery_AttemptRange{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *GraphQuery_AttemptRange) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GraphQuery_AttemptRange) ProtoMessage() {}
-
-func (x *GraphQuery_AttemptRange) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GraphQuery_AttemptRange.ProtoReflect.Descriptor instead.
-func (*GraphQuery_AttemptRange) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescGZIP(), []int{0, 0}
-}
-
-func (x *GraphQuery_AttemptRange) GetQuest() string {
-	if x != nil {
-		return x.Quest
-	}
-	return ""
-}
-
-func (x *GraphQuery_AttemptRange) GetLow() uint32 {
-	if x != nil {
-		return x.Low
-	}
-	return 0
-}
-
-func (x *GraphQuery_AttemptRange) GetHigh() uint32 {
-	if x != nil {
-		return x.High
-	}
-	return 0
-}
-
-// A Search allows you to query objects whose properties match all of the
-// provided filters. Filters take the form of a dot-delimited path. For
-// example, say that we had the following objects:
-//
-//   Quest(id=deadbeef):
-//     created = <timestamp>  #sort
-//     descriptor.distributor_config_name = "foo"
-//     descriptor.json_payload = {
-//       "key": "value",
-//       "multi": ["some", 10, "values", true],
-//       "sub": [{"msg": 11}, {"msg": 12}],
-//     }
-//
-//   Attempt(id=deadbeef|1):
-//     created = <timestamp>  #sort
-//     attempt_type = Finished
-//     finished.expiration = <timestamp>
-//     finished.json_result = {
-//       "rslt": "yes",
-//       "ok": true,
-//     }
-//
-// Then you could query (in pseudo-proto):
-//   domain: Attempt
-//   approx_filters: {
-//     "attempt_type": ["Finished"],
-//     "$quest.descriptor.json_payload.multi": [true, 10],
-//     "$quest.descriptor.json_payload.sub.msg": [11, 10],
-//     "finished.json_result.ok": [true],
-//   }
-//
-// Or:
-//
-//   domain: Attempt
-//   exact_filters: {
-//     "$quest.descriptor.json_payload.multi[1]": [10],
-//     "$quest.descriptor.json_payload.sub[0].msg": [11],
-//   }
-//
-// Literal '.' and '[' characters may be escaped with a backslash.
-type GraphQuery_Search struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Domain indicates which class of objects your query applies to. The fields
-	// available to query are defined by the `data` field in the corresponding
-	// GraphData message.
-	//
-	// Additionally `Attempt` has a special field $quest whose subfields are
-	// queriable in the exact same way that a search in a Quest domain works.
-	Domain GraphQuery_Search_Domain `protobuf:"varint,1,opt,name=domain,proto3,enum=dm.GraphQuery_Search_Domain" json:"domain,omitempty"`
-	// Start and End are optional restrictions on the first sort property. For
-	// now, these are just restrictions on the 'created' timestamp for either
-	// the Quest or Attempt, depending on the SearchDomain.
-	Start *PropertyValue `protobuf:"bytes,3,opt,name=start,proto3" json:"start,omitempty"`
-	End   *PropertyValue `protobuf:"bytes,4,opt,name=end,proto3" json:"end,omitempty"`
-	// ApproxFilters allows you to filter on 'approximate' fields. Approximate
-	// fields are the json path to the value, without any array subscripts. For
-	// example, if your document looked like:
-	//
-	//   {
-	//     "some": ["list", {"of": ["data", "and", "stuff"]}],
-	//   }
-	//
-	// Then the following approximate filters would match:
-	//   "some" = ["list"]
-	//   "some.of" = ["data"]
-	//   "some.of" = ["and"]
-	//   "some.of" = ["stuff"]
-	//   "some.of" = ["stuff", "and"]
-	//   "some.of" = ["stuff", "and", "data"]
-	//
-	// This is useful for filtering documents where the order of parameters
-	// in a list or sublist isn't known, or doesn't matter.
-	ApproxFilters map[string]*MultiPropertyValue `protobuf:"bytes,5,rep,name=approx_filters,json=approxFilters,proto3" json:"approx_filters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	// ExactFilters allows you to filter on 'exact' fields. Exact fields are the
-	// json path to the value, including array subscripts. For example if your
-	// document looked like:
-	//
-	//   {
-	//     "some": ["list", {"of": ["data", "and", "stuff"]}],
-	//   }
-	//
-	// Then the following exact filters would match:
-	//   "some[0]" = "list"
-	//   "some[1].of[0]" = "data"
-	//   "some[1].of[1]" = "and"
-	//   "some[1].of[2]" = "stuff"
-	//
-	// This is useful for filtering documents where the order of parameters
-	// in a list or sublist matters.
-	ExactFilters map[string]*PropertyValue `protobuf:"bytes,6,rep,name=exact_filters,json=exactFilters,proto3" json:"exact_filters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-}
-
-func (x *GraphQuery_Search) Reset() {
-	*x = GraphQuery_Search{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *GraphQuery_Search) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GraphQuery_Search) ProtoMessage() {}
-
-func (x *GraphQuery_Search) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use GraphQuery_Search.ProtoReflect.Descriptor instead.
-func (*GraphQuery_Search) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescGZIP(), []int{0, 1}
-}
-
-func (x *GraphQuery_Search) GetDomain() GraphQuery_Search_Domain {
-	if x != nil {
-		return x.Domain
-	}
-	return GraphQuery_Search_QUEST
-}
-
-func (x *GraphQuery_Search) GetStart() *PropertyValue {
-	if x != nil {
-		return x.Start
-	}
-	return nil
-}
-
-func (x *GraphQuery_Search) GetEnd() *PropertyValue {
-	if x != nil {
-		return x.End
-	}
-	return nil
-}
-
-func (x *GraphQuery_Search) GetApproxFilters() map[string]*MultiPropertyValue {
-	if x != nil {
-		return x.ApproxFilters
-	}
-	return nil
-}
-
-func (x *GraphQuery_Search) GetExactFilters() map[string]*PropertyValue {
-	if x != nil {
-		return x.ExactFilters
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_service_v1_graph_query_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDesc = []byte{
-	0x0a, 0x38, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x71,
-	0x75, 0x65, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x64, 0x6d, 0x1a, 0x32,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x22, 0x8a, 0x06, 0x0a, 0x0a, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x75, 0x65, 0x72,
-	0x79, 0x12, 0x32, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x6c, 0x69, 0x73,
-	0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74,
-	0x65, 0x6d, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70,
-	0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74,
-	0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x64,
-	0x6d, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x41, 0x74, 0x74,
-	0x65, 0x6d, 0x70, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x6d,
-	0x70, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x65, 0x61, 0x72, 0x63,
-	0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x64, 0x6d, 0x2e, 0x47, 0x72, 0x61,
-	0x70, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x06,
-	0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x1a, 0x4a, 0x0a, 0x0c, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70,
-	0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03,
-	0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6c, 0x6f, 0x77, 0x12, 0x12,
-	0x0a, 0x04, 0x68, 0x69, 0x67, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x68, 0x69,
-	0x67, 0x68, 0x1a, 0x8a, 0x04, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x34, 0x0a,
-	0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e,
-	0x64, 0x6d, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x65,
-	0x61, 0x72, 0x63, 0x68, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d,
-	0x61, 0x69, 0x6e, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x11, 0x2e, 0x64, 0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79,
-	0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x23, 0x0a, 0x03,
-	0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x64, 0x6d, 0x2e, 0x50,
-	0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x65, 0x6e,
-	0x64, 0x12, 0x4f, 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x5f, 0x66, 0x69, 0x6c, 0x74,
-	0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x64, 0x6d, 0x2e, 0x47,
-	0x72, 0x61, 0x70, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e,
-	0x74, 0x72, 0x79, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x46, 0x69, 0x6c, 0x74, 0x65,
-	0x72, 0x73, 0x12, 0x4c, 0x0a, 0x0d, 0x65, 0x78, 0x61, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74,
-	0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x64, 0x6d, 0x2e, 0x47,
-	0x72, 0x61, 0x70, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x2e, 0x45, 0x78, 0x61, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74,
-	0x72, 0x79, 0x52, 0x0c, 0x65, 0x78, 0x61, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73,
-	0x1a, 0x58, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72,
-	0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
-	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x64, 0x6d, 0x2e, 0x4d, 0x75, 0x6c,
-	0x74, 0x69, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
-	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x52, 0x0a, 0x11, 0x45, 0x78,
-	0x61, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
-	0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
-	0x79, 0x12, 0x27, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x11, 0x2e, 0x64, 0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61,
-	0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x20,
-	0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x51, 0x55, 0x45, 0x53,
-	0x54, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x54, 0x54, 0x45, 0x4d, 0x50, 0x54, 0x10, 0x01,
-	0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x07, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, 0x42,
-	0x2b, 0x5a, 0x29, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f,
-	0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73,
-	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x6d, 0x62, 0x06, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescData = file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
-var file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_goTypes = []interface{}{
-	(GraphQuery_Search_Domain)(0),   // 0: dm.GraphQuery.Search.Domain
-	(*GraphQuery)(nil),              // 1: dm.GraphQuery
-	(*GraphQuery_AttemptRange)(nil), // 2: dm.GraphQuery.AttemptRange
-	(*GraphQuery_Search)(nil),       // 3: dm.GraphQuery.Search
-	nil,                             // 4: dm.GraphQuery.Search.ApproxFiltersEntry
-	nil,                             // 5: dm.GraphQuery.Search.ExactFiltersEntry
-	(*AttemptList)(nil),             // 6: dm.AttemptList
-	(*PropertyValue)(nil),           // 7: dm.PropertyValue
-	(*MultiPropertyValue)(nil),      // 8: dm.MultiPropertyValue
-}
-var file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_depIdxs = []int32{
-	6,  // 0: dm.GraphQuery.attempt_list:type_name -> dm.AttemptList
-	2,  // 1: dm.GraphQuery.attempt_range:type_name -> dm.GraphQuery.AttemptRange
-	3,  // 2: dm.GraphQuery.search:type_name -> dm.GraphQuery.Search
-	0,  // 3: dm.GraphQuery.Search.domain:type_name -> dm.GraphQuery.Search.Domain
-	7,  // 4: dm.GraphQuery.Search.start:type_name -> dm.PropertyValue
-	7,  // 5: dm.GraphQuery.Search.end:type_name -> dm.PropertyValue
-	4,  // 6: dm.GraphQuery.Search.approx_filters:type_name -> dm.GraphQuery.Search.ApproxFiltersEntry
-	5,  // 7: dm.GraphQuery.Search.exact_filters:type_name -> dm.GraphQuery.Search.ExactFiltersEntry
-	8,  // 8: dm.GraphQuery.Search.ApproxFiltersEntry.value:type_name -> dm.MultiPropertyValue
-	7,  // 9: dm.GraphQuery.Search.ExactFiltersEntry.value:type_name -> dm.PropertyValue
-	10, // [10:10] is the sub-list for method output_type
-	10, // [10:10] is the sub-list for method input_type
-	10, // [10:10] is the sub-list for extension type_name
-	10, // [10:10] is the sub-list for extension extendee
-	0,  // [0:10] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_init() }
-func file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_init() {
-	if File_go_chromium_org_luci_dm_api_service_v1_graph_query_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_init()
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GraphQuery); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GraphQuery_AttemptRange); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GraphQuery_Search); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDesc,
-			NumEnums:      1,
-			NumMessages:   5,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_depIdxs,
-		EnumInfos:         file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_enumTypes,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_service_v1_graph_query_proto = out.File
-	file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_depIdxs = nil
-}
diff --git a/dm/api/service/v1/graph_query.proto b/dm/api/service/v1/graph_query.proto
deleted file mode 100644
index d6cba9d..0000000
--- a/dm/api/service/v1/graph_query.proto
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/service/v1;dm";
-
-import "go.chromium.org/luci/dm/api/service/v1/types.proto";
-
-package dm;
-
-// GraphQuery represents a single query into the state of DM's dependency graph.
-// It's a required parameter for WalkGraphReq.
-message GraphQuery {
-  // AttemptList allows you to list one or more specific attempts as the result
-  // of the query. If a quest contains the attempt number 0, or is empty, it
-  // means 'all attempts for this quest'.
-  dm.AttemptList attempt_list = 1;
-
-  message AttemptRange {
-    string quest = 1;
-    uint32 low = 2;
-    uint32 high = 3;
-  }
-  // attempt_range allows you to list a range of attempts in a single quest.
-  // low must be > 0, and high must be > low. The range is [low, high). High may
-  // be higher than the highest attempt, and low may be lower than the lowest
-  // attempt (but not 0).
-  repeated AttemptRange attempt_range = 2;
-
-  // A Search allows you to query objects whose properties match all of the
-  // provided filters. Filters take the form of a dot-delimited path. For
-  // example, say that we had the following objects:
-  //
-  //   Quest(id=deadbeef):
-  //     created = <timestamp>  #sort
-  //     descriptor.distributor_config_name = "foo"
-  //     descriptor.json_payload = {
-  //       "key": "value",
-  //       "multi": ["some", 10, "values", true],
-  //       "sub": [{"msg": 11}, {"msg": 12}],
-  //     }
-  //
-  //   Attempt(id=deadbeef|1):
-  //     created = <timestamp>  #sort
-  //     attempt_type = Finished
-  //     finished.expiration = <timestamp>
-  //     finished.json_result = {
-  //       "rslt": "yes",
-  //       "ok": true,
-  //     }
-  //
-  // Then you could query (in pseudo-proto):
-  //   domain: Attempt
-  //   approx_filters: {
-  //     "attempt_type": ["Finished"],
-  //     "$quest.descriptor.json_payload.multi": [true, 10],
-  //     "$quest.descriptor.json_payload.sub.msg": [11, 10],
-  //     "finished.json_result.ok": [true],
-  //   }
-  //
-  // Or:
-  //
-  //   domain: Attempt
-  //   exact_filters: {
-  //     "$quest.descriptor.json_payload.multi[1]": [10],
-  //     "$quest.descriptor.json_payload.sub[0].msg": [11],
-  //   }
-  //
-  // Literal '.' and '[' characters may be escaped with a backslash.
-  message Search {
-    enum Domain {
-      QUEST = 0;
-      ATTEMPT = 1;
-    }
-    // Domain indicates which class of objects your query applies to. The fields
-    // available to query are defined by the `data` field in the corresponding
-    // GraphData message.
-    //
-    // Additionally `Attempt` has a special field $quest whose subfields are
-    // queriable in the exact same way that a search in a Quest domain works.
-    Domain domain = 1;
-
-    // 2 is reserved for sort_by. For now everything will sort by "created", but
-    // it may be possible to expand quest and/or result payloads in the future
-    // so that they can elect alternate sort-orders for themselves.
-    reserved "sort_by";
-    reserved 2;
-
-    // Start and End are optional restrictions on the first sort property. For
-    // now, these are just restrictions on the 'created' timestamp for either
-    // the Quest or Attempt, depending on the SearchDomain.
-    dm.PropertyValue start = 3;
-    dm.PropertyValue end = 4;
-
-    // ApproxFilters allows you to filter on 'approximate' fields. Approximate
-    // fields are the json path to the value, without any array subscripts. For
-    // example, if your document looked like:
-    //
-    //   {
-    //     "some": ["list", {"of": ["data", "and", "stuff"]}],
-    //   }
-    //
-    // Then the following approximate filters would match:
-    //   "some" = ["list"]
-    //   "some.of" = ["data"]
-    //   "some.of" = ["and"]
-    //   "some.of" = ["stuff"]
-    //   "some.of" = ["stuff", "and"]
-    //   "some.of" = ["stuff", "and", "data"]
-    //
-    // This is useful for filtering documents where the order of parameters
-    // in a list or sublist isn't known, or doesn't matter.
-    map<string, dm.MultiPropertyValue> approx_filters = 5;
-
-    // ExactFilters allows you to filter on 'exact' fields. Exact fields are the
-    // json path to the value, including array subscripts. For example if your
-    // document looked like:
-    //
-    //   {
-    //     "some": ["list", {"of": ["data", "and", "stuff"]}],
-    //   }
-    //
-    // Then the following exact filters would match:
-    //   "some[0]" = "list"
-    //   "some[1].of[0]" = "data"
-    //   "some[1].of[1]" = "and"
-    //   "some[1].of[2]" = "stuff"
-    //
-    // This is useful for filtering documents where the order of parameters
-    // in a list or sublist matters.
-    map<string, dm.PropertyValue> exact_filters = 6;
-  }
-  repeated Search search = 3;
-}
diff --git a/dm/api/service/v1/graph_query_normalize.go b/dm/api/service/v1/graph_query_normalize.go
deleted file mode 100644
index 0c5233c..0000000
--- a/dm/api/service/v1/graph_query_normalize.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"fmt"
-
-	"go.chromium.org/luci/common/errors"
-)
-
-// Normalize returns an error iff this GraphQuery is not valid.
-func (g *GraphQuery) Normalize() error {
-	if err := g.AttemptList.Normalize(); err != nil {
-		return err
-	}
-	if len(g.AttemptRange) > 0 {
-		lme := errors.NewLazyMultiError(len(g.AttemptRange))
-		for i, rng := range g.AttemptRange {
-			lme.Assign(i, rng.Normalize())
-		}
-		if err := lme.Get(); err != nil {
-			return err
-		}
-	}
-	if len(g.Search) > 0 {
-		lme := errors.NewLazyMultiError(len(g.Search))
-		for i, s := range g.Search {
-			lme.Assign(i, s.Normalize())
-		}
-		if err := lme.Get(); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// Normalize returns nil iff this AttemptRange is in a bad state.
-func (al *GraphQuery_AttemptRange) Normalize() error {
-	if al.Quest == "" {
-		return fmt.Errorf("must specify quest")
-	}
-	if al.Low == 0 {
-		return fmt.Errorf("must specify low")
-	}
-	if al.High <= al.Low {
-		return fmt.Errorf("high must be > low")
-	}
-	return nil
-}
-
-// Normalize returns nil iff this Search is in a bad state.
-func (s *GraphQuery_Search) Normalize() error {
-	// for now, start and end MUST be timestamp values.
-	switch s.Start.Value.(type) {
-	case *PropertyValue_Time:
-	default:
-		return fmt.Errorf("invalid Start type: %T", s.Start.Value)
-	}
-	switch s.End.Value.(type) {
-	case *PropertyValue_Time:
-	default:
-		return fmt.Errorf("invalid End type: %T", s.End.Value)
-	}
-	return nil
-}
diff --git a/dm/api/service/v1/id_helpers.go b/dm/api/service/v1/id_helpers.go
deleted file mode 100644
index 96e9728..0000000
--- a/dm/api/service/v1/id_helpers.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-// Equals returns true iff the two Quest_IDs are equivalent.
-func (q *Quest_ID) Equals(o *Quest_ID) bool {
-	return q.Id == o.Id
-}
-
-// QuestID is a helper function to obtain the *Quest_ID from this Attempt_ID.
-func (a *Attempt_ID) QuestID() *Quest_ID {
-	return &Quest_ID{Id: a.Quest}
-}
-
-// Equals returns true iff the two Attempt_IDs are equivalent.
-func (a *Attempt_ID) Equals(o *Attempt_ID) bool {
-	return a.Quest == o.Quest && a.Id == o.Id
-}
-
-// Execution returns an Execution_ID for this Attempt.
-func (a *Attempt_ID) Execution(eid uint32) *Execution_ID {
-	return &Execution_ID{Quest: a.Quest, Attempt: a.Id, Id: eid}
-}
-
-// QuestID is a helper function to obtain the *Quest_ID from this Execution_ID.
-func (e *Execution_ID) QuestID() *Quest_ID {
-	return &Quest_ID{Id: e.Quest}
-}
-
-// AttemptID is a helper function to obtain the *Attempt_ID from this
-// Execution_ID.
-func (e *Execution_ID) AttemptID() *Attempt_ID {
-	return &Attempt_ID{Quest: e.Quest, Id: e.Attempt}
-}
-
-// Equals returns true iff the two Execution_IDs are equivalent.
-func (e *Execution_ID) Equals(o *Execution_ID) bool {
-	return e.Quest == o.Quest && e.Attempt == o.Attempt && e.Id == o.Id
-}
diff --git a/dm/api/service/v1/json_result.go b/dm/api/service/v1/json_result.go
deleted file mode 100644
index f920769..0000000
--- a/dm/api/service/v1/json_result.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"fmt"
-
-	template "go.chromium.org/luci/common/data/text/templateproto"
-)
-
-// JSONObjectMaxLength is the maximum number of bytes that may be present in the
-// Object field of a normalized JSONObject.
-const JSONObjectMaxLength = 256 * 1024
-
-// JSONNonNormalizedSizeFactor is the excess multiple of JSONObjectMaxLength
-// that a non-normalized json object must be smaller than. Otherwise we won't
-// attempt to normalize it at all.
-const JSONNonNormalizedSizeFactor = 0.1
-
-var jsonNonNormalizedSize int
-
-func init() {
-	// can't do this conversion statically because reasons
-	siz := JSONObjectMaxLength * (1 + JSONNonNormalizedSizeFactor)
-	jsonNonNormalizedSize = int(siz)
-}
-
-// Normalize normalizes the JSONObject (ensures it's an object, removes
-// whitespace, sorts keys, normalizes Size value, etc.)
-func (j *JsonResult) Normalize() error {
-	if j == nil {
-		return nil
-	}
-	if j.Object == "" {
-		j.Size = 0
-		return nil
-	}
-	if len(j.Object) > jsonNonNormalizedSize {
-		return fmt.Errorf(
-			"JSONObject.Object length exceeds max non-normalized length: %d > %d (max)",
-			len(j.Object), jsonNonNormalizedSize)
-	}
-	normed, err := template.NormalizeJSON(j.Object, true)
-	if err != nil {
-		return err
-	}
-	if len(normed) > JSONObjectMaxLength {
-		return fmt.Errorf(
-			"JSONObject.Object length exceeds max: %d > %d (max)",
-			len(normed), JSONObjectMaxLength)
-	}
-	j.Object = normed
-	j.Size = uint32(len(j.Object))
-	return nil
-}
diff --git a/dm/api/service/v1/pb.discovery.go b/dm/api/service/v1/pb.discovery.go
deleted file mode 100644
index 3214840..0000000
--- a/dm/api/service/v1/pb.discovery.go
+++ /dev/null
@@ -1,1888 +0,0 @@
-// Code generated by cproto. DO NOT EDIT.
-
-package dm
-
-import "go.chromium.org/luci/grpc/discovery"
-
-import "google.golang.org/protobuf/types/descriptorpb"
-
-func init() {
-	discovery.RegisterDescriptorSetCompressed(
-		[]string{
-			"dm.Deps",
-		},
-		[]byte{31, 139,
-			8, 0, 0, 0, 0, 0, 0, 255, 236, 253, 11, 120, 28, 201,
-			113, 32, 8, 163, 42, 171, 27, 141, 196, 187, 8, 130, 96, 115,
-			72, 230, 128, 15, 0, 100, 163, 193, 199, 204, 72, 195, 25, 142,
-			4, 18, 224, 176, 71, 32, 64, 53, 64, 141, 102, 102, 71, 100,
-			161, 59, 27, 93, 98, 117, 85, 79, 85, 53, 64, 204, 136, 182,
-			172, 145, 60, 150, 236, 93, 253, 178, 246, 215, 158, 214, 178, 189,
-			182, 100, 239, 90, 159, 252, 88, 249, 177, 103, 251, 78, 62, 219,
-			235, 179, 37, 219, 242, 249, 243, 249, 37, 249, 185, 62, 127, 183,
-			182, 111, 237, 239, 211, 237, 222, 249, 113, 178, 239, 139, 200, 204,
-			170, 172, 6, 248, 26, 217, 183, 223, 250, 27, 124, 26, 177, 51,
-			42, 159, 145, 153, 145, 17, 145, 145, 17, 244, 183, 142, 209, 67,
-			27, 65, 176, 225, 241, 185, 118, 24, 196, 193, 122, 167, 49, 87,
-			239, 132, 78, 236, 6, 126, 25, 33, 246, 176, 248, 94, 86, 223,
-			39, 207, 209, 194, 130, 204, 98, 79, 208, 222, 136, 215, 2, 191,
-			30, 77, 24, 204, 152, 38, 85, 149, 180, 199, 104, 206, 119, 252,
-			32, 154, 48, 153, 49, 157, 171, 138, 196, 133, 87, 13, 186, 167,
-			22, 180, 202, 93, 117, 94, 24, 84, 53, 94, 5, 200, 85, 227,
-			249, 211, 50, 199, 70, 224, 57, 254, 70, 57, 8, 55, 210, 14,
-			198, 219, 109, 30, 205, 221, 244, 131, 45, 63, 233, 108, 123, 253,
-			47, 13, 227, 187, 77, 242, 244, 213, 11, 159, 54, 15, 61, 45,
-			10, 95, 149, 37, 202, 207, 114, 207, 123, 27, 228, 95, 131, 162,
-			207, 124, 233, 8, 205, 219, 214, 161, 158, 200, 160, 191, 52, 64,
-			141, 1, 155, 28, 234, 177, 207, 252, 244, 0, 195, 2, 181, 192,
-			99, 23, 58, 141, 6, 15, 35, 54, 203, 68, 85, 83, 17, 171,
-			59, 177, 195, 92, 63, 230, 97, 173, 233, 248, 27, 156, 53, 130,
-			176, 229, 196, 148, 93, 12, 218, 219, 161, 187, 209, 140, 217, 153,
-			83, 167, 222, 44, 11, 176, 138, 95, 43, 51, 54, 239, 121, 12,
-			191, 69, 44, 228, 17, 15, 55, 121, 189, 76, 89, 51, 142, 219,
-			209, 185, 185, 185, 58, 223, 228, 94, 208, 230, 97, 164, 16, 82,
-			11, 90, 98, 156, 181, 192, 155, 93, 23, 157, 152, 163, 148, 85,
-			121, 221, 141, 226, 208, 93, 239, 192, 96, 153, 227, 215, 89, 39,
-			226, 204, 245, 89, 20, 116, 194, 26, 71, 200, 186, 235, 59, 225,
-			54, 246, 43, 42, 177, 45, 55, 110, 178, 32, 196, 127, 131, 78,
-			76, 89, 43, 168, 187, 13, 183, 134, 232, 42, 49, 39, 228, 172,
-			205, 195, 150, 27, 199, 188, 206, 218, 97, 176, 233, 214, 121, 157,
-			197, 77, 39, 102, 113, 19, 70, 231, 121, 193, 150, 235, 111, 48,
-			152, 79, 23, 10, 69, 80, 136, 178, 22, 143, 207, 81, 202, 224,
-			239, 68, 87, 199, 34, 22, 52, 84, 143, 106, 65, 157, 179, 86,
-			39, 138, 89, 200, 99, 199, 245, 177, 86, 103, 61, 216, 132, 79,
-			18, 99, 148, 249, 65, 236, 214, 120, 137, 197, 77, 55, 98, 158,
-			27, 197, 80, 131, 222, 162, 95, 239, 234, 78, 221, 141, 106, 158,
-			227, 182, 120, 88, 190, 83, 39, 92, 95, 199, 133, 234, 68, 59,
-			12, 234, 157, 26, 79, 251, 65, 211, 142, 124, 77, 253, 160, 76,
-			142, 174, 30, 212, 58, 45, 238, 199, 142, 154, 164, 185, 32, 100,
-			65, 220, 228, 33, 107, 57, 49, 15, 93, 199, 139, 82, 84, 227,
-			4, 197, 77, 78, 153, 222, 251, 100, 80, 203, 220, 197, 146, 80,
-			177, 239, 180, 56, 116, 72, 95, 91, 126, 144, 126, 67, 188, 187,
-			113, 4, 35, 242, 69, 85, 65, 24, 177, 150, 179, 205, 214, 57,
-			172, 148, 58, 139, 3, 198, 253, 122, 16, 70, 28, 22, 69, 59,
-			12, 90, 65, 204, 153, 192, 73, 28, 177, 58, 15, 221, 77, 94,
-			103, 141, 48, 104, 81, 129, 133, 40, 104, 196, 91, 176, 76, 228,
-			10, 98, 81, 155, 215, 96, 5, 177, 118, 232, 194, 194, 10, 97,
-			237, 248, 98, 21, 69, 17, 246, 157, 178, 181, 203, 149, 85, 182,
-			186, 114, 105, 237, 217, 249, 234, 34, 171, 172, 178, 171, 213, 149,
-			119, 84, 22, 22, 23, 216, 133, 231, 216, 218, 229, 69, 118, 113,
-			229, 234, 115, 213, 202, 211, 151, 215, 216, 229, 149, 165, 133, 197,
-			234, 42, 155, 95, 94, 96, 23, 87, 150, 215, 170, 149, 11, 215,
-			214, 86, 170, 171, 148, 77, 206, 175, 178, 202, 234, 36, 126, 153,
-			95, 126, 142, 45, 190, 243, 106, 117, 113, 117, 149, 173, 84, 89,
-			229, 202, 213, 165, 202, 226, 2, 123, 118, 190, 90, 157, 95, 94,
-			171, 44, 174, 150, 88, 101, 249, 226, 210, 181, 133, 202, 242, 211,
-			37, 118, 225, 218, 26, 91, 94, 89, 163, 108, 169, 114, 165, 178,
-			182, 184, 192, 214, 86, 74, 216, 236, 206, 114, 108, 229, 18, 187,
-			178, 88, 189, 120, 121, 126, 121, 109, 254, 66, 101, 169, 178, 246,
-			28, 54, 120, 169, 178, 182, 12, 141, 93, 90, 169, 82, 54, 207,
-			174, 206, 87, 215, 42, 23, 175, 45, 205, 87, 217, 213, 107, 213,
-			171, 43, 171, 139, 12, 70, 182, 80, 89, 189, 184, 52, 95, 185,
-			178, 184, 80, 102, 149, 101, 182, 188, 194, 22, 223, 177, 184, 188,
-			198, 86, 47, 207, 47, 45, 101, 7, 74, 217, 202, 179, 203, 139,
-			85, 232, 189, 62, 76, 118, 97, 145, 45, 85, 230, 47, 44, 45,
-			66, 83, 56, 206, 133, 74, 117, 241, 226, 26, 12, 40, 253, 117,
-			177, 178, 176, 184, 188, 54, 191, 84, 162, 108, 245, 234, 226, 197,
-			202, 252, 82, 137, 45, 190, 115, 241, 202, 213, 165, 249, 234, 115,
-			37, 89, 233, 234, 226, 219, 175, 45, 46, 175, 85, 230, 151, 216,
-			194, 252, 149, 249, 167, 23, 87, 217, 244, 189, 176, 114, 181, 186,
-			114, 241, 90, 117, 241, 10, 244, 122, 229, 18, 91, 189, 118, 97,
-			117, 173, 178, 118, 109, 109, 145, 61, 189, 178, 178, 128, 200, 94,
-			93, 172, 190, 163, 114, 113, 113, 245, 9, 182, 180, 178, 138, 8,
-			187, 182, 186, 88, 162, 108, 97, 126, 109, 30, 155, 190, 90, 93,
-			185, 84, 89, 91, 125, 2, 126, 95, 184, 182, 90, 65, 196, 85,
-			150, 215, 22, 171, 213, 107, 87, 215, 42, 43, 203, 51, 236, 242,
-			202, 179, 139, 239, 88, 172, 178, 139, 243, 215, 86, 23, 23, 16,
-			195, 43, 203, 48, 90, 88, 43, 139, 43, 213, 231, 160, 90, 192,
-			3, 206, 64, 137, 61, 123, 121, 113, 237, 242, 98, 21, 144, 138,
-			216, 154, 7, 52, 172, 174, 85, 43, 23, 215, 244, 108, 43, 85,
-			182, 182, 82, 93, 163, 218, 56, 217, 242, 226, 211, 75, 149, 167,
-			23, 151, 47, 46, 194, 231, 21, 168, 230, 217, 202, 234, 226, 12,
-			155, 175, 86, 86, 33, 67, 5, 27, 102, 207, 206, 63, 199, 86,
-			174, 225, 168, 97, 162, 174, 173, 46, 82, 241, 91, 91, 186, 37,
-			156, 79, 86, 185, 196, 230, 23, 222, 81, 129, 158, 203, 220, 87,
-			87, 86, 87, 43, 114, 185, 32, 218, 46, 94, 150, 56, 47, 83,
-			90, 160, 134, 105, 19, 214, 51, 1, 191, 10, 54, 153, 236, 121,
-			130, 246, 81, 179, 112, 76, 252, 20, 192, 35, 61, 135, 17, 120,
-			88, 252, 20, 192, 163, 61, 151, 17, 216, 47, 126, 10, 224, 177,
-			158, 18, 2, 13, 241, 83, 0, 143, 247, 148, 17, 40, 127, 10,
-			224, 84, 207, 36, 2, 169, 248, 41, 128, 211, 61, 15, 35, 240,
-			168, 248, 249, 29, 35, 212, 180, 122, 108, 171, 209, 19, 25, 197,
-			143, 140, 176, 121, 166, 78, 93, 164, 142, 60, 226, 126, 28, 49,
-			135, 69, 238, 134, 207, 235, 37, 214, 112, 111, 241, 250, 172, 199,
-			253, 141, 184, 201, 162, 182, 227, 3, 149, 137, 221, 22, 79, 179,
-			243, 58, 101, 14, 148, 169, 5, 29, 31, 105, 166, 60, 255, 145,
-			96, 54, 66, 167, 150, 30, 11, 234, 67, 204, 144, 23, 192, 36,
-			133, 99, 49, 240, 4, 229, 99, 149, 152, 185, 64, 189, 235, 188,
-			205, 253, 58, 23, 21, 58, 254, 54, 171, 57, 30, 247, 235, 78,
-			136, 181, 214, 2, 191, 198, 219, 49, 144, 233, 155, 156, 77, 214,
-			157, 237, 73, 10, 52, 109, 178, 21, 248, 113, 115, 82, 85, 19,
-			114, 207, 137, 5, 225, 91, 115, 91, 60, 138, 157, 86, 91, 16,
-			106, 121, 194, 213, 93, 56, 94, 185, 95, 227, 108, 157, 199, 91,
-			156, 251, 148, 197, 91, 122, 238, 77, 199, 235, 240, 8, 42, 115,
-			82, 84, 65, 23, 220, 152, 213, 28, 31, 104, 171, 83, 7, 82,
-			30, 132, 44, 234, 172, 199, 48, 92, 192, 8, 16, 81, 230, 164,
-			21, 149, 89, 21, 57, 6, 168, 168, 221, 14, 131, 91, 46, 28,
-			7, 222, 54, 59, 57, 123, 250, 84, 233, 212, 169, 83, 108, 155,
-			59, 97, 4, 228, 243, 8, 91, 188, 229, 180, 218, 30, 143, 40,
-			85, 63, 217, 233, 115, 236, 98, 208, 106, 119, 98, 158, 118, 3,
-			219, 200, 116, 23, 207, 189, 118, 196, 59, 245, 0, 15, 223, 178,
-			60, 164, 211, 241, 68, 177, 19, 198, 236, 60, 43, 151, 203, 79,
-			116, 127, 227, 126, 61, 243, 37, 105, 72, 113, 88, 234, 171, 248,
-			156, 48, 137, 106, 90, 207, 67, 13, 73, 106, 86, 180, 165, 210,
-			79, 116, 21, 194, 5, 32, 139, 136, 223, 170, 0, 166, 84, 35,
-			110, 131, 77, 239, 104, 232, 73, 118, 138, 29, 63, 222, 93, 215,
-			83, 236, 212, 12, 123, 69, 20, 219, 165, 119, 39, 207, 179, 211,
-			79, 236, 248, 42, 155, 62, 207, 78, 159, 82, 127, 50, 211, 109,
-			198, 61, 224, 175, 118, 235, 192, 83, 187, 118, 224, 201, 187, 119,
-			96, 246, 46, 29, 56, 185, 91, 7, 180, 233, 63, 147, 78, 127,
-			58, 95, 56, 255, 105, 242, 100, 58, 97, 15, 190, 10, 238, 56,
-			215, 119, 94, 35, 226, 147, 62, 229, 231, 179, 83, 206, 78, 238,
-			64, 194, 19, 105, 33, 181, 0, 180, 73, 215, 11, 236, 88, 5,
-			105, 153, 44, 158, 51, 107, 78, 71, 113, 90, 96, 87, 236, 166,
-			211, 155, 102, 124, 74, 207, 120, 135, 54, 78, 238, 222, 198, 174,
-			75, 72, 155, 193, 179, 119, 218, 192, 117, 39, 230, 64, 81, 203,
-			240, 127, 117, 238, 161, 136, 193, 174, 110, 199, 77, 193, 77, 193,
-			95, 12, 72, 223, 153, 113, 186, 238, 108, 71, 231, 207, 150, 88,
-			203, 245, 59, 49, 143, 206, 159, 62, 53, 147, 221, 102, 236, 124,
-			210, 218, 116, 215, 167, 242, 165, 48, 104, 173, 37, 85, 197, 245,
-			25, 164, 61, 207, 172, 174, 44, 179, 43, 78, 187, 237, 250, 27,
-			148, 178, 138, 47, 32, 66, 210, 41, 33, 213, 76, 250, 15, 82,
-			24, 80, 52, 238, 195, 50, 171, 139, 99, 0, 248, 88, 127, 131,
-			133, 142, 100, 93, 29, 160, 151, 148, 5, 235, 239, 230, 181, 184,
-			196, 182, 154, 60, 20, 12, 184, 204, 200, 1, 169, 146, 123, 142,
-			58, 141, 134, 123, 139, 77, 70, 147, 108, 218, 245, 235, 40, 169,
-			248, 27, 234, 220, 152, 1, 194, 75, 161, 193, 118, 200, 107, 28,
-			90, 92, 223, 22, 12, 112, 167, 181, 206, 67, 237, 136, 145, 178,
-			79, 122, 202, 68, 140, 223, 130, 3, 43, 194, 110, 210, 228, 92,
-			114, 60, 85, 164, 204, 46, 5, 33, 227, 98, 186, 74, 236, 108,
-			114, 90, 97, 77, 167, 50, 117, 69, 205, 160, 227, 213, 217, 58,
-			167, 201, 216, 221, 12, 162, 0, 21, 147, 103, 163, 73, 24, 175,
-			11, 179, 159, 57, 20, 79, 107, 149, 201, 186, 40, 156, 36, 105,
-			23, 119, 171, 173, 172, 86, 215, 105, 168, 23, 234, 233, 170, 149,
-			178, 150, 91, 11, 179, 245, 222, 111, 181, 167, 163, 201, 50, 197,
-			63, 98, 245, 24, 54, 105, 20, 70, 232, 239, 24, 212, 178, 122,
-			204, 30, 155, 188, 219, 28, 43, 126, 209, 96, 171, 200, 21, 36,
-			141, 2, 43, 0, 147, 166, 177, 5, 101, 118, 5, 36, 173, 117,
-			46, 214, 246, 236, 217, 211, 143, 150, 30, 125, 211, 99, 112, 192,
-			193, 127, 20, 142, 226, 147, 93, 64, 230, 250, 53, 175, 19, 185,
-			155, 188, 204, 150, 131, 152, 159, 131, 90, 35, 206, 214, 131, 14,
-			14, 45, 4, 105, 17, 119, 142, 144, 77, 206, 81, 246, 216, 41,
-			232, 196, 92, 203, 245, 217, 9, 72, 180, 92, 127, 174, 25, 178,
-			19, 236, 204, 35, 172, 25, 206, 213, 157, 109, 118, 130, 157, 125,
-			236, 209, 242, 153, 71, 25, 236, 145, 57, 56, 92, 217, 9, 177,
-			67, 197, 73, 75, 233, 0, 205, 193, 232, 114, 48, 188, 94, 149,
-			50, 108, 242, 238, 194, 176, 74, 17, 155, 188, 219, 222, 67, 95,
-			37, 136, 8, 195, 38, 161, 105, 23, 255, 139, 169, 16, 145, 97,
-			110, 28, 137, 151, 44, 119, 163, 49, 55, 58, 190, 104, 138, 48,
-			181, 155, 34, 230, 241, 40, 18, 27, 38, 240, 121, 82, 91, 152,
-			225, 181, 196, 106, 116, 216, 41, 202, 110, 200, 121, 184, 193, 26,
-			46, 247, 234, 184, 6, 28, 214, 14, 34, 55, 118, 55, 81, 196,
-			243, 249, 134, 131, 191, 111, 96, 135, 100, 70, 177, 208, 21, 25,
-			136, 176, 43, 90, 131, 65, 200, 90, 65, 200, 75, 204, 97, 126,
-			224, 207, 190, 204, 195, 64, 112, 65, 176, 106, 112, 0, 153, 218,
-			132, 104, 13, 59, 65, 13, 15, 4, 85, 224, 31, 97, 121, 97,
-			246, 108, 63, 187, 151, 200, 227, 143, 63, 94, 146, 255, 137, 229,
-			161, 1, 180, 165, 161, 230, 203, 200, 193, 44, 168, 249, 50, 96,
-			78, 10, 131, 42, 69, 108, 18, 142, 140, 174, 231, 81, 127, 114,
-			150, 254, 252, 105, 122, 184, 91, 181, 21, 39, 28, 217, 29, 116,
-			91, 79, 208, 190, 228, 184, 123, 96, 229, 214, 7, 238, 160, 220,
-			26, 74, 170, 84, 218, 173, 51, 247, 169, 221, 74, 250, 251, 64,
-			234, 173, 159, 155, 163, 189, 118, 238, 80, 207, 183, 26, 111, 232,
-			183, 222, 208, 111, 189, 161, 223, 122, 67, 191, 245, 134, 126, 235,
-			13, 253, 214, 127, 117, 253, 86, 37, 213, 111, 85, 238, 174, 223,
-			154, 75, 245, 91, 115, 15, 160, 223, 250, 189, 131, 168, 223, 202,
-			191, 102, 192, 209, 87, 252, 149, 131, 108, 94, 19, 94, 51, 42,
-			174, 118, 224, 250, 49, 146, 53, 183, 197, 119, 211, 56, 33, 252,
-			101, 224, 140, 130, 144, 121, 65, 205, 241, 104, 162, 133, 42, 101,
-			101, 158, 7, 81, 125, 209, 221, 185, 195, 50, 91, 107, 114, 89,
-			145, 82, 93, 1, 235, 22, 7, 204, 241, 25, 111, 7, 181, 38,
-			112, 150, 215, 214, 46, 178, 150, 91, 247, 145, 162, 7, 62, 101,
-			207, 56, 126, 7, 142, 129, 211, 37, 118, 250, 241, 55, 157, 42,
-			41, 66, 221, 14, 3, 143, 183, 99, 183, 198, 158, 14, 249, 70,
-			16, 186, 142, 159, 234, 208, 182, 154, 110, 173, 201, 248, 173, 24,
-			133, 47, 36, 208, 187, 228, 90, 119, 106, 55, 183, 156, 16, 114,
-			4, 200, 52, 3, 155, 8, 4, 16, 142, 124, 41, 114, 226, 33,
-			43, 216, 113, 28, 159, 23, 248, 27, 101, 182, 196, 157, 118, 58,
-			228, 144, 179, 201, 168, 197, 157, 144, 215, 39, 89, 20, 136, 3,
-			216, 15, 152, 199, 157, 54, 85, 108, 103, 236, 172, 123, 40, 76,
-			250, 28, 37, 59, 96, 54, 145, 21, 105, 195, 217, 42, 14, 244,
-			78, 4, 167, 146, 195, 94, 56, 243, 200, 108, 51, 232, 132, 204,
-			115, 125, 238, 132, 148, 97, 237, 47, 78, 223, 157, 233, 128, 249,
-			156, 195, 156, 51, 72, 197, 155, 156, 133, 74, 39, 135, 172, 40,
-			136, 65, 179, 248, 191, 181, 83, 167, 206, 225, 255, 158, 135, 161,
-			63, 254, 248, 227, 143, 207, 158, 62, 51, 123, 246, 244, 218, 153,
-			179, 231, 30, 125, 252, 220, 163, 143, 151, 31, 87, 127, 207, 151,
-			217, 133, 109, 212, 97, 198, 161, 91, 67, 113, 53, 150, 67, 196,
-			218, 75, 108, 139, 51, 238, 71, 29, 148, 122, 157, 24, 146, 53,
-			192, 114, 224, 111, 242, 48, 22, 243, 43, 14, 37, 246, 66, 245,
-			210, 69, 202, 206, 158, 61, 251, 120, 58, 150, 173, 173, 173, 178,
-			203, 227, 6, 114, 136, 97, 163, 6, 255, 65, 142, 114, 124, 43,
-			158, 65, 157, 128, 20, 164, 239, 75, 119, 216, 165, 60, 186, 186,
-			178, 90, 121, 39, 187, 1, 152, 153, 158, 185, 177, 83, 79, 148,
-			48, 159, 82, 161, 145, 50, 207, 17, 143, 175, 203, 9, 158, 198,
-			226, 203, 215, 150, 150, 102, 102, 118, 205, 135, 235, 125, 250, 212,
-			204, 19, 247, 165, 208, 146, 125, 218, 224, 49, 212, 18, 52, 234,
-			206, 182, 214, 183, 40, 14, 59, 181, 24, 27, 216, 116, 60, 22,
-			111, 202, 22, 51, 217, 143, 199, 155, 37, 134, 29, 122, 226, 245,
-			14, 105, 179, 28, 111, 66, 234, 110, 35, 18, 153, 58, 17, 175,
-			73, 209, 50, 51, 194, 179, 119, 28, 225, 179, 174, 127, 246, 12,
-			187, 241, 52, 143, 87, 183, 163, 152, 163, 18, 102, 62, 186, 228,
-			122, 124, 45, 59, 17, 151, 42, 75, 139, 107, 149, 43, 139, 172,
-			17, 203, 110, 220, 169, 204, 241, 70, 172, 122, 122, 173, 178, 188,
-			246, 216, 35, 44, 118, 107, 55, 35, 118, 158, 77, 79, 79, 11,
-			200, 76, 35, 46, 215, 183, 46, 187, 27, 205, 5, 39, 198, 82,
-			51, 236, 201, 39, 217, 217, 51, 51, 236, 61, 12, 191, 45, 5,
-			91, 234, 147, 194, 219, 220, 28, 155, 135, 254, 214, 131, 173, 8,
-			171, 132, 205, 114, 250, 84, 70, 27, 82, 78, 50, 8, 42, 117,
-			250, 177, 157, 219, 40, 169, 13, 138, 159, 126, 236, 145, 71, 30,
-			121, 211, 217, 199, 78, 165, 100, 99, 157, 55, 130, 144, 179, 107,
-			190, 123, 75, 213, 242, 248, 155, 78, 117, 215, 82, 126, 125, 147,
-			57, 45, 198, 207, 166, 167, 5, 82, 230, 18, 77, 221, 12, 155,
-			213, 187, 115, 143, 21, 12, 245, 0, 186, 84, 61, 199, 180, 122,
-			112, 1, 204, 100, 22, 192, 35, 119, 92, 0, 207, 56, 155, 14,
-			187, 33, 38, 178, 92, 235, 132, 33, 247, 99, 200, 114, 197, 245,
-			60, 55, 210, 22, 0, 80, 83, 214, 66, 40, 59, 207, 238, 92,
-			224, 46, 203, 156, 157, 215, 46, 33, 124, 190, 117, 161, 227, 122,
-			117, 30, 78, 207, 192, 192, 86, 37, 134, 100, 19, 2, 49, 51,
-			74, 185, 201, 24, 228, 89, 22, 99, 119, 253, 24, 70, 46, 115,
-			138, 161, 207, 40, 149, 10, 12, 189, 188, 14, 53, 99, 95, 82,
-			28, 60, 122, 15, 28, 84, 252, 40, 118, 252, 184, 236, 7, 91,
-			218, 176, 37, 148, 249, 193, 22, 59, 207, 50, 121, 238, 58, 210,
-			180, 227, 247, 30, 178, 31, 108, 149, 55, 120, 188, 8, 139, 77,
-			192, 166, 103, 180, 145, 103, 71, 47, 51, 67, 98, 250, 14, 35,
-			125, 236, 142, 35, 149, 243, 165, 248, 140, 110, 213, 238, 110, 19,
-			165, 116, 181, 233, 42, 124, 154, 199, 23, 211, 121, 159, 190, 111,
-			93, 173, 134, 167, 187, 40, 107, 5, 207, 64, 241, 0, 122, 160,
-			243, 71, 52, 5, 188, 139, 3, 108, 75, 73, 84, 35, 213, 139,
-			110, 196, 38, 95, 1, 190, 225, 246, 236, 43, 120, 49, 119, 123,
-			246, 149, 186, 179, 125, 123, 237, 21, 56, 188, 111, 159, 123, 165,
-			229, 250, 183, 207, 189, 18, 241, 218, 237, 23, 202, 175, 0, 187,
-			4, 91, 246, 246, 139, 207, 79, 82, 169, 38, 22, 165, 241, 210,
-			204, 219, 114, 182, 117, 37, 174, 224, 5, 26, 192, 5, 212, 221,
-			13, 55, 142, 164, 166, 85, 182, 84, 98, 216, 84, 137, 50, 209,
-			88, 137, 97, 107, 66, 111, 138, 77, 34, 95, 242, 50, 15, 131,
-			217, 182, 184, 193, 131, 99, 123, 43, 80, 181, 113, 167, 214, 20,
-			60, 89, 170, 42, 166, 154, 122, 25, 57, 40, 56, 200, 55, 2,
-			214, 105, 35, 155, 160, 138, 78, 187, 101, 94, 150, 192, 211, 187,
-			115, 123, 51, 37, 138, 237, 7, 109, 81, 179, 104, 105, 242, 249,
-			73, 165, 2, 151, 218, 111, 46, 84, 104, 176, 14, 144, 19, 157,
-			158, 188, 182, 118, 113, 114, 230, 137, 12, 148, 10, 134, 241, 165,
-			142, 27, 242, 122, 153, 205, 51, 161, 254, 18, 139, 33, 66, 153,
-			220, 125, 153, 135, 74, 35, 44, 81, 217, 137, 56, 114, 147, 211,
-			78, 148, 180, 86, 103, 235, 219, 20, 186, 49, 3, 19, 224, 131,
-			20, 236, 11, 150, 102, 231, 82, 146, 234, 70, 173, 169, 182, 19,
-			70, 105, 51, 235, 156, 50, 228, 233, 128, 195, 169, 213, 120, 59,
-			102, 235, 65, 220, 196, 54, 161, 172, 80, 26, 168, 49, 68, 59,
-			250, 193, 80, 171, 220, 136, 120, 140, 236, 90, 70, 57, 63, 121,
-			230, 212, 233, 55, 193, 233, 112, 250, 209, 181, 83, 167, 207, 157,
-			61, 117, 238, 244, 163, 229, 83, 167, 159, 159, 148, 171, 59, 98,
-			152, 78, 142, 151, 182, 19, 197, 148, 97, 78, 108, 63, 240, 83,
-			190, 249, 209, 18, 131, 218, 202, 114, 3, 57, 155, 206, 106, 45,
-			116, 219, 113, 9, 149, 162, 58, 171, 230, 48, 56, 30, 229, 77,
-			134, 224, 242, 128, 117, 20, 139, 93, 172, 71, 92, 254, 64, 174,
-			234, 78, 88, 167, 236, 133, 56, 168, 172, 174, 172, 226, 38, 155,
-			158, 217, 133, 65, 45, 183, 130, 151, 93, 207, 115, 112, 119, 113,
-			127, 246, 218, 234, 92, 61, 168, 69, 115, 207, 242, 245, 185, 180,
-			43, 115, 85, 46, 175, 169, 231, 158, 246, 130, 117, 199, 187, 190,
-			130, 125, 136, 230, 160, 67, 115, 90, 35, 51, 168, 187, 106, 6,
-			245, 50, 12, 70, 80, 154, 18, 238, 115, 209, 37, 118, 35, 185,
-			69, 82, 63, 110, 168, 1, 201, 235, 108, 57, 90, 94, 167, 187,
-			14, 145, 178, 23, 110, 68, 113, 216, 192, 162, 218, 136, 130, 90,
-			84, 110, 11, 202, 6, 99, 57, 51, 231, 185, 235, 161, 19, 110,
-			35, 219, 93, 110, 198, 45, 239, 8, 254, 82, 101, 103, 80, 231,
-			66, 147, 133, 172, 26, 137, 218, 188, 198, 166, 142, 61, 55, 123,
-			172, 53, 123, 172, 190, 118, 236, 242, 185, 99, 87, 206, 29, 91,
-			45, 31, 107, 60, 63, 85, 102, 75, 238, 77, 190, 229, 70, 28,
-			197, 28, 64, 80, 58, 75, 157, 136, 139, 218, 158, 9, 234, 226,
-			226, 125, 42, 98, 47, 220, 168, 172, 174, 40, 166, 230, 146, 32,
-			86, 117, 153, 156, 158, 185, 241, 226, 180, 208, 84, 74, 58, 247,
-			238, 160, 46, 102, 2, 126, 204, 162, 188, 224, 180, 93, 156, 16,
-			5, 21, 82, 132, 232, 235, 220, 206, 186, 113, 156, 170, 129, 99,
-			103, 22, 142, 157, 89, 160, 108, 6, 16, 25, 172, 163, 134, 208,
-			145, 227, 140, 121, 200, 106, 78, 27, 55, 72, 208, 96, 27, 220,
-			231, 161, 184, 236, 138, 51, 151, 249, 26, 254, 241, 126, 166, 95,
-			220, 207, 88, 175, 25, 133, 81, 250, 237, 234, 130, 198, 250, 102,
-			195, 28, 43, 254, 51, 131, 85, 83, 9, 87, 187, 165, 129, 37,
-			143, 56, 142, 92, 191, 166, 115, 89, 116, 119, 54, 43, 171, 161,
-			191, 131, 88, 68, 119, 147, 139, 158, 207, 104, 236, 7, 213, 13,
-			11, 244, 175, 87, 37, 13, 72, 22, 134, 85, 146, 64, 210, 222,
-			67, 255, 216, 144, 151, 44, 214, 71, 12, 211, 46, 254, 134, 193,
-			150, 3, 127, 54, 185, 194, 120, 176, 187, 150, 50, 91, 150, 5,
-			19, 1, 83, 90, 114, 160, 74, 50, 173, 12, 21, 167, 81, 236,
-			122, 30, 107, 58, 155, 28, 175, 60, 146, 54, 197, 205, 174, 40,
-			72, 133, 244, 38, 4, 244, 70, 16, 130, 96, 172, 180, 7, 221,
-			8, 147, 66, 99, 122, 173, 177, 19, 41, 70, 14, 199, 169, 144,
-			98, 224, 176, 11, 131, 42, 73, 32, 169, 221, 100, 252, 148, 77,
-			15, 116, 223, 100, 240, 86, 59, 222, 190, 211, 45, 70, 47, 205,
-			45, 194, 247, 11, 183, 119, 191, 144, 160, 248, 85, 93, 70, 148,
-			239, 243, 50, 2, 155, 124, 160, 139, 136, 191, 29, 17, 118, 182,
-			103, 71, 222, 184, 135, 120, 227, 30, 226, 141, 123, 136, 55, 238,
-			33, 222, 184, 135, 120, 227, 30, 226, 255, 195, 123, 136, 69, 117,
-			229, 0, 63, 213, 61, 68, 114, 229, 112, 52, 185, 114, 56, 214,
-			115, 82, 93, 57, 192, 79, 117, 15, 145, 92, 57, 28, 79, 174,
-			28, 166, 210, 43, 7, 248, 169, 238, 33, 146, 11, 15, 248, 249,
-			55, 38, 222, 67, 144, 179, 61, 35, 197, 191, 48, 217, 188, 96,
-			240, 220, 26, 195, 19, 148, 181, 120, 20, 57, 27, 82, 33, 188,
-			29, 116, 144, 129, 13, 249, 44, 28, 52, 32, 46, 109, 6, 110,
-			157, 213, 121, 195, 245, 145, 252, 117, 218, 158, 16, 139, 104, 182,
-			60, 146, 223, 109, 16, 129, 231, 175, 86, 34, 144, 252, 226, 237,
-			182, 91, 115, 60, 37, 41, 129, 96, 24, 7, 226, 252, 138, 149,
-			61, 6, 72, 138, 28, 228, 33, 73, 213, 66, 30, 181, 3, 31,
-			90, 6, 177, 14, 47, 63, 160, 190, 68, 144, 184, 132, 154, 120,
-			144, 32, 106, 92, 157, 70, 112, 190, 186, 53, 206, 46, 5, 65,
-			106, 37, 23, 182, 107, 236, 130, 19, 78, 119, 241, 26, 101, 100,
-			53, 102, 224, 108, 234, 132, 126, 196, 238, 240, 93, 179, 153, 3,
-			89, 24, 37, 202, 228, 194, 70, 218, 203, 5, 33, 187, 129, 185,
-			111, 160, 38, 3, 113, 129, 25, 165, 8, 115, 227, 149, 219, 55,
-			202, 169, 17, 211, 217, 194, 96, 194, 65, 253, 172, 77, 207, 108,
-			4, 229, 90, 51, 12, 90, 110, 167, 133, 60, 142, 215, 169, 185,
-			115, 245, 22, 48, 249, 115, 114, 68, 115, 155, 167, 5, 199, 35,
-			25, 43, 179, 222, 42, 222, 203, 134, 164, 120, 55, 214, 108, 242,
-			45, 212, 190, 210, 241, 98, 247, 106, 8, 236, 71, 188, 253, 14,
-			96, 39, 237, 25, 154, 23, 124, 229, 132, 193, 200, 116, 255, 153,
-			209, 114, 189, 85, 206, 100, 169, 202, 12, 147, 95, 52, 232, 96,
-			182, 176, 77, 73, 20, 135, 104, 145, 210, 119, 185, 167, 10, 9,
-			128, 213, 157, 24, 173, 81, 6, 0, 86, 119, 98, 128, 249, 157,
-			214, 4, 97, 198, 52, 1, 152, 223, 105, 1, 108, 221, 245, 39,
-			114, 204, 152, 46, 0, 108, 221, 245, 237, 83, 212, 130, 33, 77,
-			228, 153, 49, 221, 127, 166, 216, 205, 44, 150, 19, 201, 255, 114,
-			79, 21, 115, 218, 37, 106, 249, 29, 207, 155, 232, 197, 18, 227,
-			59, 74, 224, 36, 65, 110, 200, 117, 161, 151, 230, 112, 44, 207,
-			88, 5, 107, 36, 55, 249, 73, 131, 246, 207, 199, 49, 32, 105,
-			201, 141, 98, 123, 138, 154, 113, 48, 97, 34, 30, 246, 1, 30,
-			180, 143, 229, 181, 96, 209, 143, 195, 237, 170, 25, 7, 197, 67,
-			212, 90, 238, 180, 34, 123, 28, 90, 111, 9, 212, 13, 94, 48,
-			71, 140, 42, 166, 139, 111, 163, 189, 50, 187, 61, 66, 201, 77,
-			190, 45, 80, 84, 133, 159, 246, 9, 217, 9, 68, 81, 255, 153,
-			177, 238, 134, 160, 230, 170, 200, 114, 206, 124, 179, 113, 225, 228,
-			243, 51, 247, 183, 94, 158, 168, 183, 158, 249, 221, 65, 96, 115,
-			173, 158, 71, 13, 250, 163, 6, 178, 185, 86, 143, 125, 230, 211,
-			70, 134, 99, 61, 253, 24, 174, 236, 165, 107, 23, 43, 108, 190,
-			19, 55, 131, 16, 246, 236, 174, 108, 235, 181, 136, 11, 123, 42,
-			100, 14, 82, 38, 207, 141, 216, 70, 176, 201, 67, 159, 215, 89,
-			199, 175, 75, 158, 101, 190, 237, 212, 160, 98, 183, 198, 125, 144,
-			141, 223, 193, 67, 224, 17, 216, 153, 242, 41, 37, 182, 8, 217,
-			190, 17, 116, 252, 186, 98, 161, 150, 42, 23, 23, 151, 87, 23,
-			89, 195, 245, 184, 160, 167, 5, 155, 228, 123, 222, 170, 8, 166,
-			252, 73, 122, 108, 82, 232, 153, 193, 159, 134, 77, 250, 122, 142,
-			73, 210, 219, 223, 211, 79, 169, 120, 78, 48, 216, 51, 108, 36,
-			187, 110, 176, 80, 164, 253, 202, 114, 112, 200, 60, 170, 140, 233,
-			44, 72, 37, 102, 119, 121, 155, 12, 245, 79, 104, 102, 119, 67,
-			251, 15, 107, 102, 119, 67, 147, 71, 176, 114, 195, 182, 70, 123,
-			142, 138, 202, 13, 195, 38, 163, 133, 189, 244, 91, 77, 72, 244,
-			217, 100, 220, 28, 44, 126, 192, 84, 120, 99, 143, 32, 129, 104,
-			120, 129, 19, 71, 101, 182, 6, 184, 115, 35, 22, 72, 190, 123,
-			157, 215, 28, 32, 132, 252, 165, 142, 227, 185, 241, 246, 108, 45,
-			104, 181, 157, 208, 141, 2, 95, 170, 34, 68, 73, 188, 131, 12,
-			226, 32, 116, 131, 78, 228, 109, 227, 27, 1, 183, 214, 241, 98,
-			84, 169, 0, 226, 92, 223, 141, 93, 199, 99, 46, 144, 216, 148,
-			9, 13, 26, 108, 225, 74, 137, 178, 182, 179, 237, 5, 142, 188,
-			4, 14, 121, 212, 241, 98, 37, 118, 138, 6, 182, 64, 218, 92,
-			7, 194, 11, 68, 139, 215, 203, 236, 114, 208, 230, 141, 142, 231,
-			161, 53, 235, 246, 84, 8, 114, 40, 112, 236, 120, 21, 42, 116,
-			150, 91, 192, 243, 250, 83, 49, 2, 129, 168, 71, 157, 118, 59,
-			8, 81, 130, 104, 149, 41, 98, 220, 232, 235, 177, 201, 120, 255,
-			0, 226, 209, 232, 3, 172, 106, 41, 83, 165, 44, 203, 40, 244,
-			216, 214, 132, 121, 132, 136, 111, 5, 200, 57, 81, 24, 20, 149,
-			192, 180, 237, 183, 246, 136, 79, 104, 31, 185, 223, 162, 42, 101,
-			216, 100, 127, 255, 144, 74, 17, 155, 236, 31, 181, 101, 49, 195,
-			38, 197, 164, 152, 145, 131, 84, 159, 74, 193, 183, 164, 152, 65,
-			108, 82, 76, 138, 153, 54, 57, 144, 20, 51, 115, 144, 82, 197,
-			160, 202, 3, 73, 49, 147, 216, 228, 64, 82, 140, 216, 228, 161,
-			164, 24, 201, 65, 170, 160, 82, 134, 77, 30, 74, 138, 17, 200,
-			57, 106, 211, 111, 53, 176, 156, 101, 19, 102, 77, 21, 223, 111,
-			160, 138, 72, 41, 43, 3, 223, 75, 249, 119, 37, 45, 8, 211,
-			244, 57, 238, 215, 89, 134, 254, 194, 177, 75, 217, 211, 161, 211,
-			110, 190, 189, 195, 195, 237, 85, 238, 132, 181, 102, 153, 85, 26,
-			138, 111, 23, 166, 182, 14, 108, 173, 24, 37, 146, 118, 9, 14,
-			96, 53, 241, 238, 134, 31, 132, 176, 207, 101, 23, 173, 60, 116,
-			234, 160, 74, 25, 54, 97, 135, 38, 85, 138, 216, 132, 29, 59,
-			46, 71, 157, 179, 201, 164, 117, 68, 126, 202, 229, 33, 181, 95,
-			165, 12, 155, 76, 22, 15, 169, 20, 177, 201, 228, 195, 147, 244,
-			71, 12, 106, 90, 166, 109, 205, 244, 60, 106, 20, 255, 181, 193,
-			52, 138, 7, 11, 221, 11, 54, 128, 95, 240, 182, 153, 131, 162,
-			24, 176, 27, 65, 131, 117, 124, 247, 165, 14, 103, 142, 200, 156,
-			168, 187, 155, 210, 216, 161, 213, 118, 106, 49, 237, 62, 157, 37,
-			89, 169, 5, 173, 86, 224, 179, 168, 198, 125, 39, 116, 3, 168,
-			78, 213, 220, 130, 115, 16, 216, 18, 85, 177, 180, 25, 165, 194,
-			104, 20, 217, 146, 233, 104, 70, 158, 224, 48, 251, 51, 133, 61,
-			184, 96, 129, 10, 89, 39, 204, 146, 88, 176, 38, 129, 117, 120,
-			130, 14, 209, 65, 154, 135, 20, 44, 217, 147, 214, 73, 58, 68,
-			123, 69, 210, 130, 244, 64, 154, 206, 217, 228, 228, 224, 158, 52,
-			109, 216, 228, 228, 216, 68, 154, 38, 54, 57, 121, 224, 161, 52,
-			93, 176, 201, 201, 131, 39, 232, 48, 45, 200, 180, 105, 147, 147,
-			135, 102, 232, 47, 194, 34, 50, 161, 185, 71, 204, 3, 197, 255,
-			209, 96, 107, 129, 120, 27, 212, 114, 218, 48, 24, 28, 66, 52,
-			27, 7, 179, 201, 16, 227, 128, 9, 211, 18, 22, 248, 101, 182,
-			26, 48, 183, 129, 44, 223, 150, 227, 199, 233, 71, 202, 2, 41,
-			182, 139, 114, 108, 178, 17, 4, 239, 57, 61, 89, 18, 63, 206,
-			76, 34, 17, 152, 92, 119, 66, 4, 226, 193, 176, 133, 75, 215,
-			11, 130, 155, 248, 14, 234, 28, 48, 80, 146, 25, 131, 66, 147,
-			231, 216, 11, 167, 75, 236, 204, 139, 37, 9, 91, 119, 66, 132,
-			9, 192, 109, 177, 250, 76, 36, 197, 143, 152, 123, 84, 202, 176,
-			201, 35, 99, 227, 42, 69, 108, 242, 200, 254, 98, 194, 69, 125,
-			215, 191, 53, 232, 155, 238, 147, 141, 218, 128, 13, 114, 189, 238,
-			196, 142, 198, 75, 221, 227, 169, 249, 189, 121, 173, 215, 193, 196,
-			77, 254, 71, 131, 14, 205, 175, 251, 65, 216, 114, 188, 75, 174,
-			239, 70, 77, 251, 52, 205, 71, 177, 19, 119, 132, 93, 239, 208,
-			153, 253, 200, 14, 100, 242, 148, 87, 49, 67, 85, 102, 180, 199,
-			105, 62, 228, 78, 20, 248, 200, 65, 244, 85, 101, 106, 242, 67,
-			6, 205, 139, 172, 118, 63, 237, 173, 44, 191, 99, 126, 169, 178,
-			48, 210, 99, 83, 154, 191, 52, 95, 89, 90, 92, 24, 49, 224,
-			195, 197, 234, 252, 234, 229, 197, 133, 17, 19, 18, 139, 239, 188,
-			90, 169, 46, 46, 140, 16, 123, 144, 246, 173, 129, 104, 123, 125,
-			229, 218, 218, 136, 5, 201, 139, 243, 203, 23, 23, 151, 160, 92,
-			206, 30, 160, 133, 234, 226, 51, 139, 23, 215, 22, 23, 70, 242,
-			80, 240, 74, 101, 21, 196, 171, 145, 94, 123, 140, 142, 84, 23,
-			87, 175, 45, 173, 93, 191, 50, 191, 116, 105, 165, 122, 101, 113,
-			97, 164, 48, 249, 167, 5, 154, 123, 59, 44, 66, 251, 33, 106,
-			186, 117, 28, 93, 255, 153, 1, 24, 29, 130, 203, 149, 133, 170,
-			233, 214, 129, 63, 90, 88, 94, 196, 145, 20, 170, 240, 211, 158,
-			164, 22, 204, 21, 114, 139, 253, 103, 134, 210, 18, 11, 78, 236,
-			84, 241, 155, 125, 150, 22, 212, 186, 158, 176, 82, 126, 77, 228,
-			147, 164, 37, 18, 252, 90, 146, 209, 158, 160, 189, 109, 39, 132,
-			19, 115, 98, 4, 155, 83, 201, 226, 24, 53, 43, 11, 246, 80,
-			210, 209, 62, 232, 90, 241, 119, 45, 106, 45, 240, 168, 102, 63,
-			70, 247, 37, 234, 154, 32, 188, 94, 11, 252, 134, 187, 113, 221,
-			119, 90, 92, 230, 222, 171, 125, 190, 136, 95, 151, 157, 22, 183,
-			15, 81, 218, 118, 66, 167, 197, 99, 30, 70, 114, 178, 52, 136,
-			253, 40, 29, 215, 235, 213, 242, 146, 29, 213, 94, 77, 139, 77,
-			81, 171, 197, 99, 103, 194, 66, 4, 237, 209, 16, 196, 163, 90,
-			249, 10, 7, 44, 65, 134, 226, 39, 8, 181, 32, 105, 31, 164,
-			212, 137, 174, 59, 53, 84, 26, 203, 62, 247, 57, 209, 188, 0,
-			216, 115, 52, 23, 242, 56, 220, 150, 28, 233, 254, 93, 106, 44,
-			87, 33, 67, 85, 228, 179, 223, 76, 11, 104, 228, 210, 137, 35,
-			57, 77, 15, 237, 86, 102, 77, 230, 169, 38, 185, 139, 109, 154,
-			195, 154, 96, 17, 55, 28, 215, 227, 2, 225, 131, 85, 153, 130,
-			73, 170, 133, 78, 212, 228, 117, 236, 205, 96, 85, 37, 225, 11,
-			191, 213, 118, 67, 94, 199, 54, 7, 171, 42, 105, 31, 160, 125,
-			248, 20, 233, 122, 208, 137, 17, 43, 131, 162, 197, 250, 74, 39,
-			46, 254, 11, 131, 22, 84, 71, 96, 164, 120, 150, 202, 229, 184,
-			127, 135, 188, 160, 30, 65, 84, 69, 62, 251, 36, 37, 97, 199,
-			79, 16, 115, 199, 236, 144, 203, 158, 165, 86, 20, 7, 109, 137,
-			146, 187, 228, 198, 108, 197, 38, 29, 88, 227, 173, 182, 231, 196,
-			124, 181, 205, 107, 184, 62, 195, 0, 88, 49, 57, 69, 42, 9,
-			155, 36, 228, 13, 185, 130, 224, 39, 228, 221, 20, 204, 181, 92,
-			43, 42, 105, 219, 212, 194, 149, 105, 33, 24, 127, 23, 63, 106,
-			80, 11, 118, 143, 253, 8, 96, 151, 131, 4, 47, 49, 112, 23,
-			25, 171, 170, 178, 226, 142, 228, 81, 77, 98, 97, 40, 59, 213,
-			85, 252, 102, 159, 166, 133, 245, 142, 235, 197, 215, 215, 183, 39,
-			8, 238, 200, 241, 52, 159, 62, 204, 106, 47, 230, 187, 176, 93,
-			188, 76, 7, 51, 91, 85, 151, 149, 6, 133, 172, 244, 112, 86,
-			86, 234, 215, 100, 37, 77, 68, 154, 140, 41, 125, 38, 10, 252,
-			42, 242, 184, 176, 180, 132, 24, 46, 209, 40, 83, 128, 153, 200,
-			125, 153, 203, 117, 133, 191, 237, 115, 148, 226, 42, 194, 121, 145,
-			19, 119, 55, 156, 104, 185, 39, 93, 154, 151, 45, 42, 146, 101,
-			164, 8, 74, 251, 35, 73, 214, 19, 116, 216, 145, 100, 253, 122,
-			3, 233, 186, 28, 148, 189, 147, 226, 87, 135, 156, 76, 122, 242,
-			207, 41, 237, 149, 227, 182, 15, 105, 244, 116, 72, 67, 200, 157,
-			41, 234, 209, 12, 69, 29, 209, 203, 104, 52, 245, 9, 64, 5,
-			175, 9, 125, 186, 164, 170, 7, 244, 188, 139, 201, 87, 65, 89,
-			181, 236, 246, 9, 90, 104, 108, 213, 175, 215, 121, 59, 66, 145,
-			190, 255, 204, 112, 151, 92, 91, 237, 109, 108, 213, 23, 120, 59,
-			178, 75, 180, 111, 221, 169, 221, 20, 153, 243, 187, 103, 46, 64,
-			14, 204, 61, 155, 165, 218, 146, 224, 169, 62, 93, 21, 159, 82,
-			82, 126, 2, 73, 249, 24, 205, 33, 7, 36, 87, 128, 72, 72,
-			2, 47, 166, 31, 8, 252, 127, 177, 190, 166, 109, 241, 24, 45,
-			136, 251, 21, 73, 171, 238, 94, 44, 201, 107, 31, 163, 67, 126,
-			167, 117, 93, 67, 182, 160, 103, 131, 126, 167, 149, 226, 216, 62,
-			79, 105, 84, 107, 242, 122, 199, 115, 253, 13, 137, 212, 3, 221,
-			115, 87, 94, 77, 178, 92, 238, 169, 106, 5, 236, 115, 180, 79,
-			182, 224, 111, 36, 10, 149, 238, 210, 139, 42, 199, 229, 158, 106,
-			154, 29, 240, 177, 229, 184, 88, 82, 40, 86, 38, 118, 148, 124,
-			86, 124, 191, 220, 83, 85, 89, 237, 55, 209, 130, 88, 216, 188,
-			62, 81, 72, 79, 146, 76, 177, 75, 50, 195, 229, 158, 106, 146,
-			217, 62, 191, 115, 107, 244, 221, 105, 107, 92, 238, 233, 222, 28,
-			197, 1, 74, 83, 44, 20, 31, 165, 125, 201, 168, 236, 105, 58,
-			82, 235, 132, 41, 170, 175, 187, 234, 188, 25, 170, 117, 194, 4,
-			217, 149, 122, 241, 4, 237, 149, 67, 178, 15, 211, 126, 152, 31,
-			133, 1, 145, 159, 250, 157, 150, 204, 80, 44, 211, 130, 26, 199,
-			253, 108, 253, 11, 67, 116, 64, 50, 33, 215, 129, 27, 44, 46,
-			209, 225, 174, 189, 180, 11, 233, 59, 146, 37, 125, 131, 80, 115,
-			82, 74, 35, 126, 197, 191, 52, 104, 175, 220, 6, 64, 226, 146,
-			222, 20, 228, 190, 62, 148, 217, 215, 130, 44, 232, 91, 119, 191,
-			182, 117, 137, 224, 139, 212, 78, 61, 160, 239, 84, 11, 191, 165,
-			27, 243, 12, 176, 161, 48, 74, 92, 155, 67, 217, 213, 37, 59,
-			84, 150, 120, 144, 57, 39, 175, 36, 36, 147, 210, 252, 210, 202,
-			252, 194, 34, 48, 168, 67, 148, 46, 175, 172, 93, 151, 105, 195,
-			182, 233, 16, 164, 231, 175, 173, 93, 94, 169, 86, 158, 71, 94,
-			117, 15, 29, 94, 152, 95, 155, 191, 190, 90, 121, 126, 241, 58,
-			94, 105, 140, 144, 201, 119, 210, 28, 48, 188, 28, 106, 88, 189,
-			120, 121, 113, 225, 218, 18, 240, 164, 61, 192, 189, 46, 190, 115,
-			241, 226, 181, 53, 72, 34, 215, 251, 236, 124, 5, 19, 38, 176,
-			178, 151, 42, 203, 21, 228, 129, 137, 189, 151, 142, 206, 95, 88,
-			94, 169, 94, 153, 95, 186, 158, 128, 173, 201, 239, 47, 36, 203,
-			40, 240, 109, 166, 145, 220, 145, 204, 68, 40, 162, 123, 92, 34,
-			94, 35, 233, 105, 30, 141, 200, 222, 153, 7, 125, 138, 90, 243,
-			157, 184, 121, 31, 109, 141, 209, 92, 28, 220, 228, 130, 43, 25,
-			168, 138, 68, 113, 225, 46, 132, 111, 130, 246, 202, 5, 168, 152,
-			42, 153, 148, 36, 145, 36, 36, 241, 119, 114, 255, 85, 72, 226,
-			21, 58, 162, 115, 194, 174, 223, 8, 228, 105, 53, 185, 19, 149,
-			229, 133, 52, 107, 197, 111, 4, 213, 225, 122, 22, 96, 191, 37,
-			67, 58, 5, 159, 124, 112, 151, 138, 238, 72, 60, 31, 163, 189,
-			97, 199, 247, 83, 194, 91, 220, 165, 116, 85, 228, 0, 18, 40,
-			51, 219, 143, 211, 2, 176, 118, 237, 148, 230, 30, 216, 173, 89,
-			153, 5, 136, 160, 202, 14, 69, 19, 234, 217, 123, 199, 162, 247,
-			75, 63, 11, 15, 64, 63, 191, 193, 160, 195, 93, 40, 5, 26,
-			184, 83, 204, 161, 181, 84, 182, 57, 70, 135, 100, 6, 197, 135,
-			10, 238, 116, 80, 64, 165, 230, 55, 93, 171, 130, 75, 21, 9,
-			160, 118, 157, 208, 147, 44, 42, 252, 236, 162, 225, 125, 180, 87,
-			34, 183, 72, 105, 65, 161, 235, 129, 233, 238, 8, 29, 74, 41,
-			63, 80, 222, 201, 103, 239, 68, 48, 250, 105, 111, 245, 218, 242,
-			178, 32, 23, 3, 180, 176, 186, 182, 114, 245, 234, 3, 208, 139,
-			207, 25, 180, 15, 21, 113, 184, 121, 78, 211, 188, 80, 192, 200,
-			75, 21, 60, 7, 147, 207, 130, 41, 150, 76, 148, 204, 8, 34,
-			90, 211, 169, 95, 231, 97, 24, 132, 138, 74, 247, 53, 157, 250,
-			34, 2, 128, 72, 195, 231, 86, 16, 114, 69, 164, 155, 78, 253,
-			74, 16, 242, 226, 2, 237, 215, 42, 220, 229, 194, 225, 112, 246,
-			36, 233, 75, 248, 242, 215, 125, 203, 240, 109, 255, 204, 160, 189,
-			118, 206, 234, 249, 67, 242, 143, 245, 158, 97, 58, 189, 103, 16,
-			87, 14, 120, 209, 240, 164, 188, 114, 24, 76, 175, 28, 134, 123,
-			120, 122, 229, 48, 92, 24, 71, 53, 97, 15, 124, 25, 49, 29,
-			161, 38, 236, 193, 111, 35, 189, 131, 244, 227, 6, 205, 67, 210,
-			236, 177, 201, 152, 53, 82, 252, 160, 33, 174, 7, 132, 102, 71,
-			120, 28, 218, 116, 60, 87, 60, 162, 151, 58, 97, 63, 136, 19,
-			149, 176, 235, 199, 220, 23, 166, 186, 222, 54, 154, 138, 198, 66,
-			239, 215, 246, 156, 26, 111, 6, 30, 162, 40, 96, 110, 29, 178,
-			53, 182, 217, 169, 89, 121, 75, 224, 190, 204, 235, 44, 75, 11,
-			228, 35, 150, 78, 200, 163, 50, 69, 157, 99, 143, 188, 3, 25,
-			179, 250, 211, 180, 105, 147, 177, 161, 97, 250, 97, 83, 246, 221,
-			176, 201, 97, 107, 184, 248, 119, 178, 239, 208, 80, 188, 45, 117,
-			178, 66, 138, 151, 183, 13, 101, 52, 75, 87, 140, 198, 57, 233,
-			233, 40, 33, 52, 44, 228, 237, 32, 140, 117, 11, 164, 216, 137,
-			110, 50, 177, 103, 185, 192, 129, 168, 176, 196, 86, 170, 244, 14,
-			229, 35, 22, 117, 106, 53, 30, 41, 195, 107, 200, 149, 180, 42,
-			80, 138, 48, 185, 191, 209, 44, 54, 22, 207, 199, 164, 244, 41,
-			122, 230, 57, 81, 172, 21, 108, 58, 117, 230, 48, 161, 56, 99,
-			66, 173, 86, 70, 171, 172, 56, 220, 118, 214, 113, 5, 41, 12,
-			25, 136, 17, 45, 109, 218, 228, 240, 224, 16, 253, 51, 53, 219,
-			166, 77, 102, 172, 145, 226, 151, 179, 24, 147, 184, 66, 5, 253,
-			186, 83, 103, 91, 206, 118, 55, 198, 214, 186, 70, 28, 7, 94,
-			157, 117, 162, 20, 97, 239, 14, 214, 89, 221, 229, 117, 182, 233,
-			6, 30, 247, 99, 111, 91, 98, 193, 245, 5, 190, 82, 42, 87,
-			82, 24, 96, 65, 200, 20, 125, 123, 32, 100, 72, 205, 225, 61,
-			176, 129, 234, 114, 109, 253, 224, 232, 135, 134, 233, 247, 169, 245,
-			67, 108, 242, 136, 53, 82, 252, 184, 201, 128, 161, 198, 75, 164,
-			64, 188, 48, 81, 142, 29, 96, 84, 113, 32, 61, 242, 220, 99,
-			17, 213, 96, 143, 248, 83, 177, 244, 37, 164, 138, 75, 139, 72,
-			52, 26, 89, 184, 34, 113, 141, 150, 196, 27, 60, 22, 134, 200,
-			176, 227, 58, 109, 124, 185, 38, 60, 88, 117, 213, 172, 158, 100,
-			78, 243, 242, 70, 89, 221, 195, 196, 156, 109, 57, 17, 213, 240,
-			42, 122, 45, 135, 48, 115, 127, 168, 244, 153, 84, 188, 222, 3,
-			151, 64, 128, 30, 209, 112, 9, 84, 232, 145, 161, 97, 250, 227,
-			10, 151, 150, 77, 222, 98, 217, 197, 239, 51, 113, 169, 192, 192,
-			17, 13, 176, 99, 214, 59, 49, 116, 235, 102, 210, 183, 123, 97,
-			82, 150, 84, 40, 20, 53, 184, 113, 138, 225, 90, 208, 106, 123,
-			60, 150, 139, 107, 7, 118, 95, 15, 114, 233, 110, 216, 77, 22,
-			234, 235, 194, 108, 162, 197, 190, 7, 110, 45, 3, 112, 55, 152,
-			166, 77, 155, 188, 101, 100, 148, 126, 179, 194, 109, 206, 38, 151,
-			45, 187, 248, 55, 70, 130, 91, 232, 91, 205, 241, 107, 220, 243,
-			146, 167, 1, 252, 86, 204, 67, 223, 241, 212, 174, 158, 110, 118,
-			90, 142, 95, 98, 78, 39, 14, 90, 248, 132, 32, 194, 231, 82,
-			51, 247, 66, 63, 48, 189, 97, 203, 245, 55, 0, 163, 153, 13,
-			14, 205, 182, 67, 14, 35, 119, 55, 185, 183, 77, 211, 78, 220,
-			239, 206, 85, 170, 124, 137, 147, 146, 176, 185, 113, 35, 85, 152,
-			118, 141, 109, 211, 117, 216, 194, 21, 13, 91, 57, 3, 176, 145,
-			98, 43, 103, 218, 228, 242, 200, 40, 253, 95, 20, 141, 203, 219,
-			228, 170, 53, 90, 252, 159, 178, 216, 106, 135, 124, 83, 248, 139,
-			193, 85, 32, 249, 100, 229, 46, 73, 31, 254, 244, 75, 157, 32,
-			118, 74, 154, 105, 97, 84, 162, 140, 199, 181, 242, 204, 61, 143,
-			145, 134, 50, 119, 12, 59, 210, 82, 253, 221, 193, 250, 125, 162,
-			70, 93, 107, 164, 171, 69, 13, 49, 111, 192, 144, 6, 210, 180,
-			105, 147, 171, 195, 35, 244, 199, 212, 144, 123, 109, 242, 78, 107,
-			164, 248, 189, 233, 144, 221, 136, 117, 252, 144, 215, 130, 13, 31,
-			206, 219, 123, 77, 121, 61, 224, 17, 108, 172, 155, 126, 176, 197,
-			156, 245, 0, 118, 172, 236, 61, 206, 16, 156, 169, 141, 32, 220,
-			8, 226, 152, 251, 84, 230, 112, 227, 251, 28, 153, 188, 162, 217,
-			57, 176, 94, 3, 58, 158, 82, 149, 94, 211, 38, 239, 28, 26,
-			166, 31, 82, 43, 191, 96, 147, 27, 214, 254, 226, 95, 27, 59,
-			14, 160, 208, 241, 179, 244, 65, 24, 83, 241, 58, 219, 112, 194,
-			117, 103, 131, 223, 251, 204, 151, 249, 29, 230, 7, 45, 23, 249,
-			24, 117, 128, 55, 58, 158, 228, 28, 176, 110, 113, 128, 1, 199,
-			204, 224, 156, 215, 60, 23, 137, 76, 176, 192, 0, 123, 234, 113,
-			207, 58, 103, 130, 187, 81, 168, 191, 175, 217, 207, 222, 92, 237,
-			68, 86, 193, 0, 100, 140, 165, 105, 211, 38, 55, 246, 77, 164,
-			150, 37, 53, 115, 76, 179, 37, 169, 153, 5, 205, 150, 164, 214,
-			167, 187, 112, 170, 217, 123, 100, 49, 195, 38, 245, 164, 152, 145,
-			131, 84, 65, 243, 36, 84, 79, 138, 25, 196, 38, 117, 44, 6,
-			244, 42, 183, 209, 243, 167, 70, 106, 131, 178, 129, 14, 135, 44,
-			203, 32, 61, 182, 213, 52, 223, 45, 173, 40, 240, 82, 186, 73,
-			7, 240, 82, 218, 16, 151, 210, 174, 101, 227, 8, 12, 121, 9,
-			237, 74, 118, 197, 144, 151, 208, 110, 255, 96, 154, 38, 54, 113,
-			71, 70, 83, 35, 140, 155, 230, 128, 50, 180, 200, 67, 202, 210,
-			140, 48, 110, 230, 122, 53, 35, 140, 155, 180, 159, 126, 189, 50,
-			194, 8, 204, 225, 98, 200, 22, 150, 23, 97, 91, 68, 92, 188,
-			84, 10, 59, 232, 235, 14, 151, 57, 10, 33, 184, 9, 144, 199,
-			229, 183, 220, 40, 46, 179, 101, 244, 116, 208, 200, 154, 94, 83,
-			225, 179, 73, 60, 226, 23, 28, 178, 170, 37, 91, 121, 98, 203,
-			0, 88, 13, 204, 188, 102, 248, 17, 244, 82, 205, 240, 35, 24,
-			28, 162, 255, 63, 130, 216, 51, 236, 220, 75, 230, 255, 106, 144,
-			201, 247, 18, 182, 182, 178, 176, 50, 237, 58, 190, 223, 169, 213,
-			220, 153, 115, 226, 49, 134, 195, 166, 34, 52, 178, 185, 238, 214,
-			121, 171, 29, 0, 15, 62, 37, 238, 216, 89, 11, 196, 20, 52,
-			75, 192, 123, 239, 19, 204, 21, 139, 18, 58, 206, 235, 115, 252,
-			86, 27, 109, 107, 160, 127, 53, 199, 243, 208, 163, 67, 106, 213,
-			24, 177, 233, 249, 90, 236, 110, 58, 49, 79, 150, 38, 222, 138,
-			47, 226, 75, 253, 68, 102, 68, 114, 240, 172, 227, 221, 68, 200,
-			140, 104, 9, 141, 69, 164, 109, 185, 124, 172, 176, 238, 212, 110,
-			178, 184, 25, 6, 157, 141, 102, 247, 222, 155, 77, 140, 185, 167,
-			240, 168, 157, 130, 90, 132, 43, 172, 244, 253, 40, 154, 66, 116,
-			34, 229, 100, 43, 185, 221, 95, 231, 114, 120, 2, 17, 44, 134,
-			177, 163, 197, 189, 203, 37, 63, 26, 118, 252, 185, 160, 19, 183,
-			59, 210, 153, 0, 171, 172, 174, 44, 205, 175, 137, 195, 120, 161,
-			82, 21, 229, 161, 32, 28, 1, 115, 204, 169, 207, 54, 131, 26,
-			91, 119, 64, 18, 193, 247, 101, 210, 25, 154, 65, 96, 186, 94,
-			162, 67, 244, 255, 49, 112, 9, 195, 42, 180, 222, 107, 88, 83,
-			197, 63, 147, 44, 180, 176, 128, 119, 82, 251, 244, 44, 75, 232,
-			55, 220, 13, 229, 28, 112, 58, 8, 153, 227, 185, 78, 52, 147,
-			60, 47, 149, 210, 236, 84, 164, 23, 139, 202, 181, 198, 134, 16,
-			14, 69, 27, 202, 74, 70, 29, 46, 104, 224, 208, 105, 119, 217,
-			239, 7, 225, 84, 212, 109, 129, 37, 93, 195, 250, 188, 38, 13,
-			82, 196, 187, 17, 248, 141, 207, 25, 21, 97, 2, 36, 83, 125,
-			47, 192, 234, 94, 148, 226, 79, 153, 210, 97, 220, 145, 104, 251,
-			4, 195, 215, 0, 6, 0, 250, 39, 83, 0, 1, 192, 177, 227,
-			244, 11, 68, 98, 12, 95, 55, 89, 197, 226, 143, 19, 54, 159,
-			177, 77, 149, 47, 70, 131, 80, 216, 219, 10, 175, 26, 194, 156,
-			12, 166, 46, 189, 133, 214, 217, 241, 50, 26, 195, 70, 60, 65,
-			74, 219, 81, 142, 252, 156, 221, 215, 216, 150, 179, 173, 42, 134,
-			242, 202, 12, 142, 130, 144, 24, 114, 142, 175, 52, 180, 110, 9,
-			227, 50, 124, 182, 129, 207, 55, 153, 131, 114, 93, 83, 156, 50,
-			248, 160, 98, 203, 141, 184, 58, 50, 41, 243, 57, 28, 25, 78,
-			232, 122, 219, 106, 147, 162, 54, 33, 156, 229, 128, 238, 26, 48,
-			94, 181, 38, 111, 57, 202, 199, 70, 134, 215, 202, 206, 151, 235,
-			3, 207, 133, 67, 3, 66, 132, 214, 207, 104, 65, 132, 210, 182,
-			178, 14, 194, 119, 125, 1, 107, 57, 55, 57, 238, 226, 84, 95,
-			200, 234, 188, 230, 34, 203, 178, 91, 99, 87, 230, 159, 99, 181,
-			102, 16, 8, 155, 106, 36, 94, 232, 45, 35, 104, 113, 217, 69,
-			133, 233, 136, 107, 232, 215, 230, 223, 192, 151, 107, 218, 252, 27,
-			56, 187, 253, 123, 83, 0, 190, 94, 155, 216, 79, 127, 195, 148,
-			243, 111, 218, 214, 63, 55, 172, 227, 197, 159, 51, 239, 119, 254,
-			119, 157, 198, 180, 63, 52, 187, 30, 118, 142, 19, 237, 196, 185,
-			48, 55, 84, 163, 20, 150, 222, 221, 163, 148, 150, 132, 128, 239,
-			228, 181, 164, 124, 22, 215, 228, 33, 135, 109, 42, 241, 156, 32,
-			86, 50, 63, 205, 96, 43, 21, 241, 34, 32, 57, 202, 199, 50,
-			62, 115, 222, 169, 35, 216, 106, 114, 245, 164, 38, 74, 26, 193,
-			135, 80, 98, 1, 7, 190, 182, 74, 69, 191, 220, 6, 139, 2,
-			124, 224, 179, 5, 100, 13, 86, 170, 54, 23, 102, 14, 17, 171,
-			1, 12, 0, 244, 63, 156, 2, 8, 0, 142, 30, 163, 35, 98,
-			42, 72, 143, 157, 255, 152, 97, 125, 209, 200, 169, 44, 112, 66,
-			91, 31, 51, 6, 70, 232, 15, 25, 180, 32, 32, 64, 226, 254,
-			165, 145, 127, 168, 248, 237, 25, 18, 7, 61, 235, 68, 60, 84,
-			26, 56, 38, 173, 56, 16, 153, 112, 158, 36, 180, 36, 144, 172,
-			47, 30, 75, 101, 246, 92, 208, 161, 98, 63, 225, 238, 72, 217,
-			106, 101, 136, 143, 153, 85, 109, 72, 150, 80, 139, 175, 94, 89,
-			75, 130, 132, 15, 154, 82, 86, 170, 76, 233, 40, 237, 83, 61,
-			206, 97, 151, 7, 116, 144, 1, 160, 193, 125, 58, 136, 0, 168,
-			120, 128, 126, 53, 25, 43, 96, 228, 187, 140, 252, 191, 53, 122,
-			139, 255, 209, 16, 194, 89, 98, 177, 24, 117, 57, 82, 69, 187,
-			43, 65, 103, 66, 156, 124, 39, 134, 205, 42, 117, 99, 33, 159,
-			149, 244, 146, 226, 115, 1, 105, 180, 86, 239, 112, 53, 173, 201,
-			219, 43, 165, 245, 214, 148, 83, 203, 43, 107, 139, 66, 201, 130,
-			183, 19, 44, 118, 54, 100, 203, 145, 182, 37, 175, 92, 91, 93,
-			67, 255, 218, 158, 240, 182, 153, 62, 226, 226, 126, 167, 197, 229,
-			49, 35, 151, 86, 208, 96, 187, 90, 111, 61, 172, 33, 14, 167,
-			255, 187, 140, 161, 61, 116, 155, 82, 5, 130, 249, 255, 148, 81,
-			40, 22, 57, 118, 232, 206, 8, 8, 24, 26, 225, 104, 92, 118,
-			98, 21, 9, 84, 208, 167, 108, 135, 130, 90, 9, 228, 65, 67,
-			42, 180, 202, 148, 238, 161, 253, 105, 211, 57, 108, 123, 40, 11,
-			52, 0, 56, 188, 55, 11, 36, 0, 156, 216, 79, 95, 214, 122,
-			110, 216, 214, 191, 49, 10, 7, 138, 141, 127, 208, 158, 75, 237,
-			83, 87, 215, 129, 52, 254, 155, 238, 174, 27, 216, 163, 225, 241,
-			44, 144, 0, 112, 127, 49, 211, 117, 211, 182, 62, 243, 15, 223,
-			117, 169, 236, 233, 234, 58, 80, 146, 207, 116, 119, 29, 144, 249,
-			153, 238, 174, 3, 69, 249, 12, 116, 253, 61, 90, 215, 137, 109,
-			253, 144, 81, 56, 88, 108, 254, 131, 118, 61, 209, 166, 116, 117,
-			158, 228, 176, 249, 108, 231, 137, 1, 192, 225, 137, 44, 16, 59,
-			122, 224, 33, 234, 38, 164, 206, 176, 173, 31, 53, 242, 227, 197,
-			103, 5, 165, 115, 26, 13, 94, 139, 35, 36, 238, 234, 28, 22,
-			125, 86, 164, 94, 154, 178, 195, 168, 54, 29, 52, 136, 103, 252,
-			86, 141, 183, 149, 59, 140, 154, 27, 214, 58, 45, 241, 52, 40,
-			75, 163, 140, 60, 182, 213, 175, 131, 176, 249, 129, 81, 29, 68,
-			0, 52, 182, 151, 254, 149, 149, 208, 40, 195, 206, 255, 188, 145,
-			255, 69, 163, 183, 248, 191, 89, 108, 205, 109, 137, 115, 30, 24,
-			213, 117, 73, 164, 156, 150, 114, 183, 134, 122, 66, 36, 77, 26,
-			150, 19, 14, 250, 237, 226, 153, 147, 36, 89, 128, 246, 146, 178,
-			178, 77, 223, 150, 66, 21, 158, 235, 11, 54, 123, 113, 147, 251,
-			241, 57, 150, 220, 94, 177, 136, 75, 35, 221, 244, 104, 19, 198,
-			180, 239, 98, 147, 168, 183, 155, 100, 155, 119, 42, 88, 143, 216,
-			14, 25, 35, 41, 28, 118, 252, 187, 23, 109, 58, 30, 158, 9,
-			213, 171, 23, 217, 180, 124, 159, 186, 163, 58, 166, 186, 211, 37,
-			182, 204, 104, 157, 12, 218, 217, 134, 244, 83, 122, 195, 221, 228,
-			145, 214, 180, 20, 240, 133, 52, 19, 176, 133, 43, 148, 178, 138,
-			16, 9, 33, 171, 208, 29, 34, 63, 224, 198, 137, 211, 38, 60,
-			55, 248, 173, 152, 161, 202, 73, 169, 253, 21, 94, 75, 80, 139,
-			88, 91, 45, 39, 188, 217, 117, 77, 224, 68, 233, 74, 47, 37,
-			47, 127, 49, 66, 66, 59, 116, 129, 93, 19, 11, 178, 29, 120,
-			110, 109, 155, 38, 108, 176, 211, 110, 123, 174, 208, 54, 84, 26,
-			204, 233, 234, 29, 170, 131, 60, 183, 229, 162, 66, 214, 227, 176,
-			225, 144, 65, 81, 178, 73, 199, 7, 209, 53, 8, 217, 41, 125,
-			209, 130, 248, 99, 253, 188, 49, 52, 78, 237, 100, 191, 163, 8,
-			244, 11, 70, 225, 164, 182, 183, 80, 30, 7, 32, 203, 2, 13,
-			0, 62, 124, 60, 11, 36, 0, 156, 57, 145, 169, 210, 176, 173,
-			207, 27, 133, 153, 76, 70, 216, 48, 159, 239, 174, 210, 192, 156,
-			15, 31, 205, 2, 9, 0, 167, 166, 51, 85, 154, 182, 245, 5,
-			163, 112, 34, 147, 209, 204, 35, 48, 91, 37, 52, 254, 5, 227,
-			225, 99, 89, 32, 1, 224, 244, 12, 29, 73, 104, 133, 105, 91,
-			191, 108, 228, 31, 210, 54, 43, 84, 247, 203, 70, 126, 72, 7,
-			25, 0, 26, 214, 217, 14, 168, 234, 151, 129, 237, 248, 1, 37,
-			67, 18, 219, 250, 53, 195, 178, 19, 6, 203, 141, 64, 8, 119,
-			80, 110, 22, 20, 81, 233, 227, 4, 65, 18, 27, 180, 227, 75,
-			167, 59, 110, 188, 173, 212, 18, 146, 28, 149, 40, 10, 39, 168,
-			192, 144, 69, 36, 9, 67, 159, 1, 78, 77, 189, 183, 217, 133,
-			41, 245, 53, 241, 65, 215, 152, 105, 156, 38, 201, 99, 135, 11,
-			41, 192, 0, 64, 223, 96, 10, 192, 33, 141, 140, 210, 33, 212,
-			99, 152, 118, 254, 55, 12, 243, 203, 6, 65, 239, 13, 6, 1,
-			172, 252, 134, 65, 199, 233, 16, 98, 192, 132, 37, 244, 155, 134,
-			181, 79, 150, 55, 241, 220, 255, 205, 148, 151, 69, 163, 123, 235,
-			55, 141, 126, 59, 5, 16, 0, 236, 77, 171, 48, 108, 235, 183,
-			12, 107, 79, 146, 1, 206, 223, 223, 210, 171, 48, 48, 71, 255,
-			80, 10, 32, 0, 24, 181, 147, 42, 76, 219, 250, 109, 189, 23,
-			112, 14, 254, 182, 94, 5, 52, 242, 219, 122, 47, 96, 234, 126,
-			91, 239, 5, 177, 173, 47, 25, 214, 88, 146, 1, 78, 163, 47,
-			233, 85, 0, 170, 190, 100, 244, 15, 167, 0, 44, 98, 239, 145,
-			168, 34, 118, 254, 119, 13, 243, 15, 19, 84, 65, 254, 223, 53,
-			232, 144, 108, 129, 0, 170, 126, 207, 176, 78, 200, 242, 4, 119,
-			218, 239, 25, 214, 193, 20, 96, 0, 224, 208, 177, 20, 64, 0,
-			48, 61, 147, 84, 97, 216, 214, 239, 27, 214, 129, 36, 3, 236,
-			172, 223, 55, 172, 209, 20, 128, 57, 236, 241, 20, 64, 0, 176,
-			191, 152, 84, 97, 218, 214, 31, 24, 214, 169, 36, 131, 105, 33,
-			96, 32, 5, 228, 1, 48, 56, 153, 2, 12, 0, 28, 57, 153,
-			2, 8, 0, 202, 115, 66, 83, 8, 53, 254, 7, 195, 28, 17,
-			195, 198, 226, 255, 193, 48, 243, 42, 105, 64, 178, 183, 95, 37,
-			9, 36, 135, 134, 233, 155, 228, 75, 39, 235, 143, 13, 243, 104,
-			113, 134, 221, 228, 219, 248, 162, 183, 201, 217, 13, 183, 174, 28,
-			176, 203, 205, 145, 154, 163, 82, 89, 15, 44, 228, 63, 54, 204,
-			113, 149, 52, 32, 185, 239, 176, 74, 98, 189, 147, 71, 168, 39,
-			223, 69, 89, 127, 98, 152, 99, 197, 119, 49, 105, 67, 134, 45,
-			9, 181, 97, 67, 127, 55, 204, 156, 232, 166, 244, 207, 137, 7,
-			172, 80, 147, 193, 134, 204, 234, 133, 105, 114, 111, 229, 109, 179,
-			6, 208, 109, 212, 160, 139, 198, 173, 28, 54, 167, 16, 96, 25,
-			144, 236, 29, 82, 73, 2, 201, 209, 61, 244, 11, 226, 245, 82,
-			254, 47, 140, 158, 191, 53, 140, 226, 79, 26, 44, 53, 54, 201,
-			122, 115, 109, 132, 156, 207, 118, 43, 55, 80, 70, 21, 23, 228,
-			45, 231, 150, 219, 234, 180, 88, 228, 190, 204, 89, 208, 160, 236,
-			204, 163, 143, 189, 237, 130, 166, 184, 102, 211, 126, 192, 248, 173,
-			56, 68, 162, 20, 243, 168, 237, 212, 248, 76, 89, 83, 80, 200,
-			156, 204, 245, 107, 65, 11, 201, 7, 52, 37, 61, 49, 169, 195,
-			48, 228, 53, 199, 171, 117, 188, 68, 160, 115, 67, 108, 179, 44,
-			92, 247, 192, 76, 255, 133, 81, 176, 233, 183, 168, 135, 68, 214,
-			87, 0, 235, 95, 199, 158, 238, 56, 161, 227, 199, 242, 113, 31,
-			28, 113, 93, 47, 155, 203, 229, 242, 237, 27, 234, 205, 182, 120,
-			250, 44, 189, 183, 77, 107, 42, 217, 182, 19, 198, 84, 184, 200,
-			81, 243, 40, 15, 117, 188, 8, 194, 75, 63, 39, 213, 104, 2,
-			123, 49, 35, 103, 69, 208, 165, 175, 24, 102, 65, 37, 13, 72,
-			246, 13, 171, 36, 129, 164, 189, 135, 254, 39, 19, 251, 110, 216,
-			214, 95, 25, 166, 93, 252, 61, 113, 9, 42, 131, 68, 5, 13,
-			212, 136, 150, 5, 223, 128, 180, 94, 188, 117, 199, 103, 149, 254,
-			172, 239, 122, 234, 249, 82, 226, 116, 199, 145, 1, 6, 128, 129,
-			160, 204, 109, 168, 65, 39, 111, 188, 197, 101, 37, 138, 222, 172,
-			157, 25, 214, 76, 250, 208, 179, 19, 241, 70, 199, 195, 92, 47,
-			117, 120, 40, 156, 178, 138, 199, 151, 232, 76, 110, 59, 232, 48,
-			201, 72, 5, 109, 228, 234, 252, 32, 102, 200, 223, 226, 65, 1,
-			231, 209, 52, 122, 234, 169, 243, 242, 137, 50, 166, 207, 159, 167,
-			172, 225, 120, 17, 159, 41, 237, 120, 46, 15, 156, 48, 175, 75,
-			77, 11, 44, 12, 228, 56, 216, 116, 20, 36, 79, 250, 35, 206,
-			241, 104, 90, 119, 165, 107, 48, 113, 232, 37, 252, 40, 91, 231,
-			220, 23, 26, 117, 85, 92, 110, 34, 81, 57, 175, 167, 147, 3,
-			20, 255, 175, 210, 201, 49, 16, 253, 125, 131, 42, 73, 32, 57,
-			50, 74, 63, 36, 22, 150, 105, 91, 95, 53, 204, 147, 197, 247,
-			224, 220, 164, 78, 6, 131, 134, 56, 5, 113, 6, 210, 205, 52,
-			21, 165, 90, 55, 241, 188, 3, 39, 80, 190, 157, 45, 49, 55,
-			229, 163, 97, 105, 70, 81, 167, 165, 219, 143, 36, 101, 125, 190,
-			201, 67, 85, 131, 234, 57, 80, 187, 175, 26, 230, 1, 149, 52,
-			32, 249, 208, 113, 149, 36, 144, 156, 57, 65, 47, 83, 216, 248,
-			249, 111, 48, 123, 222, 111, 26, 197, 115, 76, 110, 243, 102, 224,
-			213, 35, 53, 113, 136, 191, 149, 106, 170, 84, 16, 118, 119, 186,
-			170, 87, 238, 52, 160, 118, 223, 96, 22, 134, 144, 254, 226, 185,
-			242, 62, 83, 146, 66, 113, 170, 188, 207, 52, 7, 84, 210, 128,
-			228, 224, 168, 74, 18, 72, 142, 237, 149, 69, 13, 219, 122, 213,
-			52, 143, 201, 143, 112, 154, 188, 106, 74, 74, 46, 206, 146, 87,
-			205, 81, 166, 146, 4, 146, 71, 142, 210, 1, 106, 90, 150, 157,
-			255, 70, 179, 231, 47, 77, 3, 59, 4, 52, 238, 27, 205, 194,
-			48, 158, 132, 22, 233, 177, 243, 175, 153, 230, 135, 76, 113, 18,
-			90, 168, 155, 120, 205, 164, 3, 120, 6, 89, 66, 47, 241, 77,
-			166, 37, 84, 141, 150, 84, 22, 124, 147, 41, 207, 90, 75, 42,
-			10, 190, 201, 236, 31, 73, 1, 4, 0, 123, 198, 146, 42, 12,
-			219, 250, 160, 105, 217, 73, 6, 88, 66, 31, 212, 171, 48, 48,
-			71, 255, 96, 10, 32, 0, 24, 25, 197, 161, 91, 232, 89, 76,
-			161, 201, 66, 172, 125, 179, 105, 90, 42, 105, 64, 50, 215, 171,
-			146, 4, 146, 180, 159, 190, 207, 192, 178, 134, 109, 125, 216, 52,
-			135, 139, 241, 221, 174, 162, 18, 197, 209, 223, 247, 101, 148, 232,
-			19, 12, 248, 195, 166, 60, 102, 44, 28, 238, 135, 205, 222, 228,
-			43, 129, 228, 224, 144, 152, 17, 171, 199, 206, 127, 196, 52, 255,
-			149, 154, 17, 116, 179, 246, 17, 179, 119, 128, 190, 25, 208, 41,
-			252, 172, 125, 212, 180, 246, 20, 167, 113, 79, 169, 174, 3, 37,
-			19, 6, 234, 146, 112, 119, 93, 36, 88, 210, 231, 217, 71, 77,
-			107, 40, 5, 152, 0, 24, 181, 233, 179, 178, 110, 195, 182, 62,
-			102, 90, 118, 241, 233, 238, 186, 165, 247, 80, 111, 59, 105, 5,
-			61, 99, 199, 201, 23, 77, 154, 138, 3, 185, 31, 180, 166, 13,
-			81, 243, 96, 10, 48, 1, 48, 50, 74, 87, 100, 211, 166, 109,
-			125, 220, 180, 70, 138, 111, 185, 211, 176, 26, 168, 100, 86, 222,
-			209, 231, 181, 135, 173, 248, 136, 61, 10, 188, 205, 204, 104, 97,
-			48, 31, 55, 173, 254, 20, 128, 77, 12, 13, 211, 71, 100, 147,
-			196, 182, 62, 97, 90, 163, 197, 163, 221, 77, 186, 62, 14, 173,
-			225, 98, 96, 38, 105, 35, 165, 170, 129, 45, 253, 9, 83, 114,
-			97, 150, 48, 203, 177, 62, 97, 14, 143, 208, 39, 101, 189, 150,
-			109, 125, 167, 105, 21, 139, 165, 93, 234, 117, 252, 12, 213, 216,
-			165, 126, 216, 161, 223, 153, 108, 57, 97, 154, 98, 125, 167, 57,
-			177, 95, 110, 89, 195, 206, 127, 183, 105, 254, 66, 178, 101, 1,
-			181, 223, 109, 74, 230, 213, 18, 162, 226, 39, 77, 201, 188, 90,
-			82, 76, 252, 164, 41, 153, 87, 75, 138, 136, 159, 52, 37, 243,
-			106, 73, 241, 240, 147, 166, 100, 94, 45, 33, 26, 126, 202, 180,
-			78, 38, 25, 128, 220, 124, 74, 175, 194, 192, 28, 135, 142, 167,
-			0, 2, 128, 153, 19, 73, 21, 166, 109, 125, 143, 105, 29, 74,
-			50, 0, 159, 255, 61, 233, 174, 23, 236, 230, 247, 152, 253, 251,
-			83, 0, 1, 192, 67, 7, 41, 23, 85, 144, 30, 219, 250, 62,
-			211, 218, 95, 188, 38, 21, 69, 41, 34, 67, 238, 212, 183, 187,
-			22, 186, 224, 254, 154, 226, 224, 194, 19, 77, 169, 77, 186, 175,
-			236, 216, 54, 143, 203, 73, 71, 144, 230, 125, 159, 57, 48, 78,
-			191, 94, 182, 107, 216, 249, 239, 55, 173, 31, 52, 115, 197, 86,
-			182, 101, 193, 196, 121, 238, 166, 174, 60, 152, 78, 31, 234, 39,
-			207, 238, 43, 11, 51, 101, 118, 177, 201, 241, 58, 150, 107, 18,
-			158, 52, 115, 106, 200, 240, 70, 93, 39, 134, 234, 17, 96, 247,
-			251, 205, 129, 189, 40, 8, 35, 0, 38, 245, 7, 204, 252, 36,
-			138, 184, 18, 146, 67, 208, 128, 14, 50, 0, 52, 120, 80, 7,
-			17, 0, 177, 135, 233, 219, 229, 224, 76, 59, 255, 89, 211, 250,
-			17, 51, 135, 59, 45, 29, 220, 84, 212, 109, 35, 129, 198, 233,
-			210, 210, 169, 94, 23, 10, 48, 177, 253, 106, 46, 143, 180, 238,
-			194, 76, 126, 214, 28, 216, 147, 116, 23, 57, 202, 31, 54, 243,
-			105, 71, 4, 87, 247, 195, 122, 119, 5, 103, 247, 195, 230, 224,
-			132, 14, 34, 0, 58, 240, 16, 157, 149, 221, 37, 118, 254, 223,
-			153, 214, 79, 153, 185, 226, 129, 29, 171, 64, 113, 246, 90, 87,
-			96, 115, 254, 59, 115, 96, 140, 190, 215, 148, 125, 193, 67, 247,
-			115, 102, 190, 88, 252, 79, 194, 160, 69, 50, 162, 93, 242, 10,
-			91, 75, 156, 99, 238, 176, 140, 83, 183, 97, 162, 100, 122, 19,
-			134, 248, 74, 212, 86, 37, 113, 103, 37, 92, 236, 7, 76, 178,
-			112, 204, 137, 153, 199, 33, 35, 156, 37, 154, 101, 170, 79, 133,
-			207, 36, 100, 18, 203, 148, 178, 21, 223, 219, 134, 147, 228, 134,
-			98, 254, 228, 72, 21, 11, 136, 103, 202, 141, 146, 96, 88, 51,
-			44, 160, 44, 32, 248, 186, 178, 20, 58, 104, 130, 85, 193, 104,
-			124, 206, 204, 143, 232, 32, 3, 64, 163, 123, 117, 16, 1, 208,
-			196, 126, 188, 185, 178, 136, 81, 232, 177, 243, 63, 109, 90, 63,
-			111, 230, 20, 122, 11, 80, 234, 167, 77, 169, 83, 176, 132, 86,
-			229, 103, 204, 60, 75, 246, 48, 8, 123, 63, 3, 45, 37, 0,
-			3, 0, 163, 7, 82, 0, 22, 57, 116, 56, 169, 194, 178, 173,
-			159, 53, 243, 41, 161, 176, 242, 8, 24, 78, 1, 6, 0, 70,
-			82, 66, 1, 130, 217, 207, 2, 161, 80, 85, 228, 108, 235, 223,
-			155, 249, 98, 146, 33, 151, 71, 192, 96, 10, 48, 0, 48, 180,
-			55, 5, 16, 0, 32, 77, 21, 85, 228, 109, 235, 231, 204, 252,
-			67, 73, 134, 188, 0, 12, 165, 0, 3, 0, 195, 251, 82, 0,
-			1, 64, 241, 64, 82, 69, 175, 109, 253, 207, 102, 126, 38, 201,
-			208, 155, 71, 192, 88, 10, 48, 0, 176, 247, 104, 10, 32, 0,
-			152, 154, 150, 124, 142, 105, 91, 159, 87, 60, 157, 133, 252, 234,
-			231, 83, 174, 1, 213, 117, 166, 148, 206, 45, 36, 150, 159, 135,
-			195, 236, 113, 44, 74, 108, 235, 151, 76, 115, 186, 120, 242, 238,
-			210, 185, 254, 154, 72, 241, 31, 48, 101, 191, 100, 154, 19, 42,
-			105, 64, 114, 255, 17, 149, 196, 154, 143, 79, 201, 46, 90, 182,
-			245, 69, 211, 60, 36, 63, 194, 84, 125, 49, 237, 49, 76, 212,
-			23, 205, 209, 253, 42, 73, 32, 249, 208, 65, 89, 52, 103, 91,
-			191, 98, 154, 135, 229, 71, 152, 162, 95, 73, 139, 194, 4, 253,
-			138, 57, 90, 84, 73, 2, 201, 131, 135, 228, 145, 71, 236, 252,
-			175, 154, 230, 255, 153, 28, 121, 208, 199, 95, 53, 233, 40, 125,
-			7, 162, 30, 183, 248, 175, 1, 223, 114, 73, 24, 140, 117, 235,
-			12, 228, 38, 199, 111, 154, 30, 94, 156, 18, 13, 215, 243, 212,
-			233, 33, 196, 30, 69, 78, 8, 18, 173, 95, 51, 165, 18, 206,
-			146, 219, 230, 215, 204, 190, 193, 20, 64, 0, 48, 50, 74, 91,
-			178, 43, 134, 109, 253, 166, 105, 77, 20, 95, 212, 47, 3, 186,
-			59, 164, 223, 198, 240, 48, 81, 106, 168, 110, 0, 11, 234, 120,
-			30, 106, 8, 226, 38, 111, 9, 35, 92, 56, 236, 64, 78, 76,
-			185, 28, 104, 46, 135, 237, 165, 61, 52, 176, 3, 125, 123, 82,
-			0, 1, 192, 248, 62, 90, 147, 61, 52, 109, 235, 203, 166, 53,
-			94, 92, 101, 151, 196, 75, 191, 76, 247, 20, 236, 238, 253, 202,
-			118, 139, 238, 236, 23, 76, 247, 151, 245, 126, 1, 98, 190, 108,
-			246, 141, 166, 0, 2, 128, 177, 189, 242, 184, 39, 144, 254, 125,
-			211, 218, 87, 188, 198, 46, 200, 87, 134, 153, 142, 37, 192, 175,
-			177, 103, 36, 135, 237, 164, 61, 131, 213, 244, 251, 102, 159, 157,
-			2, 176, 39, 123, 199, 37, 33, 36, 192, 147, 255, 161, 105, 253,
-			69, 66, 8, 133, 243, 227, 63, 52, 251, 134, 233, 101, 60, 102,
-			136, 224, 203, 255, 200, 204, 143, 22, 31, 99, 226, 41, 35, 154,
-			153, 36, 230, 81, 89, 195, 69, 116, 28, 221, 112, 106, 113, 41,
-			237, 159, 32, 196, 68, 242, 233, 127, 148, 30, 149, 68, 114, 234,
-			127, 4, 60, 230, 107, 70, 210, 160, 97, 91, 255, 187, 153, 223,
-			91, 236, 176, 244, 253, 164, 18, 65, 220, 140, 169, 100, 106, 161,
-			141, 122, 6, 229, 131, 42, 70, 133, 4, 26, 180, 59, 44, 14,
-			29, 63, 114, 129, 99, 194, 87, 72, 169, 158, 65, 168, 219, 66,
-			199, 103, 65, 39, 185, 238, 202, 244, 215, 16, 61, 25, 209, 65,
-			38, 128, 246, 140, 209, 15, 164, 253, 53, 109, 235, 207, 204, 252,
-			254, 98, 196, 178, 239, 59, 187, 250, 140, 7, 34, 154, 15, 59,
-			157, 184, 201, 253, 88, 250, 98, 23, 177, 172, 125, 166, 221, 98,
-			109, 53, 131, 136, 103, 164, 55, 224, 253, 18, 63, 55, 66, 40,
-			19, 209, 130, 210, 174, 1, 222, 254, 12, 200, 178, 6, 194, 174,
-			237, 155, 160, 213, 164, 179, 196, 182, 254, 28, 152, 134, 183, 178,
-			174, 135, 167, 93, 189, 109, 57, 183, 208, 185, 204, 117, 77, 247,
-			2, 125, 15, 185, 83, 107, 118, 205, 43, 44, 180, 63, 55, 243,
-			123, 117, 144, 9, 160, 137, 253, 244, 95, 24, 114, 23, 88, 182,
-			245, 21, 216, 157, 223, 104, 168, 217, 75, 27, 84, 206, 15, 148,
-			66, 169, 107, 35, 36, 23, 87, 218, 115, 99, 52, 186, 82, 239,
-			230, 196, 94, 1, 246, 5, 205, 143, 132, 231, 24, 125, 161, 104,
-			250, 211, 29, 251, 6, 136, 253, 87, 82, 6, 158, 32, 185, 255,
-			138, 217, 159, 238, 104, 32, 248, 95, 129, 29, 253, 101, 33, 123,
-			231, 109, 235, 255, 54, 205, 125, 197, 95, 50, 18, 45, 160, 102,
-			130, 115, 15, 173, 174, 70, 179, 75, 26, 189, 68, 127, 145, 64,
-			6, 118, 83, 246, 238, 208, 245, 162, 87, 50, 86, 105, 232, 218,
-			100, 165, 77, 162, 204, 141, 89, 139, 59, 126, 148, 132, 130, 82,
-			74, 61, 228, 184, 80, 7, 144, 122, 63, 87, 140, 162, 58, 54,
-			243, 98, 116, 125, 42, 105, 64, 146, 142, 170, 36, 129, 36, 58,
-			48, 50, 173, 156, 157, 255, 107, 179, 231, 167, 136, 208, 192, 192,
-			81, 247, 215, 102, 97, 148, 254, 83, 192, 82, 142, 244, 216, 249,
-			175, 154, 230, 123, 9, 41, 222, 78, 199, 121, 125, 190, 19, 55,
-			197, 219, 174, 184, 211, 246, 120, 106, 251, 140, 120, 2, 102, 60,
-			125, 191, 190, 144, 206, 188, 188, 154, 173, 235, 34, 199, 90, 112,
-			147, 251, 108, 58, 226, 226, 250, 113, 231, 245, 109, 216, 174, 41,
-			5, 95, 14, 165, 161, 175, 42, 113, 50, 39, 52, 64, 127, 107,
-			202, 139, 12, 76, 231, 17, 176, 39, 5, 24, 0, 24, 27, 79,
-			1, 4, 0, 242, 34, 35, 39, 52, 64, 127, 103, 202, 11, 155,
-			156, 212, 0, 253, 157, 105, 245, 165, 0, 204, 65, 135, 83, 0,
-			1, 128, 188, 176, 201, 129, 68, 246, 62, 98, 126, 35, 33, 178,
-			147, 144, 255, 125, 68, 170, 169, 114, 66, 60, 122, 149, 72, 153,
-			57, 39, 133, 163, 87, 137, 92, 172, 57, 41, 26, 189, 74, 164,
-			154, 42, 39, 5, 163, 87, 137, 84, 83, 229, 132, 204, 251, 126,
-			34, 47, 166, 114, 210, 236, 238, 253, 122, 21, 6, 230, 144, 23,
-			83, 57, 41, 243, 190, 159, 200, 139, 169, 156, 144, 121, 63, 64,
-			172, 52, 3, 28, 130, 31, 208, 171, 128, 70, 62, 64, 164, 166,
-			43, 39, 101, 222, 15, 16, 169, 233, 202, 193, 48, 94, 35, 82,
-			211, 149, 67, 76, 191, 70, 164, 166, 43, 135, 67, 120, 141, 72,
-			77, 87, 14, 7, 240, 26, 161, 253, 2, 69, 112, 70, 125, 144,
-			152, 255, 82, 161, 8, 79, 168, 15, 146, 222, 1, 250, 46, 232,
-			156, 56, 159, 190, 133, 88, 123, 138, 203, 40, 5, 113, 205, 20,
-			62, 18, 140, 144, 8, 143, 145, 134, 179, 214, 100, 32, 249, 26,
-			72, 40, 199, 228, 51, 14, 170, 137, 209, 202, 163, 254, 183, 16,
-			169, 93, 202, 201, 51, 235, 91, 200, 168, 77, 47, 202, 30, 24,
-			182, 245, 97, 98, 141, 20, 207, 118, 245, 64, 152, 242, 225, 211,
-			144, 105, 20, 177, 213, 42, 22, 247, 167, 11, 87, 102, 180, 102,
-			12, 81, 75, 127, 10, 48, 1, 48, 52, 76, 61, 217, 140, 105,
-			91, 31, 37, 214, 104, 241, 159, 220, 105, 160, 248, 142, 14, 95,
-			152, 5, 109, 24, 236, 194, 21, 73, 76, 56, 178, 133, 64, 80,
-			154, 220, 9, 83, 223, 216, 252, 14, 218, 131, 156, 60, 78, 62,
-			74, 164, 58, 40, 39, 15, 147, 143, 146, 225, 17, 250, 152, 236,
-			15, 177, 173, 143, 65, 127, 142, 239, 28, 246, 29, 21, 77, 57,
-			121, 92, 124, 76, 175, 25, 14, 139, 143, 65, 205, 231, 101, 205,
-			150, 109, 125, 156, 88, 197, 226, 236, 174, 53, 223, 65, 213, 148,
-			54, 0, 4, 252, 227, 201, 174, 145, 154, 166, 143, 19, 169, 105,
-			202, 17, 211, 206, 127, 130, 152, 63, 158, 236, 58, 24, 234, 39,
-			72, 66, 26, 80, 202, 255, 118, 34, 53, 77, 152, 206, 35, 224,
-			96, 10, 48, 0, 32, 53, 77, 57, 41, 223, 127, 59, 145, 154,
-			166, 156, 224, 10, 191, 131, 72, 77, 19, 166, 243, 8, 72, 171,
-			48, 48, 135, 212, 52, 229, 228, 141, 242, 119, 144, 153, 19, 200,
-			157, 229, 136, 9, 4, 244, 95, 17, 235, 123, 72, 78, 101, 65,
-			26, 246, 175, 200, 192, 1, 84, 72, 32, 0, 186, 250, 93, 68,
-			42, 36, 36, 36, 135, 160, 1, 29, 100, 0, 72, 42, 36, 36,
-			136, 0, 232, 192, 67, 90, 85, 134, 109, 125, 55, 201, 51, 45,
-			19, 144, 138, 239, 206, 86, 133, 90, 57, 50, 120, 64, 7, 17,
-			0, 29, 58, 172, 85, 101, 218, 214, 39, 73, 126, 159, 150, 9,
-			72, 198, 39, 179, 85, 65, 131, 159, 36, 131, 182, 14, 34, 0,
-			66, 14, 85, 85, 69, 108, 235, 83, 68, 242, 22, 18, 146, 67,
-			144, 94, 21, 44, 169, 79, 145, 193, 17, 29, 132, 5, 19, 58,
-			136, 203, 247, 123, 137, 53, 147, 224, 27, 142, 241, 239, 37, 9,
-			189, 23, 55, 39, 223, 75, 198, 142, 166, 0, 2, 128, 169, 105,
-			85, 5, 180, 242, 111, 136, 181, 63, 153, 15, 180, 200, 35, 3,
-			227, 73, 6, 211, 182, 62, 77, 172, 241, 36, 3, 84, 249, 105,
-			50, 176, 39, 201, 64, 108, 235, 51, 41, 49, 54, 81, 226, 251,
-			12, 25, 24, 75, 38, 221, 178, 243, 63, 64, 172, 31, 210, 38,
-			29, 86, 243, 15, 136, 44, 2, 39, 120, 113, 240, 131, 36, 95,
-			76, 70, 43, 46, 15, 126, 144, 228, 71, 116, 144, 1, 160, 209,
-			189, 58, 136, 0, 72, 106, 66, 114, 196, 44, 244, 216, 249, 207,
-			18, 235, 191, 79, 91, 67, 77, 200, 103, 9, 157, 72, 208, 70,
-			108, 235, 135, 137, 212, 132, 96, 58, 143, 128, 145, 20, 96, 0,
-			96, 244, 64, 10, 192, 34, 82, 19, 146, 19, 215, 251, 63, 66,
-			164, 26, 3, 211, 121, 4, 12, 166, 0, 3, 0, 67, 123, 83,
-			0, 1, 128, 84, 99, 228, 132, 212, 245, 163, 68, 170, 49, 48,
-			157, 71, 192, 80, 10, 48, 0, 48, 188, 47, 5, 16, 0, 72,
-			53, 70, 78, 216, 20, 252, 152, 94, 69, 94, 0, 210, 42, 128,
-			213, 249, 49, 189, 10, 96, 118, 126, 76, 175, 162, 215, 182, 254,
-			29, 201, 167, 75, 168, 55, 143, 128, 177, 20, 96, 0, 96, 111,
-			186, 132, 122, 9, 0, 164, 38, 36, 7, 203, 225, 39, 136, 84,
-			14, 228, 144, 38, 252, 4, 145, 154, 144, 28, 110, 173, 159, 32,
-			82, 19, 146, 195, 109, 245, 19, 64, 255, 3, 44, 106, 218, 214,
-			231, 136, 57, 86, 116, 30, 192, 130, 32, 101, 47, 239, 207, 132,
-			64, 58, 187, 21, 237, 3, 206, 63, 151, 246, 14, 250, 254, 57,
-			34, 141, 8, 114, 184, 46, 62, 71, 70, 247, 208, 63, 37, 20,
-			38, 52, 255, 5, 210, 243, 135, 196, 40, 126, 153, 176, 196, 78,
-			46, 181, 157, 79, 36, 88, 182, 112, 133, 161, 231, 74, 193, 139,
-			34, 131, 42, 131, 59, 36, 111, 232, 80, 32, 194, 103, 154, 236,
-			98, 114, 61, 131, 175, 130, 210, 139, 117, 229, 237, 92, 123, 74,
-			132, 39, 185, 180, 63, 236, 196, 157, 144, 203, 128, 21, 243, 87,
-			43, 226, 54, 156, 50, 126, 171, 237, 41, 155, 58, 209, 11, 215,
-			151, 185, 182, 156, 237, 40, 145, 52, 182, 167, 132, 173, 102, 39,
-			148, 76, 50, 58, 80, 197, 30, 39, 206, 5, 146, 183, 2, 28,
-			163, 241, 7, 59, 239, 227, 209, 171, 129, 12, 125, 134, 15, 167,
-			88, 205, 115, 241, 30, 55, 14, 24, 119, 34, 215, 219, 6, 222,
-			164, 211, 234, 120, 112, 124, 37, 54, 160, 41, 254, 16, 19, 117,
-			183, 129, 225, 169, 98, 233, 66, 2, 207, 192, 32, 148, 46, 17,
-			90, 142, 235, 139, 208, 71, 62, 115, 253, 217, 22, 111, 5, 33,
-			62, 165, 173, 53, 185, 178, 22, 16, 104, 78, 249, 126, 224, 11,
-			196, 165, 61, 126, 168, 75, 213, 82, 221, 141, 106, 193, 38, 15,
-			121, 157, 57, 181, 48, 136, 34, 154, 186, 148, 173, 94, 189, 24,
-			201, 171, 95, 216, 38, 95, 32, 133, 81, 180, 108, 201, 3, 45,
-			250, 101, 98, 178, 226, 187, 132, 189, 74, 164, 148, 116, 208, 49,
-			198, 125, 97, 94, 232, 106, 166, 253, 41, 242, 81, 173, 75, 239,
-			174, 217, 195, 74, 149, 82, 47, 143, 116, 238, 151, 137, 57, 166,
-			146, 6, 36, 247, 30, 80, 73, 2, 201, 67, 135, 233, 143, 153,
-			216, 55, 195, 182, 126, 157, 152, 227, 197, 127, 109, 178, 203, 202,
-			233, 200, 174, 119, 165, 114, 114, 19, 155, 23, 94, 199, 39, 27,
-			210, 9, 133, 146, 241, 92, 190, 69, 187, 4, 22, 94, 23, 37,
-			165, 105, 62, 90, 200, 225, 179, 105, 108, 171, 44, 21, 243, 242,
-			77, 157, 90, 231, 109, 46, 68, 25, 169, 138, 16, 171, 2, 63,
-			215, 154, 242, 61, 141, 80, 185, 183, 28, 207, 227, 66, 149, 238,
-			226, 188, 43, 235, 127, 241, 112, 52, 117, 240, 43, 240, 137, 179,
-			9, 34, 40, 190, 137, 16, 79, 227, 43, 141, 157, 67, 191, 44,
-			124, 172, 8, 141, 187, 227, 69, 120, 221, 20, 113, 37, 3, 230,
-			241, 220, 255, 117, 181, 245, 243, 72, 152, 126, 157, 244, 142, 170,
-			36, 129, 228, 216, 94, 250, 57, 130, 88, 54, 109, 235, 15, 128,
-			50, 253, 32, 73, 106, 222, 29, 199, 10, 17, 234, 2, 38, 106,
-			6, 97, 114, 97, 209, 232, 120, 94, 214, 178, 4, 171, 72, 222,
-			60, 184, 254, 70, 148, 58, 226, 61, 193, 90, 206, 173, 244, 166,
-			32, 85, 82, 164, 31, 209, 122, 89, 26, 141, 160, 129, 75, 66,
-			61, 170, 252, 165, 242, 21, 231, 150, 8, 210, 186, 206, 129, 63,
-			111, 170, 146, 126, 224, 207, 198, 60, 196, 55, 188, 114, 22, 49,
-			234, 93, 7, 102, 22, 102, 187, 19, 170, 183, 36, 106, 56, 211,
-			41, 130, 19, 140, 10, 11, 225, 117, 165, 13, 144, 100, 164, 230,
-			68, 28, 95, 204, 47, 7, 49, 87, 250, 51, 113, 191, 158, 238,
-			242, 184, 41, 95, 35, 43, 58, 191, 30, 4, 30, 136, 243, 231,
-			196, 69, 81, 200, 27, 248, 110, 73, 93, 223, 224, 91, 99, 224,
-			250, 221, 184, 227, 40, 75, 120, 238, 195, 206, 193, 85, 83, 15,
-			148, 116, 163, 105, 18, 196, 189, 156, 152, 79, 32, 244, 127, 144,
-			206, 54, 218, 218, 145, 222, 97, 149, 36, 144, 180, 247, 36, 78,
-			138, 255, 245, 40, 125, 203, 125, 122, 9, 86, 2, 79, 234, 170,
-			78, 243, 85, 252, 122, 29, 29, 79, 110, 208, 177, 29, 178, 126,
-			149, 191, 100, 31, 167, 150, 211, 137, 155, 210, 121, 82, 151, 183,
-			178, 249, 78, 220, 172, 226, 119, 123, 138, 14, 107, 14, 148, 52,
-			159, 99, 169, 95, 37, 84, 45, 60, 152, 247, 160, 111, 26, 22,
-			49, 10, 202, 255, 88, 125, 7, 205, 75, 47, 65, 180, 167, 159,
-			254, 73, 65, 184, 9, 58, 210, 83, 54, 138, 191, 83, 216, 169,
-			123, 169, 242, 151, 196, 153, 135, 46, 205, 213, 41, 62, 171, 196,
-			225, 140, 81, 133, 90, 37, 32, 50, 114, 175, 81, 166, 108, 33,
-			16, 123, 12, 35, 147, 98, 37, 11, 87, 32, 39, 122, 20, 72,
-			212, 206, 139, 25, 9, 56, 241, 16, 130, 145, 51, 129, 168, 113,
-			31, 24, 157, 136, 118, 101, 150, 1, 51, 163, 72, 231, 15, 128,
-			176, 164, 4, 162, 196, 230, 235, 117, 161, 140, 115, 252, 186, 210,
-			51, 166, 154, 178, 93, 116, 77, 45, 25, 162, 14, 182, 163, 238,
-			228, 190, 91, 155, 37, 75, 138, 142, 220, 228, 62, 77, 222, 126,
-			165, 225, 180, 132, 5, 153, 222, 231, 173, 116, 128, 187, 218, 94,
-			151, 211, 151, 4, 89, 172, 8, 47, 75, 168, 4, 145, 186, 135,
-			82, 119, 213, 210, 230, 191, 229, 132, 55, 49, 110, 45, 101, 83,
-			50, 179, 235, 111, 76, 73, 150, 72, 25, 20, 74, 166, 200, 241,
-			217, 202, 219, 112, 61, 150, 217, 188, 36, 98, 120, 202, 151, 196,
-			229, 175, 56, 210, 40, 158, 105, 234, 221, 233, 98, 102, 115, 137,
-			97, 56, 254, 54, 178, 22, 2, 9, 242, 233, 78, 154, 19, 149,
-			133, 201, 91, 110, 164, 126, 213, 171, 23, 177, 86, 209, 17, 121,
-			22, 172, 188, 141, 9, 85, 65, 198, 67, 18, 186, 159, 80, 195,
-			46, 139, 156, 21, 225, 136, 106, 62, 220, 104, 97, 128, 51, 89,
-			78, 145, 114, 192, 115, 203, 241, 26, 65, 216, 226, 245, 178, 120,
-			195, 7, 75, 49, 121, 68, 219, 228, 94, 91, 86, 117, 53, 121,
-			123, 184, 192, 125, 151, 215, 101, 85, 233, 203, 188, 174, 153, 198,
-			202, 93, 31, 159, 168, 214, 98, 25, 29, 237, 174, 45, 204, 123,
-			104, 15, 178, 40, 24, 55, 81, 253, 174, 181, 202, 58, 5, 15,
-			140, 42, 112, 177, 180, 133, 243, 22, 209, 146, 35, 42, 211, 148,
-			80, 56, 107, 41, 133, 196, 234, 37, 47, 34, 47, 19, 107, 220,
-			1, 42, 212, 150, 175, 1, 163, 123, 116, 154, 34, 41, 147, 77,
-			139, 3, 49, 181, 106, 12, 121, 28, 186, 250, 242, 229, 183, 156,
-			90, 44, 56, 235, 221, 200, 135, 188, 245, 79, 195, 13, 29, 41,
-			60, 36, 204, 47, 209, 245, 195, 113, 243, 96, 241, 54, 83, 218,
-			228, 204, 250, 18, 58, 230, 90, 128, 124, 177, 58, 172, 181, 125,
-			135, 235, 175, 196, 156, 52, 130, 29, 221, 229, 177, 240, 157, 182,
-			161, 116, 10, 89, 214, 67, 173, 28, 151, 254, 253, 133, 215, 137,
-			227, 99, 19, 154, 123, 140, 227, 7, 30, 162, 63, 99, 42, 255,
-			24, 179, 230, 67, 197, 31, 49, 187, 247, 130, 134, 37, 199, 175,
-			7, 45, 111, 91, 133, 44, 77, 181, 150, 45, 167, 214, 116, 125,
-			158, 104, 20, 197, 83, 205, 212, 72, 35, 8, 119, 243, 63, 163,
-			222, 215, 70, 157, 154, 228, 15, 129, 23, 219, 10, 88, 232, 212,
-			50, 132, 56, 162, 34, 126, 176, 50, 67, 137, 131, 100, 86, 180,
-			136, 29, 48, 89, 119, 166, 104, 18, 177, 89, 203, 32, 181, 219,
-			61, 143, 77, 183, 195, 96, 221, 89, 247, 182, 129, 235, 210, 56,
-			30, 105, 119, 210, 98, 81, 32, 250, 136, 194, 94, 224, 115, 41,
-			182, 109, 185, 126, 130, 110, 35, 7, 72, 236, 213, 220, 138, 204,
-			22, 246, 105, 110, 69, 102, 139, 7, 18, 78, 229, 75, 37, 122,
-			97, 215, 3, 92, 4, 209, 152, 131, 5, 54, 23, 243, 91, 241,
-			92, 44, 93, 121, 99, 193, 36, 37, 153, 149, 193, 204, 215, 187,
-			135, 163, 250, 207, 6, 205, 37, 81, 164, 92, 233, 150, 30, 163,
-			67, 185, 126, 108, 143, 81, 171, 3, 64, 96, 55, 172, 203, 61,
-			85, 76, 217, 227, 52, 135, 161, 107, 208, 5, 162, 113, 185, 167,
-			42, 146, 144, 27, 88, 63, 225, 162, 22, 114, 67, 74, 69, 167,
-			202, 233, 209, 169, 198, 105, 110, 125, 59, 230, 194, 239, 244, 0,
-			212, 128, 73, 123, 34, 241, 25, 222, 43, 179, 43, 175, 225, 227,
-			52, 231, 132, 161, 179, 141, 46, 53, 225, 131, 72, 38, 145, 167,
-			250, 30, 40, 242, 212, 228, 167, 115, 52, 191, 138, 207, 225, 237,
-			114, 58, 238, 254, 51, 197, 114, 6, 119, 101, 145, 167, 60, 31,
-			7, 45, 133, 147, 83, 26, 78, 238, 85, 64, 224, 235, 140, 142,
-			175, 123, 21, 145, 184, 60, 165, 225, 242, 158, 173, 32, 158, 207,
-			164, 120, 238, 63, 115, 104, 247, 2, 171, 112, 108, 248, 53, 174,
-			230, 225, 49, 125, 30, 238, 167, 148, 156, 167, 57, 106, 113, 191,
-			211, 146, 30, 82, 247, 223, 169, 88, 12, 157, 131, 140, 246, 35,
-			201, 196, 22, 238, 54, 160, 103, 86, 87, 150, 181, 73, 63, 163,
-			38, 189, 239, 62, 10, 137, 172, 197, 22, 37, 171, 60, 182, 31,
-			165, 57, 148, 229, 165, 235, 207, 195, 119, 236, 98, 89, 56, 0,
-			21, 185, 139, 115, 52, 151, 248, 239, 172, 7, 53, 229, 191, 179,
-			30, 212, 178, 254, 126, 149, 15, 213, 226, 49, 106, 65, 251, 246,
-			65, 74, 91, 206, 173, 235, 226, 213, 131, 116, 32, 221, 215, 114,
-			110, 45, 33, 160, 56, 67, 11, 10, 139, 247, 202, 154, 167, 22,
-			204, 235, 133, 2, 205, 11, 135, 13, 147, 31, 182, 168, 117, 201,
-			245, 184, 125, 158, 22, 212, 48, 228, 184, 30, 238, 26, 23, 100,
-			75, 252, 252, 203, 200, 27, 42, 71, 241, 255, 48, 105, 65, 125,
-			219, 101, 128, 54, 44, 185, 250, 182, 28, 31, 254, 182, 207, 211,
-			28, 186, 158, 144, 193, 4, 166, 238, 214, 92, 25, 131, 99, 72,
-			116, 98, 169, 226, 127, 103, 208, 190, 36, 100, 198, 46, 77, 150,
-			105, 111, 157, 55, 156, 142, 23, 39, 97, 216, 178, 13, 136, 208,
-			119, 42, 147, 93, 164, 5, 216, 199, 192, 38, 75, 255, 171, 73,
-			218, 158, 85, 248, 146, 123, 102, 239, 174, 83, 94, 149, 153, 138,
-			55, 40, 77, 251, 187, 139, 187, 214, 39, 179, 238, 90, 143, 223,
-			123, 228, 48, 70, 221, 35, 248, 115, 116, 48, 51, 19, 187, 52,
-			114, 38, 219, 200, 67, 119, 107, 68, 143, 180, 240, 83, 6, 237,
-			91, 149, 70, 174, 161, 125, 132, 38, 20, 95, 247, 19, 60, 160,
-			128, 232, 41, 248, 73, 154, 199, 57, 137, 100, 100, 189, 163, 221,
-			232, 81, 213, 137, 193, 40, 191, 184, 162, 76, 113, 133, 246, 107,
-			224, 251, 9, 167, 183, 219, 60, 106, 142, 110, 31, 125, 254, 236,
-			235, 56, 233, 158, 249, 161, 67, 66, 104, 141, 254, 219, 23, 90,
-			159, 73, 133, 214, 103, 82, 161, 245, 88, 34, 180, 142, 211, 134,
-			144, 89, 135, 122, 14, 26, 197, 231, 25, 162, 48, 213, 80, 167,
-			214, 176, 226, 177, 84, 242, 26, 74, 44, 68, 233, 67, 37, 18,
-			110, 147, 156, 152, 169, 101, 132, 74, 101, 199, 23, 46, 72, 132,
-			1, 145, 98, 88, 135, 164, 35, 179, 158, 66, 143, 109, 13, 155,
-			15, 73, 183, 185, 5, 225, 82, 119, 48, 245, 181, 54, 98, 237,
-			85, 12, 99, 14, 82, 125, 26, 51, 57, 34, 35, 173, 9, 102,
-			114, 100, 207, 88, 234, 107, 109, 52, 41, 6, 76, 209, 168, 69,
-			53, 166, 104, 180, 95, 247, 181, 54, 154, 20, 51, 109, 98, 39,
-			197, 204, 28, 164, 84, 49, 168, 210, 238, 31, 81, 41, 98, 19,
-			59, 41, 70, 108, 178, 39, 41, 70, 114, 144, 82, 158, 221, 136,
-			97, 147, 61, 73, 107, 4, 114, 38, 197, 44, 155, 236, 77, 138,
-			89, 57, 72, 169, 214, 44, 195, 38, 123, 147, 177, 89, 196, 38,
-			123, 147, 98, 57, 155, 140, 39, 197, 114, 152, 82, 40, 201, 97,
-			208, 61, 213, 201, 28, 177, 201, 120, 82, 44, 111, 147, 9, 107,
-			92, 126, 202, 231, 32, 165, 90, 203, 27, 54, 153, 232, 31, 85,
-			41, 98, 147, 137, 177, 189, 178, 88, 175, 77, 246, 39, 197, 122,
-			181, 120, 124, 194, 165, 224, 254, 164, 181, 94, 98, 147, 253, 73,
-			177, 130, 77, 14, 200, 88, 113, 61, 102, 33, 15, 169, 253, 42,
-			101, 216, 228, 128, 140, 21, 215, 99, 22, 136, 77, 14, 60, 60,
-			169, 226, 45, 30, 238, 185, 156, 250, 186, 59, 44, 95, 80, 225,
-			155, 0, 102, 78, 235, 190, 238, 24, 29, 148, 47, 102, 123, 224,
-			235, 195, 214, 177, 156, 114, 102, 135, 223, 31, 30, 24, 165, 207,
-			224, 131, 114, 225, 103, 133, 28, 201, 239, 45, 62, 206, 174, 56,
-			225, 205, 122, 176, 229, 207, 10, 3, 124, 212, 80, 103, 162, 121,
-			39, 14, 28, 164, 255, 34, 60, 169, 203, 148, 142, 224, 35, 115,
-			233, 56, 133, 28, 201, 15, 232, 16, 144, 191, 6, 71, 116, 8,
-			177, 201, 145, 61, 99, 24, 195, 77, 249, 75, 33, 71, 243, 251,
-			180, 44, 176, 42, 143, 102, 170, 129, 33, 31, 29, 180, 117, 8,
-			177, 201, 209, 189, 227, 244, 114, 234, 212, 111, 202, 58, 88, 124,
-			92, 222, 28, 120, 40, 249, 10, 149, 119, 20, 185, 226, 222, 234,
-			38, 247, 35, 77, 121, 26, 113, 65, 39, 154, 206, 166, 114, 132,
-			106, 200, 32, 117, 83, 210, 207, 165, 33, 204, 123, 200, 212, 160,
-			157, 241, 15, 56, 181, 103, 34, 227, 31, 112, 234, 192, 67, 114,
-			58, 12, 219, 58, 97, 158, 34, 154, 227, 182, 19, 116, 136, 190,
-			152, 248, 109, 35, 179, 86, 177, 184, 12, 164, 47, 14, 221, 90,
-			172, 174, 60, 196, 43, 216, 212, 131, 6, 178, 119, 82, 47, 47,
-			41, 78, 130, 126, 113, 205, 209, 114, 182, 41, 139, 157, 155, 105,
-			215, 69, 80, 200, 89, 75, 75, 131, 148, 211, 191, 55, 77, 131,
-			156, 51, 177, 95, 118, 213, 180, 173, 51, 230, 99, 170, 171, 48,
-			13, 103, 168, 45, 187, 138, 177, 244, 30, 253, 7, 235, 42, 190,
-			126, 32, 143, 90, 90, 218, 176, 201, 163, 73, 87, 69, 132, 187,
-			71, 39, 246, 11, 175, 139, 64, 28, 222, 108, 142, 202, 158, 2,
-			225, 120, 51, 29, 74, 35, 102, 158, 51, 159, 214, 35, 102, 158,
-			43, 12, 165, 206, 26, 159, 176, 70, 53, 103, 141, 79, 36, 193,
-			40, 33, 227, 19, 125, 3, 154, 179, 198, 39, 134, 71, 210, 136,
-			153, 79, 90, 182, 114, 142, 152, 135, 84, 65, 115, 156, 248, 100,
-			223, 160, 230, 56, 241, 201, 196, 53, 164, 105, 147, 243, 105, 196,
-			204, 60, 164, 10, 90, 196, 204, 243, 125, 122, 196, 204, 243, 122,
-			196, 204, 167, 146, 214, 72, 30, 82, 122, 196, 204, 167, 146, 214,
-			0, 11, 79, 37, 173, 89, 54, 121, 171, 164, 117, 34, 82, 229,
-			91, 173, 1, 45, 82, 229, 91, 7, 71, 180, 72, 149, 111, 149,
-			180, 14, 35, 85, 206, 91, 251, 180, 72, 149, 243, 73, 49, 32,
-			145, 243, 131, 182, 22, 169, 114, 126, 239, 56, 157, 194, 98, 121,
-			155, 92, 180, 70, 39, 139, 172, 29, 180, 241, 214, 81, 234, 99,
-			112, 190, 175, 175, 198, 161, 242, 37, 153, 199, 156, 202, 9, 38,
-			144, 207, 139, 5, 213, 0, 144, 207, 139, 9, 150, 123, 109, 178,
-			104, 141, 201, 79, 189, 121, 72, 169, 113, 3, 249, 92, 148, 78,
-			63, 241, 81, 0, 89, 148, 190, 66, 13, 32, 159, 151, 18, 44,
-			3, 249, 188, 148, 20, 3, 242, 121, 41, 193, 50, 144, 207, 75,
-			163, 54, 189, 32, 34, 109, 190, 173, 199, 55, 138, 143, 49, 96,
-			229, 186, 158, 168, 3, 4, 47, 145, 128, 1, 145, 167, 179, 140,
-			242, 173, 124, 80, 168, 184, 151, 111, 43, 12, 208, 179, 42, 238,
-			229, 21, 211, 35, 197, 99, 201, 129, 174, 179, 4, 174, 191, 129,
-			78, 33, 37, 91, 74, 181, 240, 152, 87, 168, 141, 68, 75, 134,
-			199, 92, 177, 246, 124, 45, 180, 87, 143, 164, 185, 98, 209, 76,
-			36, 205, 149, 254, 161, 76, 36, 205, 149, 81, 155, 254, 157, 33,
-			155, 54, 108, 114, 205, 26, 43, 254, 133, 193, 64, 190, 200, 220,
-			189, 138, 247, 237, 194, 115, 101, 210, 110, 50, 22, 86, 137, 53,
-			63, 106, 226, 33, 104, 216, 194, 235, 77, 241, 246, 243, 221, 17,
-			62, 253, 9, 234, 29, 79, 232, 198, 162, 206, 122, 20, 187, 177,
-			208, 132, 105, 14, 253, 88, 69, 93, 71, 171, 86, 104, 138, 76,
-			241, 148, 13, 107, 44, 137, 46, 102, 157, 33, 138, 182, 160, 171,
-			37, 230, 52, 98, 142, 87, 196, 52, 211, 86, 164, 189, 105, 72,
-			29, 211, 40, 140, 192, 33, 115, 77, 195, 24, 236, 236, 107, 253,
-			195, 105, 154, 216, 228, 154, 45, 12, 112, 76, 113, 146, 62, 107,
-			213, 114, 234, 59, 206, 229, 179, 3, 123, 241, 36, 53, 213, 73,
-			250, 220, 215, 126, 146, 154, 201, 73, 250, 156, 60, 2, 205, 228,
-			36, 125, 78, 158, 164, 102, 114, 146, 62, 39, 79, 82, 83, 157,
-			164, 47, 228, 39, 180, 44, 64, 188, 94, 200, 247, 235, 16, 200,
-			131, 47, 211, 18, 8, 177, 201, 11, 227, 251, 232, 191, 55, 146,
-			122, 76, 155, 220, 200, 79, 20, 63, 107, 48, 37, 213, 49, 215,
-			175, 163, 217, 121, 196, 220, 6, 155, 2, 240, 148, 184, 228, 22,
-			19, 177, 153, 165, 251, 201, 44, 11, 55, 0, 84, 241, 227, 202,
-			119, 104, 93, 68, 158, 237, 184, 81, 83, 248, 62, 152, 156, 20,
-			54, 11, 126, 16, 207, 70, 29, 57, 89, 172, 210, 96, 82, 226,
-			68, 171, 109, 36, 54, 175, 64, 219, 231, 216, 43, 183, 111, 75,
-			127, 5, 234, 2, 69, 190, 48, 78, 7, 6, 180, 238, 70, 62,
-			3, 49, 108, 114, 163, 95, 31, 60, 80, 223, 27, 227, 251, 52,
-			28, 18, 155, 172, 103, 112, 8, 36, 121, 61, 51, 21, 64, 150,
-			215, 7, 245, 106, 128, 52, 175, 143, 239, 163, 159, 49, 229, 246,
-			50, 109, 114, 211, 58, 86, 252, 132, 41, 80, 33, 80, 165, 69,
-			242, 213, 12, 91, 18, 92, 161, 187, 139, 117, 55, 78, 66, 52,
-			36, 155, 1, 214, 191, 112, 57, 138, 54, 15, 56, 226, 150, 19,
-			215, 154, 242, 58, 121, 131, 223, 98, 115, 255, 228, 232, 43, 47,
-			188, 235, 246, 139, 39, 111, 207, 97, 56, 219, 201, 163, 175, 52,
-			130, 224, 246, 100, 226, 176, 150, 5, 55, 165, 31, 105, 140, 66,
-			91, 98, 147, 71, 197, 191, 65, 8, 153, 147, 156, 126, 128, 55,
-			85, 66, 224, 76, 111, 37, 208, 172, 65, 225, 90, 146, 79, 232,
-			232, 5, 216, 155, 218, 155, 190, 26, 79, 204, 76, 210, 135, 129,
-			187, 109, 107, 109, 47, 194, 241, 114, 211, 42, 166, 105, 195, 38,
-			55, 15, 176, 52, 77, 108, 114, 243, 200, 81, 60, 1, 144, 51,
-			105, 153, 199, 180, 40, 185, 45, 115, 159, 22, 37, 183, 53, 193,
-			180, 40, 185, 173, 35, 71, 145, 129, 38, 182, 213, 6, 105, 149,
-			10, 31, 4, 164, 93, 16, 7, 41, 129, 234, 94, 50, 15, 96,
-			17, 124, 223, 68, 94, 146, 206, 167, 241, 113, 19, 121, 169, 111,
-			92, 165, 136, 77, 94, 218, 95, 148, 197, 12, 155, 132, 38, 147,
-			159, 96, 159, 133, 210, 131, 53, 190, 56, 34, 225, 94, 85, 37,
-			236, 175, 240, 208, 225, 68, 185, 252, 187, 203, 244, 169, 251, 188,
-			193, 230, 232, 62, 236, 250, 174, 17, 123, 255, 30, 20, 212, 175,
-			251, 38, 253, 117, 69, 251, 253, 6, 131, 238, 85, 235, 160, 226,
-			71, 177, 227, 199, 46, 146, 195, 7, 138, 244, 249, 24, 237, 83,
-			175, 138, 67, 169, 96, 154, 184, 147, 6, 165, 154, 102, 125, 198,
-			42, 144, 17, 107, 242, 251, 115, 212, 238, 242, 201, 86, 229, 47,
-			217, 71, 211, 48, 97, 100, 151, 144, 158, 50, 108, 216, 227, 116,
-			16, 127, 92, 79, 131, 135, 17, 84, 177, 100, 131, 53, 150, 151,
-			59, 173, 168, 58, 128, 89, 85, 144, 202, 183, 210, 161, 68, 51,
-			36, 90, 34, 105, 36, 164, 93, 145, 82, 77, 84, 73, 34, 108,
-			240, 91, 232, 72, 82, 131, 106, 223, 186, 75, 251, 195, 42, 183,
-			234, 194, 25, 58, 16, 58, 91, 215, 147, 56, 193, 119, 8, 75,
-			217, 31, 58, 91, 202, 149, 128, 253, 38, 58, 216, 8, 180, 120,
-			129, 82, 61, 189, 155, 133, 196, 64, 35, 72, 3, 8, 218, 103,
-			104, 14, 13, 104, 164, 98, 26, 195, 225, 238, 196, 123, 121, 9,
-			242, 84, 69, 86, 251, 205, 180, 87, 190, 219, 149, 186, 233, 67,
-			119, 40, 85, 17, 185, 170, 42, 123, 241, 77, 52, 135, 53, 217,
-			147, 116, 48, 243, 252, 72, 70, 114, 235, 111, 57, 183, 160, 240,
-			170, 251, 50, 127, 198, 42, 24, 35, 230, 51, 86, 193, 28, 33,
-			197, 239, 48, 104, 175, 172, 205, 126, 107, 26, 20, 206, 146, 154,
-			198, 187, 54, 95, 94, 65, 119, 139, 81, 18, 60, 174, 248, 56,
-			237, 149, 48, 17, 147, 26, 131, 1, 10, 237, 168, 76, 233, 141,
-			63, 99, 21, 172, 145, 220, 51, 86, 33, 55, 146, 79, 224, 100,
-			196, 74, 32, 249, 145, 222, 201, 191, 49, 118, 174, 215, 168, 109,
-			23, 105, 65, 189, 77, 144, 177, 13, 147, 180, 61, 67, 251, 196,
-			42, 117, 235, 74, 197, 152, 13, 51, 93, 192, 207, 149, 122, 100,
-			207, 209, 68, 53, 137, 185, 201, 46, 185, 251, 85, 14, 40, 112,
-			76, 91, 198, 120, 79, 139, 75, 176, 47, 93, 171, 104, 205, 100,
-			31, 203, 132, 66, 148, 193, 26, 211, 1, 200, 143, 246, 97, 218,
-			47, 238, 47, 175, 55, 29, 47, 198, 181, 85, 168, 82, 1, 186,
-			236, 120, 241, 131, 153, 209, 252, 237, 69, 17, 131, 235, 127, 48,
-			254, 219, 87, 73, 238, 110, 71, 179, 148, 198, 224, 154, 87, 49,
-			184, 104, 18, 131, 107, 32, 141, 193, 53, 212, 195, 12, 77, 153,
-			120, 144, 94, 73, 20, 134, 230, 222, 226, 91, 153, 164, 174, 138,
-			233, 7, 156, 206, 10, 39, 241, 201, 39, 233, 0, 80, 74, 52,
-			232, 56, 50, 43, 204, 72, 149, 99, 38, 188, 195, 72, 223, 72,
-			151, 202, 241, 125, 201, 253, 245, 132, 57, 90, 252, 207, 6, 11,
-			121, 67, 53, 187, 225, 198, 152, 84, 108, 144, 108, 89, 88, 150,
-			98, 195, 245, 29, 162, 71, 67, 123, 172, 150, 218, 150, 40, 67,
-			145, 93, 132, 183, 52, 218, 142, 172, 127, 118, 203, 173, 243, 172,
-			75, 124, 138, 42, 90, 63, 72, 124, 38, 105, 222, 242, 189, 64,
-			188, 181, 12, 124, 101, 207, 89, 235, 120, 14, 6, 89, 97, 211,
-			158, 123, 147, 83, 54, 21, 242, 70, 52, 215, 228, 78, 61, 154,
-			107, 57, 81, 204, 195, 41, 52, 213, 187, 182, 124, 109, 21, 157,
-			220, 166, 170, 214, 137, 76, 88, 139, 9, 169, 126, 16, 44, 248,
-			196, 240, 8, 157, 131, 57, 235, 179, 201, 1, 115, 176, 120, 68,
-			173, 69, 118, 22, 217, 40, 125, 150, 100, 140, 65, 42, 52, 138,
-			125, 61, 54, 57, 208, 47, 235, 234, 131, 137, 208, 82, 166, 72,
-			189, 102, 40, 45, 238, 97, 115, 186, 248, 114, 226, 153, 35, 236,
-			114, 52, 237, 212, 226, 142, 227, 165, 152, 244, 157, 22, 71, 139,
-			135, 45, 238, 121, 240, 47, 122, 122, 215, 132, 44, 170, 123, 200,
-			23, 171, 70, 104, 216, 84, 13, 45, 220, 121, 33, 127, 169, 35,
-			124, 79, 73, 45, 113, 30, 122, 178, 95, 211, 32, 31, 46, 30,
-			209, 52, 200, 135, 143, 79, 209, 143, 11, 197, 103, 238, 137, 158,
-			111, 48, 140, 226, 55, 211, 110, 111, 170, 154, 169, 216, 118, 208,
-			65, 243, 172, 40, 226, 50, 232, 21, 26, 45, 115, 224, 70, 131,
-			70, 234, 27, 7, 109, 152, 167, 34, 105, 247, 170, 76, 190, 244,
-			42, 234, 188, 230, 57, 33, 207, 120, 246, 16, 139, 40, 240, 211,
-			151, 181, 24, 208, 1, 237, 85, 96, 166, 159, 147, 110, 197, 84,
-			217, 164, 57, 12, 137, 180, 205, 106, 65, 107, 221, 245, 29, 25,
-			178, 69, 154, 30, 93, 69, 198, 26, 196, 1, 71, 134, 206, 16,
-			222, 116, 219, 66, 76, 246, 58, 74, 98, 208, 6, 208, 229, 141,
-			219, 137, 133, 89, 141, 112, 113, 190, 179, 218, 100, 14, 92, 157,
-			179, 96, 211, 242, 138, 66, 110, 8, 217, 235, 186, 168, 70, 212,
-			168, 74, 206, 220, 111, 71, 238, 216, 135, 208, 217, 66, 69, 107,
-			208, 96, 234, 88, 98, 179, 79, 37, 214, 34, 122, 61, 34, 244,
-			163, 168, 110, 59, 232, 100, 173, 143, 82, 11, 190, 133, 43, 210,
-			237, 140, 190, 203, 165, 37, 155, 159, 88, 246, 150, 18, 15, 129,
-			49, 172, 92, 152, 221, 45, 101, 255, 87, 89, 136, 148, 12, 166,
-			100, 77, 105, 131, 62, 167, 166, 142, 50, 71, 90, 234, 7, 210,
-			112, 7, 27, 76, 215, 68, 73, 132, 47, 145, 166, 251, 113, 51,
-			168, 203, 72, 115, 202, 204, 198, 17, 78, 255, 176, 33, 95, 51,
-			184, 129, 69, 209, 112, 61, 79, 217, 23, 101, 24, 44, 105, 179,
-			134, 39, 146, 226, 212, 112, 15, 214, 161, 62, 229, 110, 185, 142,
-			177, 143, 54, 147, 232, 19, 181, 160, 213, 189, 96, 165, 220, 165,
-			164, 246, 122, 218, 190, 10, 16, 16, 248, 222, 54, 77, 181, 227,
-			98, 77, 236, 52, 184, 228, 186, 249, 163, 196, 196, 142, 166, 64,
-			102, 13, 182, 124, 154, 58, 143, 169, 248, 26, 181, 44, 49, 55,
-			121, 43, 169, 169, 227, 119, 173, 78, 188, 189, 247, 3, 127, 54,
-			109, 185, 19, 241, 80, 154, 98, 59, 12, 227, 137, 205, 148, 152,
-			15, 237, 70, 80, 115, 118, 12, 126, 166, 203, 52, 153, 61, 45,
-			46, 192, 58, 111, 58, 30, 30, 60, 186, 201, 91, 130, 160, 212,
-			36, 50, 41, 132, 15, 203, 133, 193, 183, 52, 227, 18, 243, 161,
-			175, 7, 140, 225, 0, 249, 212, 146, 85, 225, 85, 212, 99, 115,
-			241, 218, 80, 106, 45, 148, 225, 32, 208, 13, 52, 58, 149, 190,
-			15, 149, 151, 28, 205, 75, 135, 124, 221, 78, 89, 221, 13, 121,
-			45, 198, 64, 151, 234, 30, 232, 137, 66, 81, 248, 172, 68, 101,
-			247, 83, 230, 145, 226, 215, 203, 80, 5, 174, 190, 109, 179, 4,
-			6, 153, 30, 181, 61, 132, 140, 153, 24, 199, 82, 45, 20, 6,
-			12, 87, 190, 205, 144, 254, 223, 4, 94, 182, 89, 61, 240, 167,
-			226, 82, 242, 226, 101, 157, 119, 89, 183, 25, 120, 139, 242, 148,
-			73, 53, 221, 251, 83, 253, 19, 154, 238, 253, 169, 253, 135, 52,
-			221, 251, 83, 15, 79, 210, 79, 27, 74, 249, 126, 209, 60, 93,
-			252, 132, 33, 154, 86, 4, 71, 82, 105, 156, 149, 122, 221, 85,
-			225, 175, 210, 25, 194, 163, 71, 80, 238, 208, 221, 228, 250, 91,
-			85, 49, 250, 245, 160, 14, 11, 76, 11, 128, 16, 108, 242, 50,
-			101, 139, 78, 173, 41, 111, 141, 132, 142, 195, 105, 71, 236, 244,
-			185, 211, 154, 193, 225, 75, 29, 119, 211, 241, 184, 159, 144, 57,
-			165, 255, 183, 160, 179, 84, 187, 41, 184, 216, 127, 72, 187, 41,
-			184, 120, 184, 164, 221, 20, 92, 156, 59, 69, 223, 107, 168, 171,
-			130, 167, 205, 71, 138, 81, 162, 24, 145, 225, 37, 118, 31, 164,
-			36, 140, 119, 26, 162, 170, 35, 42, 137, 69, 41, 88, 39, 193,
-			177, 240, 112, 86, 49, 86, 235, 78, 228, 70, 73, 215, 77, 11,
-			186, 64, 181, 219, 138, 167, 251, 153, 118, 91, 241, 244, 195, 115,
-			218, 109, 197, 211, 103, 206, 210, 223, 54, 212, 117, 197, 146, 249,
-			72, 241, 23, 141, 164, 221, 175, 117, 138, 146, 254, 75, 159, 161,
-			74, 201, 196, 95, 2, 86, 196, 245, 149, 11, 211, 56, 96, 89,
-			33, 250, 117, 77, 30, 110, 203, 174, 106, 212, 5, 139, 5, 99,
-			163, 218, 85, 204, 82, 50, 157, 192, 119, 47, 29, 158, 211, 174,
-			98, 150, 206, 156, 165, 159, 48, 213, 93, 76, 213, 156, 44, 254,
-			51, 147, 85, 83, 233, 89, 219, 129, 226, 114, 12, 153, 19, 205,
-			251, 73, 234, 236, 62, 65, 145, 16, 126, 168, 218, 110, 107, 201,
-			226, 117, 235, 169, 227, 5, 172, 82, 33, 73, 18, 155, 89, 56,
-			31, 125, 225, 28, 190, 196, 150, 87, 214, 168, 162, 36, 137, 172,
-			33, 42, 18, 55, 114, 98, 237, 119, 187, 104, 69, 195, 85, 56,
-			41, 229, 97, 11, 39, 165, 114, 185, 35, 118, 99, 234, 91, 70,
-			99, 22, 181, 115, 56, 104, 164, 77, 37, 104, 181, 242, 128, 158,
-			17, 237, 114, 170, 58, 122, 80, 187, 156, 170, 178, 135, 233, 167,
-			137, 186, 157, 122, 209, 60, 94, 252, 4, 97, 151, 52, 117, 2,
-			98, 210, 215, 189, 159, 136, 155, 4, 55, 100, 211, 169, 241, 110,
-			101, 161, 36, 44, 116, 103, 18, 10, 46, 125, 239, 170, 29, 15,
-			197, 225, 192, 64, 186, 39, 120, 107, 233, 84, 37, 8, 221, 151,
-			117, 213, 188, 164, 103, 98, 72, 20, 153, 184, 27, 98, 23, 222,
-			72, 240, 42, 185, 71, 248, 164, 230, 239, 134, 118, 224, 42, 243,
-			120, 96, 126, 224, 80, 219, 245, 124, 222, 121, 232, 104, 254, 56,
-			68, 127, 51, 62, 103, 4, 23, 29, 137, 115, 11, 227, 224, 172,
-			7, 113, 23, 98, 74, 52, 233, 152, 232, 242, 92, 178, 188, 210,
-			151, 2, 137, 237, 126, 29, 3, 141, 250, 117, 199, 3, 254, 86,
-			28, 178, 192, 217, 42, 43, 109, 154, 241, 30, 35, 226, 118, 166,
-			151, 135, 47, 154, 123, 180, 203, 195, 23, 199, 30, 214, 46, 15,
-			95, 60, 122, 44, 53, 81, 184, 110, 122, 186, 137, 194, 117, 58,
-			76, 255, 185, 33, 146, 125, 54, 89, 183, 236, 226, 7, 12, 169,
-			28, 174, 5, 173, 182, 19, 227, 129, 142, 155, 56, 243, 250, 10,
-			245, 60, 37, 101, 247, 188, 197, 25, 108, 227, 80, 152, 210, 212,
-			229, 29, 18, 230, 81, 239, 41, 203, 236, 114, 176, 197, 55, 121,
-			88, 18, 34, 62, 26, 247, 111, 113, 182, 178, 188, 244, 28, 10,
-			142, 25, 133, 17, 62, 109, 66, 131, 2, 16, 170, 214, 7, 135,
-			212, 45, 63, 138, 85, 153, 180, 41, 210, 42, 59, 124, 70, 207,
-			243, 226, 179, 209, 157, 54, 69, 250, 159, 146, 212, 94, 225, 166,
-			117, 176, 248, 85, 147, 93, 73, 149, 83, 176, 88, 238, 116, 205,
-			62, 5, 153, 166, 216, 180, 235, 139, 27, 247, 25, 93, 171, 64,
-			147, 71, 176, 37, 230, 54, 88, 151, 195, 188, 235, 25, 191, 57,
-			169, 11, 104, 241, 198, 205, 141, 88, 211, 21, 135, 185, 12, 146,
-			172, 199, 121, 152, 146, 143, 24, 167, 228, 21, 143, 190, 172, 19,
-			230, 95, 197, 44, 195, 24, 187, 77, 14, 71, 13, 167, 73, 128,
-			45, 156, 170, 40, 150, 5, 187, 201, 82, 26, 126, 104, 71, 183,
-			78, 149, 4, 151, 143, 23, 64, 2, 26, 52, 216, 233, 199, 174,
-			92, 200, 4, 163, 235, 26, 16, 77, 60, 64, 159, 61, 117, 229,
-			66, 41, 217, 240, 248, 148, 160, 222, 169, 137, 27, 40, 248, 166,
-			27, 125, 228, 96, 62, 178, 65, 32, 111, 246, 103, 141, 60, 110,
-			30, 120, 72, 222, 65, 227, 157, 131, 173, 221, 120, 183, 76, 253,
-			198, 187, 85, 24, 212, 110, 188, 91, 210, 153, 9, 218, 134, 4,
-			230, 215, 235, 182, 33, 1, 29, 165, 223, 42, 246, 129, 209, 103,
-			147, 208, 154, 40, 190, 122, 95, 251, 64, 42, 33, 239, 177, 19,
-			100, 174, 251, 222, 11, 142, 230, 210, 7, 13, 86, 96, 23, 132,
-			201, 170, 55, 112, 23, 100, 210, 166, 72, 171, 236, 240, 57, 89,
-			245, 6, 238, 130, 76, 218, 20, 105, 149, 29, 146, 123, 198, 146,
-			207, 120, 167, 162, 167, 229, 119, 149, 157, 216, 36, 28, 223, 151,
-			124, 134, 35, 57, 147, 54, 85, 90, 197, 25, 179, 98, 235, 61,
-			202, 246, 73, 16, 158, 120, 96, 15, 253, 148, 161, 0, 125, 54,
-			185, 149, 47, 22, 63, 250, 32, 40, 87, 122, 223, 29, 168, 167,
-			58, 238, 89, 87, 238, 251, 157, 2, 154, 238, 135, 97, 21, 243,
-			3, 38, 225, 214, 176, 178, 161, 82, 196, 168, 11, 98, 10, 72,
-			90, 8, 178, 216, 123, 180, 44, 198, 78, 136, 41, 32, 105, 33,
-			0, 160, 19, 13, 149, 5, 166, 164, 11, 34, 243, 164, 133, 136,
-			77, 110, 161, 107, 8, 149, 5, 38, 166, 11, 98, 10, 200, 51,
-			90, 120, 55, 242, 74, 126, 188, 248, 56, 171, 248, 226, 101, 124,
-			36, 125, 36, 3, 235, 42, 125, 247, 119, 137, 67, 210, 241, 184,
-			122, 214, 53, 162, 7, 94, 35, 175, 228, 51, 16, 195, 38, 175,
-			244, 143, 234, 16, 98, 147, 87, 198, 246, 170, 181, 4, 237, 127,
-			157, 53, 145, 90, 70, 229, 33, 221, 159, 177, 156, 250, 58, 116,
-			191, 145, 90, 78, 125, 221, 248, 62, 25, 53, 162, 215, 182, 222,
-			155, 6, 112, 232, 205, 99, 178, 79, 37, 49, 24, 165, 116, 124,
-			37, 92, 90, 190, 215, 64, 175, 229, 24, 51, 225, 85, 3, 85,
-			212, 42, 234, 192, 171, 70, 161, 72, 255, 36, 167, 162, 14, 124,
-			196, 48, 199, 138, 95, 202, 165, 174, 135, 148, 175, 6, 228, 205,
-			28, 207, 99, 62, 223, 210, 29, 33, 108, 57, 17, 123, 119, 208,
-			9, 125, 199, 3, 9, 51, 137, 28, 236, 109, 171, 171, 119, 205,
-			163, 151, 226, 97, 74, 26, 203, 82, 98, 55, 178, 236, 112, 6,
-			34, 179, 221, 64, 201, 150, 98, 7, 182, 184, 231, 205, 138, 135,
-			110, 130, 209, 8, 185, 10, 222, 146, 6, 73, 168, 215, 129, 46,
-			175, 129, 172, 136, 196, 119, 10, 131, 16, 117, 28, 207, 219, 158,
-			146, 231, 149, 83, 71, 195, 130, 77, 215, 209, 223, 83, 78, 103,
-			31, 84, 206, 72, 255, 19, 146, 19, 218, 134, 214, 82, 185, 179,
-			233, 108, 202, 112, 137, 149, 5, 124, 223, 236, 137, 224, 178, 138,
-			83, 86, 202, 32, 121, 186, 104, 124, 26, 190, 133, 14, 113, 137,
-			233, 106, 39, 148, 107, 5, 247, 157, 200, 243, 0, 73, 24, 39,
-			215, 167, 26, 22, 99, 124, 117, 175, 196, 51, 121, 200, 0, 123,
-			46, 250, 112, 67, 236, 229, 27, 169, 48, 178, 176, 188, 200, 26,
-			158, 179, 33, 31, 205, 99, 167, 186, 176, 143, 145, 152, 229, 35,
-			184, 105, 249, 30, 63, 17, 88, 74, 108, 221, 169, 203, 171, 249,
-			146, 136, 6, 46, 159, 77, 113, 237, 29, 57, 186, 197, 20, 92,
-			40, 244, 34, 123, 101, 115, 3, 143, 75, 205, 254, 64, 125, 142,
-			132, 113, 77, 157, 102, 86, 81, 73, 147, 29, 64, 8, 17, 103,
-			62, 12, 59, 4, 118, 54, 228, 245, 157, 35, 216, 74, 142, 122,
-			170, 125, 116, 235, 209, 141, 76, 72, 139, 143, 168, 64, 35, 194,
-			45, 210, 71, 140, 94, 61, 164, 197, 71, 12, 123, 15, 253, 5,
-			67, 133, 180, 248, 152, 97, 30, 43, 254, 184, 145, 40, 17, 211,
-			161, 118, 89, 164, 37, 178, 74, 89, 169, 249, 18, 70, 88, 201,
-			198, 148, 173, 111, 107, 194, 32, 234, 201, 92, 25, 188, 66, 134,
-			139, 172, 196, 145, 18, 59, 221, 136, 109, 100, 130, 128, 160, 229,
-			133, 88, 118, 105, 112, 141, 151, 132, 120, 36, 28, 22, 132, 92,
-			104, 130, 252, 64, 249, 115, 72, 162, 69, 88, 56, 148, 36, 153,
-			135, 100, 255, 184, 22, 60, 226, 99, 198, 62, 166, 5, 143, 248,
-			152, 113, 228, 40, 253, 131, 36, 120, 196, 183, 25, 230, 116, 241,
-			87, 13, 166, 99, 245, 129, 48, 145, 206, 182, 142, 140, 236, 12,
-			254, 253, 97, 37, 91, 239, 189, 209, 99, 90, 56, 68, 61, 66,
-			197, 183, 165, 232, 129, 117, 240, 109, 198, 190, 35, 90, 132, 138,
-			111, 51, 142, 79, 209, 143, 8, 244, 16, 219, 250, 78, 88, 37,
-			239, 211, 208, 35, 92, 119, 186, 73, 160, 10, 17, 183, 100, 71,
-			55, 18, 77, 185, 232, 143, 10, 42, 66, 239, 56, 20, 12, 133,
-			48, 171, 135, 123, 17, 62, 28, 187, 198, 67, 44, 236, 83, 146,
-			204, 65, 178, 127, 84, 37, 13, 72, 218, 106, 186, 9, 14, 224,
-			200, 81, 250, 169, 60, 142, 199, 178, 173, 207, 26, 102, 177, 248,
-			255, 207, 43, 191, 22, 34, 230, 70, 214, 15, 10, 107, 243, 48,
-			121, 175, 26, 232, 226, 98, 73, 127, 202, 234, 248, 219, 202, 219,
-			135, 240, 184, 46, 116, 18, 82, 85, 41, 110, 75, 240, 125, 66,
-			44, 227, 146, 40, 242, 80, 115, 60, 175, 204, 230, 253, 109, 60,
-			121, 160, 69, 121, 159, 137, 14, 73, 235, 210, 77, 77, 218, 39,
-			81, 251, 180, 58, 192, 206, 159, 135, 227, 107, 70, 58, 184, 104,
-			183, 185, 19, 226, 234, 164, 236, 198, 194, 242, 162, 248, 10, 100,
-			65, 69, 63, 199, 51, 77, 56, 195, 216, 114, 182, 163, 172, 127,
-			31, 212, 239, 110, 43, 157, 164, 208, 39, 9, 85, 137, 12, 56,
-			151, 52, 138, 193, 97, 74, 73, 192, 23, 215, 143, 218, 226, 114,
-			209, 141, 196, 45, 143, 112, 213, 1, 231, 234, 182, 188, 144, 145,
-			181, 162, 247, 250, 160, 35, 186, 50, 195, 90, 32, 88, 7, 126,
-			250, 156, 86, 59, 68, 132, 46, 69, 30, 28, 32, 53, 139, 43,
-			11, 113, 124, 164, 97, 116, 186, 6, 42, 156, 182, 123, 81, 208,
-			109, 20, 39, 34, 41, 239, 116, 44, 207, 28, 129, 84, 143, 71,
-			17, 149, 182, 165, 179, 137, 207, 38, 12, 199, 38, 135, 144, 168,
-			158, 82, 39, 51, 211, 24, 20, 70, 93, 54, 236, 162, 219, 149,
-			238, 125, 102, 164, 180, 15, 127, 114, 217, 48, 17, 38, 73, 197,
-			179, 16, 222, 248, 0, 205, 138, 183, 205, 232, 167, 113, 61, 192,
-			32, 229, 129, 4, 127, 73, 160, 159, 29, 4, 74, 139, 17, 144,
-			186, 137, 77, 113, 237, 102, 244, 30, 162, 178, 140, 9, 101, 26,
-			127, 199, 202, 227, 54, 25, 82, 73, 3, 146, 195, 123, 85, 146,
-			64, 114, 98, 63, 253, 44, 193, 61, 149, 179, 173, 159, 52, 204,
-			125, 197, 79, 18, 12, 207, 116, 35, 115, 251, 114, 67, 184, 75,
-			80, 65, 11, 102, 216, 106, 98, 139, 160, 217, 63, 106, 222, 139,
-			101, 239, 112, 39, 104, 190, 34, 23, 174, 164, 174, 103, 181, 248,
-			145, 202, 207, 182, 23, 179, 233, 52, 174, 167, 188, 231, 224, 2,
-			107, 74, 151, 186, 37, 85, 85, 226, 114, 39, 98, 29, 127, 221,
-			11, 106, 55, 121, 125, 166, 172, 171, 182, 18, 124, 251, 217, 198,
-			166, 34, 138, 90, 33, 233, 234, 84, 45, 184, 144, 111, 6, 55,
-			37, 219, 38, 159, 224, 51, 47, 240, 55, 120, 200, 182, 130, 240,
-			38, 110, 176, 70, 71, 49, 99, 184, 245, 35, 197, 166, 236, 130,
-			41, 141, 43, 202, 168, 169, 18, 33, 200, 141, 152, 220, 136, 202,
-			179, 44, 77, 209, 151, 98, 6, 29, 24, 5, 126, 236, 250, 157,
-			4, 140, 78, 136, 196, 28, 230, 196, 164, 41, 94, 33, 103, 64,
-			178, 215, 86, 73, 2, 201, 189, 227, 137, 125, 221, 207, 231, 233,
-			19, 247, 105, 158, 38, 36, 14, 197, 228, 254, 125, 184, 152, 121,
-			23, 29, 201, 248, 252, 120, 16, 247, 50, 147, 212, 130, 154, 228,
-			203, 61, 52, 66, 75, 35, 65, 85, 241, 219, 131, 153, 196, 252,
-			168, 37, 30, 233, 141, 253, 99, 181, 136, 209, 61, 203, 92, 20,
-			182, 47, 131, 61, 99, 70, 241, 77, 172, 123, 18, 82, 205, 154,
-			112, 252, 153, 198, 188, 72, 195, 100, 107, 47, 240, 6, 11, 19,
-			116, 159, 50, 154, 25, 54, 15, 22, 169, 210, 189, 214, 117, 247,
-			13, 195, 25, 247, 13, 195, 25, 247, 13, 195, 7, 18, 175, 19,
-			134, 77, 246, 152, 227, 197, 219, 122, 180, 13, 60, 232, 18, 123,
-			233, 52, 232, 6, 156, 48, 64, 18, 213, 233, 130, 82, 140, 138,
-			93, 7, 91, 183, 129, 170, 134, 196, 243, 88, 146, 43, 13, 153,
-			39, 136, 143, 116, 26, 38, 149, 201, 169, 25, 74, 30, 58, 51,
-			160, 153, 161, 236, 25, 28, 213, 204, 80, 246, 140, 237, 77, 118,
-			210, 55, 205, 210, 55, 63, 208, 70, 16, 161, 59, 210, 109, 244,
-			122, 204, 68, 63, 148, 167, 20, 69, 191, 183, 67, 101, 246, 25,
-			58, 160, 180, 152, 32, 88, 201, 77, 180, 211, 108, 209, 73, 19,
-			246, 91, 233, 96, 162, 249, 116, 252, 13, 46, 205, 224, 14, 36,
-			102, 104, 88, 117, 114, 124, 65, 150, 170, 106, 5, 83, 248, 134,
-			153, 59, 97, 173, 41, 109, 226, 246, 118, 21, 93, 197, 143, 85,
-			153, 169, 248, 12, 29, 208, 43, 179, 199, 82, 123, 82, 124, 162,
-			46, 236, 71, 71, 40, 241, 130, 45, 220, 222, 131, 85, 248, 105,
-			219, 212, 106, 186, 27, 77, 105, 166, 136, 191, 139, 31, 178, 104,
-			94, 84, 111, 63, 66, 243, 245, 160, 229, 184, 62, 214, 51, 36,
-			204, 40, 119, 244, 162, 188, 128, 121, 170, 50, 175, 61, 69, 115,
-			232, 241, 71, 122, 57, 24, 133, 66, 87, 195, 0, 216, 196, 109,
-			249, 252, 23, 191, 219, 71, 40, 225, 126, 93, 90, 59, 238, 146,
-			13, 190, 218, 43, 116, 8, 213, 193, 183, 174, 55, 92, 47, 230,
-			97, 52, 145, 67, 140, 76, 239, 222, 151, 121, 204, 123, 73, 100,
-			21, 79, 151, 7, 29, 29, 102, 47, 209, 65, 116, 224, 146, 212,
-			151, 151, 47, 218, 119, 173, 111, 17, 178, 102, 170, 27, 224, 26,
-			168, 248, 78, 106, 239, 108, 114, 151, 103, 209, 165, 236, 179, 232,
-			113, 104, 237, 74, 199, 139, 221, 46, 204, 164, 175, 198, 171, 116,
-			116, 71, 227, 187, 84, 60, 149, 173, 120, 55, 108, 167, 207, 197,
-			25, 205, 139, 201, 178, 251, 104, 238, 237, 215, 22, 87, 215, 70,
-			122, 236, 126, 218, 59, 191, 182, 182, 120, 229, 234, 218, 136, 33,
-			76, 67, 171, 189, 81, 16, 198, 215, 215, 183, 31, 140, 220, 255,
-			234, 49, 97, 1, 249, 218, 63, 90, 11, 200, 39, 53, 122, 255,
-			65, 3, 9, 126, 110, 8, 198, 91, 124, 15, 75, 215, 78, 246,
-			121, 151, 124, 139, 37, 130, 40, 36, 142, 16, 133, 148, 18, 52,
-			208, 28, 44, 229, 182, 183, 133, 16, 83, 166, 172, 18, 79, 65,
-			105, 69, 245, 83, 43, 55, 36, 218, 25, 197, 176, 254, 112, 219,
-			166, 159, 79, 60, 13, 217, 230, 100, 241, 39, 13, 166, 145, 169,
-			46, 91, 51, 97, 157, 225, 115, 166, 130, 95, 37, 79, 201, 147,
-			27, 59, 39, 210, 46, 73, 168, 118, 191, 26, 110, 11, 61, 142,
-			212, 99, 72, 150, 61, 210, 205, 86, 84, 16, 252, 83, 40, 206,
-			170, 160, 157, 34, 104, 164, 80, 10, 78, 57, 186, 157, 81, 114,
-			26, 97, 149, 83, 25, 71, 69, 182, 57, 162, 157, 116, 182, 188,
-			191, 21, 39, 157, 205, 30, 22, 207, 213, 73, 143, 109, 141, 153,
-			19, 242, 185, 58, 234, 219, 199, 232, 56, 170, 92, 229, 251, 168,
-			189, 150, 120, 225, 169, 158, 56, 237, 149, 87, 46, 234, 129, 211,
-			222, 254, 145, 52, 45, 159, 118, 171, 226, 134, 77, 198, 173, 61,
-			201, 103, 3, 159, 119, 167, 197, 13, 124, 224, 61, 148, 166, 137,
-			77, 198, 71, 237, 164, 184, 105, 147, 125, 214, 88, 242, 217, 204,
-			65, 58, 45, 14, 213, 239, 147, 207, 191, 212, 195, 160, 125, 246,
-			30, 250, 254, 196, 130, 245, 160, 121, 162, 248, 127, 25, 44, 115,
-			178, 236, 54, 161, 14, 19, 159, 116, 211, 7, 215, 207, 172, 68,
-			52, 93, 240, 130, 173, 228, 22, 255, 41, 188, 235, 242, 235, 12,
-			142, 0, 13, 234, 5, 91, 210, 21, 40, 86, 233, 70, 236, 5,
-			47, 216, 42, 97, 182, 153, 50, 187, 140, 185, 157, 109, 10, 185,
-			1, 134, 91, 81, 122, 129, 196, 52, 244, 71, 116, 66, 212, 143,
-			141, 10, 206, 192, 11, 182, 244, 236, 144, 4, 97, 70, 45, 158,
-			105, 117, 211, 127, 106, 38, 101, 30, 44, 64, 131, 206, 74, 28,
-			236, 223, 167, 177, 18, 7, 39, 142, 105, 172, 196, 193, 233, 25,
-			250, 47, 250, 112, 97, 24, 118, 238, 105, 243, 3, 6, 41, 190,
-			214, 199, 230, 153, 160, 237, 93, 184, 19, 27, 84, 169, 254, 69,
-			32, 147, 182, 32, 164, 32, 3, 139, 231, 78, 169, 218, 146, 166,
-			210, 135, 60, 72, 202, 76, 146, 106, 124, 106, 156, 188, 76, 20,
-			65, 119, 235, 65, 60, 91, 231, 50, 246, 60, 107, 59, 113, 179,
-			204, 46, 5, 120, 103, 227, 180, 218, 30, 47, 177, 200, 217, 150,
-			122, 13, 142, 42, 216, 172, 133, 134, 236, 215, 57, 10, 178, 40,
-			202, 205, 211, 110, 253, 124, 157, 59, 245, 117, 206, 27, 51, 231,
-			164, 224, 44, 109, 195, 206, 179, 39, 147, 208, 174, 79, 49, 118,
-			4, 200, 185, 20, 98, 19, 19, 172, 178, 230, 109, 235, 186, 176,
-			235, 69, 167, 33, 236, 188, 120, 159, 181, 35, 255, 187, 163, 192,
-			191, 46, 67, 173, 179, 243, 236, 21, 145, 129, 177, 201, 155, 124,
-			123, 242, 28, 155, 20, 14, 149, 74, 9, 24, 93, 240, 78, 158,
-			99, 47, 76, 70, 65, 139, 79, 150, 216, 233, 83, 37, 153, 43,
-			154, 44, 161, 232, 248, 98, 154, 59, 234, 172, 67, 222, 87, 38,
-			91, 209, 198, 228, 57, 118, 250, 244, 237, 18, 75, 18, 103, 110,
-			171, 156, 183, 17, 1, 146, 164, 233, 40, 120, 207, 233, 251, 71,
-			66, 38, 28, 203, 249, 196, 62, 78, 124, 84, 183, 64, 101, 140,
-			86, 43, 108, 48, 50, 85, 117, 101, 67, 180, 72, 166, 90, 199,
-			74, 24, 121, 49, 160, 101, 27, 70, 155, 64, 131, 155, 147, 231,
-			132, 212, 156, 142, 103, 77, 153, 189, 252, 191, 228, 93, 77, 108,
-			28, 199, 114, 222, 153, 30, 174, 200, 230, 127, 147, 92, 138, 35,
-			82, 28, 209, 118, 150, 178, 201, 149, 72, 217, 142, 67, 195, 134,
-			201, 80, 178, 104, 83, 127, 75, 33, 182, 34, 211, 246, 112, 103,
-			72, 78, 180, 187, 67, 205, 236, 138, 162, 1, 7, 62, 56, 10,
-			224, 24, 57, 68, 70, 130, 32, 200, 33, 199, 28, 2, 248, 152,
-			163, 129, 24, 72, 206, 14, 2, 159, 114, 200, 41, 151, 7, 248,
-			240, 142, 15, 15, 120, 168, 170, 238, 233, 158, 37, 41, 211, 18,
-			252, 14, 126, 183, 237, 158, 237, 153, 238, 158, 154, 238, 234, 250,
-			234, 171, 162, 28, 73, 36, 136, 179, 81, 211, 219, 75, 195, 118,
-			16, 207, 163, 94, 74, 163, 35, 21, 107, 73, 77, 0, 84, 229,
-			181, 163, 37, 213, 131, 25, 115, 144, 248, 22, 212, 48, 103, 212,
-			92, 206, 60, 79, 75, 193, 49, 239, 184, 146, 189, 64, 58, 229,
-			47, 92, 60, 105, 195, 180, 189, 85, 161, 55, 119, 119, 97, 33,
-			215, 240, 168, 89, 171, 224, 156, 220, 213, 242, 0, 115, 114, 35,
-			33, 81, 63, 98, 192, 57, 237, 77, 143, 247, 36, 131, 185, 187,
-			176, 137, 157, 250, 41, 35, 185, 123, 113, 83, 15, 70, 119, 112,
-			61, 106, 133, 137, 95, 247, 202, 21, 138, 52, 89, 190, 91, 246,
-			106, 187, 126, 226, 215, 112, 9, 144, 107, 92, 152, 214, 252, 61,
-			101, 15, 247, 189, 45, 191, 118, 47, 173, 251, 152, 136, 149, 246,
-			40, 88, 181, 222, 230, 67, 136, 25, 23, 152, 5, 39, 200, 171,
-			206, 187, 93, 114, 27, 176, 112, 87, 191, 218, 51, 136, 104, 39,
-			150, 97, 23, 91, 43, 18, 244, 42, 43, 44, 168, 233, 53, 107,
-			108, 193, 214, 6, 204, 70, 150, 96, 239, 20, 133, 241, 23, 11,
-			107, 250, 205, 26, 91, 176, 119, 134, 134, 249, 127, 217, 212, 21,
-			120, 80, 213, 41, 185, 255, 110, 123, 164, 51, 26, 38, 40, 178,
-			124, 214, 234, 126, 138, 118, 125, 181, 104, 234, 244, 137, 146, 239,
-			156, 122, 173, 152, 246, 15, 202, 208, 203, 61, 255, 129, 31, 213,
-			85, 114, 32, 249, 215, 36, 204, 156, 6, 149, 141, 19, 142, 150,
-			217, 9, 180, 121, 216, 116, 200, 141, 88, 227, 10, 217, 230, 220,
-			91, 150, 110, 127, 24, 89, 248, 227, 101, 133, 29, 146, 187, 54,
-			42, 55, 152, 121, 3, 238, 250, 188, 140, 155, 137, 235, 124, 218,
-			222, 210, 41, 132, 57, 133, 173, 150, 172, 227, 206, 136, 143, 251,
-			106, 153, 246, 61, 58, 124, 209, 222, 42, 173, 199, 52, 81, 251,
-			113, 114, 47, 173, 168, 189, 157, 192, 221, 170, 99, 148, 45, 193,
-			170, 189, 195, 186, 204, 4, 171, 142, 142, 241, 255, 179, 72, 38,
-			184, 96, 239, 57, 227, 238, 119, 150, 183, 72, 231, 111, 210, 136,
-			101, 158, 40, 212, 204, 113, 247, 64, 240, 62, 124, 16, 38, 7,
-			218, 95, 10, 255, 0, 243, 56, 35, 215, 193, 25, 73, 186, 141,
-			178, 56, 222, 166, 11, 180, 116, 25, 200, 236, 102, 23, 226, 68,
-			89, 8, 228, 55, 144, 230, 99, 211, 243, 44, 214, 33, 194, 161,
-			160, 82, 135, 245, 176, 6, 170, 37, 70, 16, 111, 133, 216, 131,
-			121, 36, 224, 102, 142, 102, 141, 52, 172, 63, 8, 83, 233, 216,
-			1, 67, 44, 8, 246, 94, 127, 73, 125, 5, 61, 130, 189, 239,
-			12, 170, 139, 61, 5, 193, 222, 239, 87, 170, 20, 121, 125, 228,
-			202, 54, 149, 191, 183, 164, 168, 90, 130, 109, 58, 211, 238, 127,
-			90, 222, 6, 156, 44, 241, 131, 188, 44, 161, 225, 120, 143, 36,
-			34, 139, 35, 66, 241, 199, 229, 152, 162, 36, 109, 209, 148, 201,
-			189, 254, 64, 238, 203, 77, 80, 115, 90, 187, 97, 26, 226, 93,
-			254, 162, 141, 238, 111, 135, 239, 80, 150, 211, 92, 54, 146, 169,
-			195, 160, 9, 239, 49, 92, 23, 61, 157, 66, 107, 78, 42, 252,
-			184, 177, 211, 109, 72, 37, 161, 15, 205, 144, 28, 80, 113, 54,
-			51, 173, 145, 156, 122, 55, 199, 92, 93, 102, 130, 109, 78, 157,
-			85, 19, 7, 74, 230, 135, 206, 84, 118, 217, 46, 66, 89, 55,
-			135, 137, 250, 112, 236, 180, 46, 51, 193, 62, 60, 51, 201, 255,
-			223, 145, 237, 153, 96, 137, 179, 228, 126, 239, 120, 185, 83, 109,
-			135, 170, 68, 107, 47, 116, 189, 76, 187, 79, 212, 240, 91, 97,
-			89, 126, 228, 21, 217, 22, 43, 115, 185, 185, 97, 160, 176, 188,
-			162, 254, 163, 80, 27, 84, 8, 230, 60, 133, 122, 248, 77, 88,
-			17, 18, 159, 88, 62, 184, 40, 167, 157, 170, 82, 180, 77, 75,
-			141, 178, 200, 123, 245, 24, 205, 202, 20, 100, 29, 86, 104, 181,
-			41, 160, 230, 1, 155, 31, 104, 198, 51, 160, 81, 196, 219, 88,
-			134, 5, 102, 102, 206, 155, 241, 155, 240, 129, 204, 164, 173, 246,
-			246, 246, 204, 230, 167, 122, 125, 191, 173, 108, 218, 134, 151, 172,
-			30, 150, 210, 249, 164, 115, 25, 42, 135, 184, 65, 211, 19, 189,
-			55, 212, 35, 55, 179, 202, 74, 188, 77, 245, 248, 232, 35, 234,
-			161, 43, 71, 84, 203, 174, 29, 119, 65, 142, 225, 199, 174, 207,
-			121, 234, 185, 188, 211, 235, 22, 141, 238, 56, 28, 4, 126, 228,
-			156, 166, 89, 162, 133, 80, 6, 201, 136, 183, 13, 170, 21, 167,
-			101, 143, 78, 144, 9, 188, 43, 252, 25, 97, 154, 14, 244, 5,
-			198, 67, 159, 202, 0, 136, 81, 40, 18, 67, 176, 89, 17, 36,
-			237, 143, 116, 217, 18, 44, 41, 191, 162, 203, 32, 137, 175, 253,
-			9, 255, 76, 73, 166, 35, 156, 207, 45, 231, 101, 247, 7, 230,
-			153, 102, 145, 227, 37, 19, 215, 108, 45, 147, 216, 168, 67, 24,
-			249, 177, 210, 72, 110, 63, 248, 210, 143, 146, 69, 37, 138, 74,
-			18, 249, 239, 91, 20, 67, 57, 154, 39, 8, 225, 221, 139, 155,
-			32, 7, 244, 56, 93, 187, 176, 89, 137, 183, 213, 53, 124, 116,
-			231, 181, 5, 186, 6, 221, 233, 188, 180, 72, 151, 168, 139, 63,
-			175, 36, 145, 196, 168, 164, 214, 5, 153, 134, 248, 115, 203, 57,
-			167, 43, 44, 168, 152, 185, 160, 43, 24, 84, 44, 94, 34, 107,
-			128, 109, 11, 231, 145, 101, 79, 33, 78, 83, 64, 56, 251, 145,
-			130, 194, 145, 0, 232, 60, 82, 80, 56, 165, 116, 122, 100, 137,
-			211, 170, 200, 160, 120, 102, 50, 51, 69, 127, 187, 196, 79, 138,
-			201, 236, 251, 245, 123, 20, 50, 193, 176, 68, 159, 237, 140, 189,
-			27, 72, 134, 231, 179, 70, 66, 120, 106, 3, 249, 83, 25, 199,
-			255, 177, 155, 247, 153, 182, 167, 19, 99, 75, 20, 225, 32, 57,
-			48, 193, 37, 109, 49, 171, 210, 69, 113, 158, 59, 141, 56, 8,
-			165, 229, 24, 141, 222, 249, 220, 23, 113, 16, 86, 241, 47, 98,
-			78, 49, 252, 29, 109, 80, 61, 236, 169, 173, 184, 253, 139, 154,
-			219, 223, 37, 99, 54, 116, 254, 191, 147, 213, 15, 109, 194, 135,
-			212, 166, 120, 76, 155, 203, 15, 101, 27, 249, 71, 247, 111, 44,
-			238, 64, 39, 49, 196, 233, 118, 42, 201, 241, 240, 83, 188, 193,
-			123, 136, 63, 21, 197, 20, 58, 118, 96, 113, 250, 200, 1, 86,
-			86, 213, 223, 170, 186, 197, 204, 34, 239, 201, 234, 69, 31, 239,
-			190, 114, 163, 250, 222, 114, 117, 117, 99, 168, 32, 250, 121, 207,
-			202, 242, 159, 190, 75, 69, 75, 116, 115, 103, 229, 198, 237, 171,
-			67, 182, 251, 151, 42, 46, 193, 25, 222, 131, 110, 230, 225, 158,
-			124, 85, 172, 218, 221, 240, 31, 174, 66, 89, 188, 204, 225, 247,
-			71, 160, 190, 200, 183, 51, 113, 40, 122, 242, 170, 148, 214, 234,
-			169, 6, 165, 31, 57, 73, 168, 3, 247, 159, 152, 14, 111, 240,
-			170, 9, 73, 244, 46, 122, 199, 205, 127, 22, 214, 64, 130, 22,
-			75, 58, 44, 130, 125, 194, 150, 170, 129, 120, 147, 247, 232, 208,
-			17, 236, 132, 173, 117, 19, 241, 2, 31, 104, 182, 27, 26, 117,
-			78, 81, 216, 250, 171, 253, 205, 118, 67, 199, 31, 23, 19, 188,
-			123, 123, 63, 128, 217, 165, 168, 22, 221, 213, 83, 219, 148, 179,
-			25, 38, 30, 206, 124, 116, 141, 2, 12, 116, 111, 201, 180, 201,
-			238, 167, 58, 94, 195, 16, 103, 81, 144, 137, 75, 20, 164, 66,
-			24, 96, 108, 55, 129, 175, 199, 69, 117, 192, 112, 12, 50, 175,
-			32, 197, 220, 174, 102, 101, 113, 26, 164, 120, 47, 74, 194, 64,
-			245, 77, 22, 221, 235, 252, 148, 148, 95, 184, 49, 121, 168, 97,
-			0, 146, 158, 170, 44, 137, 151, 120, 119, 22, 175, 195, 62, 26,
-			248, 202, 254, 240, 211, 176, 130, 95, 93, 32, 172, 224, 171, 95,
-			44, 86, 48, 171, 162, 37, 112, 29, 45, 161, 183, 176, 130, 63,
-			153, 96, 125, 25, 152, 48, 80, 232, 229, 223, 217, 4, 38, 140,
-			195, 132, 184, 223, 218, 57, 3, 127, 135, 142, 3, 251, 139, 102,
-			132, 43, 211, 253, 45, 229, 69, 154, 196, 237, 157, 93, 114, 157,
-			201, 220, 57, 202, 120, 16, 219, 247, 147, 32, 231, 216, 83, 225,
-			50, 21, 216, 174, 223, 12, 234, 97, 34, 9, 153, 160, 3, 33,
-			101, 85, 251, 104, 202, 68, 78, 115, 218, 59, 2, 79, 117, 48,
-			49, 176, 147, 215, 235, 97, 189, 194, 73, 51, 242, 107, 58, 22,
-			191, 34, 85, 195, 225, 138, 152, 15, 242, 128, 143, 203, 189, 166,
-			70, 220, 111, 135, 237, 208, 243, 113, 104, 92, 167, 109, 208, 4,
-			143, 102, 28, 132, 115, 232, 78, 11, 43, 160, 116, 38, 138, 165,
-			107, 123, 26, 182, 188, 217, 108, 125, 147, 110, 169, 6, 42, 50,
-			222, 61, 202, 87, 21, 40, 50, 97, 79, 185, 127, 236, 221, 144,
-			135, 194, 138, 183, 17, 134, 199, 248, 19, 109, 211, 81, 56, 59,
-			241, 229, 240, 136, 137, 28, 242, 62, 145, 67, 222, 39, 206, 76,
-			242, 127, 97, 202, 108, 127, 206, 30, 119, 31, 51, 143, 144, 33,
-			29, 236, 32, 199, 141, 77, 200, 84, 66, 153, 82, 12, 95, 182,
-			86, 226, 63, 8, 147, 212, 175, 123, 50, 205, 5, 55, 170, 112,
-			230, 226, 90, 173, 157, 32, 139, 204, 107, 55, 243, 12, 56, 4,
-			162, 208, 255, 169, 226, 85, 195, 160, 221, 12, 252, 102, 203, 200,
-			190, 164, 147, 168, 52, 99, 144, 119, 36, 96, 100, 6, 20, 111,
-			55, 244, 31, 28, 160, 41, 227, 117, 178, 49, 200, 62, 193, 171,
-			144, 190, 90, 24, 136, 43, 174, 133, 105, 138, 4, 111, 191, 70,
-			249, 238, 106, 248, 170, 118, 252, 36, 168, 135, 100, 32, 218, 69,
-			171, 127, 243, 128, 206, 200, 240, 218, 201, 19, 47, 205, 56, 202,
-			29, 253, 213, 36, 5, 217, 241, 218, 129, 65, 35, 196, 233, 194,
-			158, 103, 105, 211, 137, 78, 151, 32, 227, 154, 18, 118, 96, 70,
-			150, 0, 115, 195, 129, 220, 227, 71, 18, 53, 41, 34, 30, 17,
-			222, 52, 138, 112, 46, 231, 144, 112, 78, 198, 160, 36, 20, 225,
-			220, 88, 73, 163, 75, 207, 217, 139, 38, 186, 244, 28, 31, 224,
-			255, 102, 107, 120, 105, 214, 25, 118, 255, 217, 246, 86, 175, 108,
-			144, 191, 199, 254, 110, 216, 34, 76, 36, 146, 116, 76, 220, 114,
-			231, 201, 236, 48, 27, 165, 187, 231, 61, 228, 189, 175, 36, 161,
-			31, 116, 92, 64, 3, 36, 247, 54, 162, 102, 45, 148, 8, 137,
-			31, 24, 31, 7, 50, 85, 235, 173, 104, 190, 181, 11, 173, 85,
-			130, 28, 105, 149, 34, 77, 59, 74, 189, 45, 68, 85, 194, 237,
-			237, 56, 145, 12, 41, 114, 111, 172, 145, 55, 60, 114, 169, 226,
-			70, 232, 237, 30, 108, 37, 81, 224, 109, 133, 173, 253, 48, 108,
-			226, 24, 96, 254, 86, 174, 108, 72, 158, 102, 26, 182, 90, 104,
-			122, 171, 197, 205, 86, 18, 215, 9, 235, 219, 138, 252, 212, 203,
-			212, 20, 37, 126, 242, 102, 208, 99, 60, 68, 213, 119, 226, 36,
-			106, 237, 54, 42, 60, 7, 191, 205, 58, 221, 57, 248, 109, 182,
-			167, 47, 7, 191, 205, 14, 14, 241, 26, 77, 175, 83, 16, 206,
-			156, 115, 177, 203, 221, 240, 50, 61, 168, 211, 41, 46, 215, 141,
-			156, 7, 99, 167, 207, 92, 70, 116, 133, 21, 71, 119, 10, 151,
-			139, 185, 30, 33, 45, 167, 5, 90, 50, 230, 139, 35, 210, 78,
-			90, 144, 223, 251, 124, 113, 192, 172, 177, 5, 155, 31, 54, 27,
-			89, 130, 85, 138, 163, 198, 95, 44, 172, 25, 52, 107, 108, 193,
-			42, 146, 251, 66, 53, 182, 96, 23, 114, 127, 129, 219, 92, 144,
-			180, 18, 89, 3, 255, 145, 116, 39, 9, 73, 46, 56, 147, 26,
-			114, 44, 66, 185, 63, 7, 73, 46, 12, 140, 231, 32, 201, 5,
-			247, 140, 142, 168, 125, 41, 67, 85, 237, 34, 148, 138, 70, 60,
-			148, 75, 167, 122, 141, 120, 40, 151, 6, 6, 229, 87, 96, 9,
-			231, 21, 251, 26, 51, 236, 215, 175, 240, 65, 254, 141, 165, 173,
-			198, 75, 206, 105, 247, 107, 11, 121, 133, 32, 237, 218, 245, 73,
-			226, 193, 38, 48, 137, 137, 246, 112, 69, 11, 95, 247, 46, 42,
-			88, 56, 106, 52, 194, 32, 242, 91, 97, 153, 123, 179, 205, 56,
-			247, 46, 207, 207, 121, 243, 11, 234, 143, 205, 152, 92, 55, 203,
-			132, 46, 190, 121, 81, 145, 158, 27, 17, 165, 187, 66, 183, 225,
-			29, 191, 21, 61, 144, 103, 123, 248, 30, 162, 32, 76, 225, 38,
-			68, 235, 69, 151, 105, 211, 90, 219, 5, 67, 232, 201, 89, 107,
-			151, 248, 72, 206, 90, 187, 84, 26, 231, 255, 109, 107, 235, 227,
-			138, 243, 162, 251, 31, 72, 165, 4, 229, 248, 73, 52, 74, 116,
-			109, 206, 196, 145, 150, 61, 185, 136, 194, 233, 87, 138, 37, 6,
-			43, 246, 150, 247, 246, 234, 106, 161, 86, 186, 77, 16, 250, 65,
-			61, 106, 162, 98, 83, 222, 66, 255, 89, 252, 180, 203, 115, 210,
-			42, 175, 232, 54, 161, 202, 73, 216, 240, 15, 8, 145, 244, 189,
-			173, 168, 165, 252, 45, 37, 238, 26, 165, 216, 35, 178, 188, 41,
-			150, 164, 145, 74, 71, 166, 205, 146, 25, 141, 178, 3, 255, 17,
-			73, 255, 118, 146, 189, 90, 118, 175, 93, 88, 144, 18, 213, 37,
-			201, 119, 110, 121, 190, 183, 235, 39, 1, 215, 131, 80, 60, 100,
-			229, 225, 159, 183, 124, 174, 100, 178, 77, 150, 207, 149, 169, 23,
-			114, 150, 207, 149, 217, 243, 252, 27, 166, 77, 159, 235, 206, 148,
-			251, 53, 251, 57, 9, 173, 196, 254, 8, 48, 109, 107, 39, 201,
-			149, 106, 201, 134, 206, 143, 163, 192, 34, 89, 233, 201, 28, 88,
-			218, 16, 255, 192, 56, 176, 5, 74, 206, 207, 214, 13, 152, 4,
-			62, 172, 245, 222, 188, 181, 122, 93, 114, 96, 49, 78, 234, 117,
-			91, 109, 212, 172, 8, 165, 83, 70, 100, 255, 235, 146, 3, 75,
-			177, 81, 175, 35, 233, 19, 150, 47, 91, 116, 221, 180, 255, 218,
-			82, 235, 23, 60, 227, 38, 31, 150, 248, 27, 134, 85, 190, 229,
-			236, 41, 252, 141, 34, 38, 223, 234, 27, 225, 63, 88, 184, 78,
-			219, 42, 204, 238, 136, 251, 191, 150, 119, 37, 170, 203, 93, 176,
-			28, 5, 101, 157, 239, 205, 112, 144, 214, 238, 199, 106, 252, 218,
-			33, 50, 151, 76, 51, 76, 194, 114, 234, 133, 77, 212, 222, 13,
-			61, 5, 119, 219, 240, 161, 220, 172, 145, 58, 144, 68, 20, 248,
-			56, 13, 189, 40, 72, 185, 130, 16, 84, 6, 180, 40, 64, 151,
-			108, 186, 81, 118, 144, 1, 21, 31, 219, 103, 97, 147, 165, 198,
-			36, 85, 115, 78, 10, 61, 136, 211, 65, 220, 174, 168, 93, 199,
-			206, 98, 1, 231, 106, 44, 193, 238, 244, 14, 152, 53, 76, 176,
-			59, 24, 236, 90, 77, 147, 37, 216, 7, 197, 81, 119, 193, 32,
-			88, 154, 27, 112, 7, 183, 114, 53, 243, 37, 53, 159, 99, 117,
-			193, 77, 114, 53, 112, 219, 222, 65, 179, 134, 9, 246, 129, 24,
-			225, 255, 202, 178, 71, 219, 130, 69, 197, 146, 251, 15, 236, 233,
-			201, 157, 42, 2, 143, 236, 46, 249, 47, 153, 177, 125, 230, 140,
-			245, 187, 30, 239, 68, 53, 169, 143, 55, 235, 7, 230, 125, 179,
-			148, 176, 50, 147, 172, 225, 33, 159, 249, 218, 211, 238, 134, 136,
-			18, 172, 1, 72, 70, 220, 143, 224, 237, 102, 82, 195, 189, 173,
-			186, 223, 188, 119, 184, 99, 229, 212, 147, 121, 152, 65, 40, 76,
-			223, 222, 44, 236, 110, 131, 18, 71, 251, 77, 46, 247, 197, 156,
-			221, 70, 165, 90, 158, 147, 119, 109, 72, 190, 78, 142, 58, 161,
-			100, 6, 142, 148, 50, 185, 107, 165, 170, 83, 221, 182, 98, 111,
-			117, 249, 246, 242, 71, 27, 107, 127, 126, 249, 163, 245, 181, 107,
-			107, 183, 161, 163, 87, 49, 139, 35, 108, 79, 176, 2, 129, 96,
-			209, 25, 53, 39, 91, 240, 205, 71, 185, 55, 12, 130, 19, 73,
-			234, 108, 65, 229, 214, 103, 209, 232, 24, 191, 147, 189, 96, 38,
-			88, 189, 120, 218, 189, 10, 147, 97, 164, 235, 157, 211, 238, 59,
-			148, 163, 209, 83, 102, 16, 79, 102, 198, 205, 37, 142, 84, 171,
-			96, 174, 67, 172, 11, 238, 157, 171, 177, 4, 171, 247, 142, 152,
-			53, 240, 252, 210, 56, 95, 205, 58, 228, 8, 22, 23, 199, 221,
-			75, 135, 58, 36, 141, 45, 70, 199, 158, 240, 108, 167, 11, 110,
-			147, 171, 177, 4, 139, 123, 133, 89, 195, 4, 139, 199, 148, 83,
-			27, 6, 35, 190, 239, 148, 212, 122, 133, 103, 211, 251, 146, 71,
-			92, 144, 105, 13, 238, 247, 13, 235, 50, 19, 236, 190, 164, 33,
-			67, 217, 66, 210, 127, 118, 25, 227, 8, 27, 205, 145, 64, 223,
-			55, 162, 203, 146, 2, 175, 154, 219, 130, 165, 142, 155, 93, 6,
-			45, 50, 53, 154, 195, 237, 211, 190, 49, 93, 102, 130, 165, 167,
-			39, 248, 223, 219, 178, 61, 19, 236, 19, 231, 172, 251, 200, 72,
-			44, 152, 229, 225, 214, 218, 162, 113, 205, 248, 106, 247, 194, 196,
-			136, 247, 181, 45, 67, 14, 208, 150, 117, 152, 145, 98, 48, 187,
-			244, 34, 108, 228, 145, 7, 137, 53, 251, 160, 118, 72, 216, 176,
-			209, 216, 130, 158, 113, 81, 128, 93, 168, 199, 251, 240, 19, 227,
-			92, 203, 99, 81, 70, 237, 250, 120, 225, 99, 46, 63, 190, 44,
-			17, 123, 232, 173, 47, 111, 220, 206, 49, 78, 130, 240, 176, 247,
-			61, 207, 38, 10, 164, 240, 19, 199, 40, 91, 130, 125, 210, 59,
-			161, 203, 48, 113, 147, 83, 252, 75, 53, 145, 142, 112, 62, 179,
-			156, 146, 251, 27, 203, 187, 66, 182, 71, 12, 186, 71, 107, 159,
-			206, 62, 111, 76, 223, 33, 131, 208, 129, 185, 237, 112, 29, 184,
-			82, 42, 7, 164, 251, 225, 250, 86, 219, 245, 155, 59, 50, 96,
-			35, 121, 186, 82, 152, 67, 115, 219, 82, 7, 123, 106, 253, 186,
-			90, 255, 164, 27, 108, 138, 7, 47, 152, 54, 213, 13, 63, 183,
-			24, 170, 152, 102, 228, 16, 135, 198, 6, 82, 94, 200, 222, 17,
-			62, 8, 155, 116, 71, 99, 151, 205, 160, 34, 27, 62, 36, 152,
-			142, 110, 93, 129, 156, 248, 158, 97, 93, 161, 88, 241, 159, 171,
-			25, 236, 18, 206, 35, 203, 25, 119, 127, 109, 121, 43, 210, 66,
-			251, 99, 83, 72, 106, 86, 237, 30, 12, 192, 116, 226, 229, 57,
-			67, 195, 83, 77, 156, 154, 55, 126, 236, 196, 169, 7, 255, 216,
-			204, 209, 196, 241, 19, 206, 92, 23, 77, 131, 158, 185, 46, 4,
-			198, 240, 72, 44, 43, 16, 26, 27, 43, 241, 191, 178, 100, 170,
-			36, 231, 11, 203, 46, 185, 251, 89, 180, 143, 142, 152, 152, 65,
-			96, 154, 149, 204, 161, 102, 116, 81, 210, 180, 77, 167, 30, 58,
-			56, 192, 23, 117, 176, 39, 51, 133, 195, 145, 176, 221, 152, 111,
-			197, 243, 117, 63, 217, 33, 226, 94, 80, 81, 120, 158, 83, 196,
-			126, 244, 168, 162, 5, 69, 174, 224, 61, 120, 221, 95, 192, 235,
-			30, 64, 37, 144, 137, 226, 151, 150, 253, 119, 22, 163, 203, 12,
-			14, 181, 95, 194, 191, 111, 162, 48, 48, 187, 32, 156, 191, 181,
-			156, 105, 247, 45, 111, 149, 146, 144, 171, 87, 78, 156, 23, 245,
-			105, 104, 64, 86, 18, 188, 245, 203, 83, 188, 127, 154, 54, 102,
-			23, 28, 188, 101, 159, 174, 232, 130, 138, 254, 17, 93, 97, 65,
-			197, 168, 171, 43, 24, 84, 76, 157, 229, 85, 217, 43, 36, 169,
-			59, 158, 187, 114, 210, 94, 153, 254, 191, 199, 244, 203, 42, 226,
-			77, 133, 174, 192, 167, 140, 156, 209, 21, 72, 134, 63, 59, 45,
-			81, 213, 46, 225, 60, 86, 177, 39, 10, 118, 87, 17, 139, 106,
-			218, 65, 90, 30, 235, 105, 7, 89, 121, 108, 25, 140, 158, 175,
-			250, 248, 203, 39, 132, 29, 229, 79, 3, 67, 125, 82, 254, 210,
-			167, 7, 80, 159, 49, 22, 190, 251, 172, 41, 229, 221, 103, 33,
-			11, 158, 120, 216, 157, 160, 244, 226, 111, 45, 238, 32, 68, 181,
-			204, 7, 59, 226, 218, 138, 210, 209, 145, 199, 221, 35, 235, 211,
-			61, 113, 153, 15, 31, 74, 132, 44, 16, 45, 61, 42, 63, 178,
-			123, 76, 114, 86, 241, 6, 239, 207, 209, 230, 4, 70, 150, 239,
-			100, 210, 29, 219, 124, 142, 247, 100, 171, 180, 24, 234, 196, 249,
-			220, 124, 16, 240, 159, 134, 86, 253, 79, 145, 136, 140, 222, 47,
-			21, 172, 122, 225, 8, 176, 170, 175, 112, 85, 129, 85, 253, 133,
-			53, 252, 233, 8, 54, 80, 184, 140, 63, 187, 4, 27, 204, 248,
-			143, 195, 133, 94, 126, 158, 219, 197, 130, 112, 70, 11, 158, 229,
-			78, 17, 173, 101, 85, 171, 22, 27, 116, 216, 92, 190, 185, 70,
-			192, 76, 17, 201, 25, 221, 125, 252, 22, 119, 138, 120, 166, 46,
-			217, 215, 220, 213, 39, 239, 29, 184, 204, 201, 77, 67, 177, 194,
-			15, 83, 103, 224, 100, 95, 164, 51, 106, 169, 56, 166, 74, 182,
-			96, 165, 210, 75, 170, 196, 4, 43, 189, 250, 46, 191, 134, 15,
-			183, 4, 155, 176, 111, 185, 111, 193, 244, 203, 44, 248, 91, 7,
-			70, 242, 108, 58, 88, 167, 185, 140, 255, 218, 167, 145, 206, 26,
-			171, 215, 178, 7, 131, 206, 60, 81, 28, 87, 37, 91, 176, 137,
-			211, 23, 84, 137, 9, 54, 177, 116, 131, 255, 25, 62, 216, 22,
-			108, 210, 94, 115, 215, 78, 240, 96, 101, 233, 150, 190, 167, 25,
-			103, 20, 247, 112, 229, 84, 173, 122, 0, 35, 154, 44, 142, 168,
-			18, 60, 102, 180, 172, 74, 76, 176, 201, 197, 183, 249, 29, 236,
-			1, 19, 108, 218, 126, 205, 93, 247, 146, 118, 51, 213, 40, 31,
-			242, 179, 253, 250, 189, 212, 243, 235, 177, 68, 219, 58, 39, 90,
-			239, 55, 121, 236, 70, 117, 2, 164, 105, 186, 56, 168, 74, 182,
-			96, 211, 67, 211, 170, 4, 207, 125, 241, 85, 181, 45, 252, 46,
-			0, 0, 255, 255, 14, 242, 176, 106, 108, 26, 1, 0},
-	)
-}
-
-// FileDescriptorSet returns a descriptor set for this proto package, which
-// includes all defined services, and all transitive dependencies.
-//
-// Will not return nil.
-//
-// Do NOT modify the returned descriptor.
-func FileDescriptorSet() *descriptorpb.FileDescriptorSet {
-	// We just need ONE of the service names to look up the FileDescriptorSet.
-	ret, err := discovery.GetDescriptorSet("dm.Deps")
-	if err != nil {
-		panic(err)
-	}
-	return ret
-}
diff --git a/dm/api/service/v1/proto_gae.gen.go b/dm/api/service/v1/proto_gae.gen.go
deleted file mode 100644
index f38eddd..0000000
--- a/dm/api/service/v1/proto_gae.gen.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Code generated by gae/tools/proto-gae/proto_gae.go. DO NOT EDIT.
-
-//go:build !copybara
-// +build !copybara
-
-package dm
-
-import (
-	"google.golang.org/protobuf/proto"
-
-	"go.chromium.org/luci/gae/service/datastore"
-)
-
-var _ datastore.PropertyConverter = (*AbnormalFinish)(nil)
-
-// ToProperty implements datastore.PropertyConverter. It causes an embedded
-// 'AbnormalFinish' to serialize to an unindexed '[]byte' when used with the
-// "go.chromium.org/luci/gae" library.
-func (p *AbnormalFinish) ToProperty() (prop datastore.Property, err error) {
-	data, err := proto.Marshal(p)
-	if err == nil {
-		prop.SetValue(data, datastore.NoIndex)
-	}
-	return
-}
-
-// FromProperty implements datastore.PropertyConverter. It parses a '[]byte'
-// into an embedded 'AbnormalFinish' when used with the "go.chromium.org/luci/gae" library.
-func (p *AbnormalFinish) FromProperty(prop datastore.Property) error {
-	data, err := prop.Project(datastore.PTBytes)
-	if err != nil {
-		return err
-	}
-	return proto.Unmarshal(data.([]byte), p)
-}
-
-var _ datastore.PropertyConverter = (*Execution_Auth)(nil)
-
-// ToProperty implements datastore.PropertyConverter. It causes an embedded
-// 'Execution_Auth' to serialize to an unindexed '[]byte' when used with the
-// "go.chromium.org/luci/gae" library.
-func (p *Execution_Auth) ToProperty() (prop datastore.Property, err error) {
-	data, err := proto.Marshal(p)
-	if err == nil {
-		prop.SetValue(data, datastore.NoIndex)
-	}
-	return
-}
-
-// FromProperty implements datastore.PropertyConverter. It parses a '[]byte'
-// into an embedded 'Execution_Auth' when used with the "go.chromium.org/luci/gae" library.
-func (p *Execution_Auth) FromProperty(prop datastore.Property) error {
-	data, err := prop.Project(datastore.PTBytes)
-	if err != nil {
-		return err
-	}
-	return proto.Unmarshal(data.([]byte), p)
-}
-
-var _ datastore.PropertyConverter = (*JsonResult)(nil)
-
-// ToProperty implements datastore.PropertyConverter. It causes an embedded
-// 'JsonResult' to serialize to an unindexed '[]byte' when used with the
-// "go.chromium.org/luci/gae" library.
-func (p *JsonResult) ToProperty() (prop datastore.Property, err error) {
-	data, err := proto.Marshal(p)
-	if err == nil {
-		prop.SetValue(data, datastore.NoIndex)
-	}
-	return
-}
-
-// FromProperty implements datastore.PropertyConverter. It parses a '[]byte'
-// into an embedded 'JsonResult' when used with the "go.chromium.org/luci/gae" library.
-func (p *JsonResult) FromProperty(prop datastore.Property) error {
-	data, err := prop.Project(datastore.PTBytes)
-	if err != nil {
-		return err
-	}
-	return proto.Unmarshal(data.([]byte), p)
-}
-
-var _ datastore.PropertyConverter = (*Quest_Desc)(nil)
-
-// ToProperty implements datastore.PropertyConverter. It causes an embedded
-// 'Quest_Desc' to serialize to an unindexed '[]byte' when used with the
-// "go.chromium.org/luci/gae" library.
-func (p *Quest_Desc) ToProperty() (prop datastore.Property, err error) {
-	data, err := proto.Marshal(p)
-	if err == nil {
-		prop.SetValue(data, datastore.NoIndex)
-	}
-	return
-}
-
-// FromProperty implements datastore.PropertyConverter. It parses a '[]byte'
-// into an embedded 'Quest_Desc' when used with the "go.chromium.org/luci/gae" library.
-func (p *Quest_Desc) FromProperty(prop datastore.Property) error {
-	data, err := prop.Project(datastore.PTBytes)
-	if err != nil {
-		return err
-	}
-	return proto.Unmarshal(data.([]byte), p)
-}
-
-var _ datastore.PropertyConverter = (*Quest_TemplateSpec)(nil)
-
-// ToProperty implements datastore.PropertyConverter. It causes an embedded
-// 'Quest_TemplateSpec' to serialize to an unindexed '[]byte' when used with the
-// "go.chromium.org/luci/gae" library.
-func (p *Quest_TemplateSpec) ToProperty() (prop datastore.Property, err error) {
-	data, err := proto.Marshal(p)
-	if err == nil {
-		prop.SetValue(data, datastore.NoIndex)
-	}
-	return
-}
-
-// FromProperty implements datastore.PropertyConverter. It parses a '[]byte'
-// into an embedded 'Quest_TemplateSpec' when used with the "go.chromium.org/luci/gae" library.
-func (p *Quest_TemplateSpec) FromProperty(prop datastore.Property) error {
-	data, err := prop.Project(datastore.PTBytes)
-	if err != nil {
-		return err
-	}
-	return proto.Unmarshal(data.([]byte), p)
-}
-
-var _ datastore.PropertyConverter = (*Result)(nil)
-
-// ToProperty implements datastore.PropertyConverter. It causes an embedded
-// 'Result' to serialize to an unindexed '[]byte' when used with the
-// "go.chromium.org/luci/gae" library.
-func (p *Result) ToProperty() (prop datastore.Property, err error) {
-	data, err := proto.Marshal(p)
-	if err == nil {
-		prop.SetValue(data, datastore.NoIndex)
-	}
-	return
-}
-
-// FromProperty implements datastore.PropertyConverter. It parses a '[]byte'
-// into an embedded 'Result' when used with the "go.chromium.org/luci/gae" library.
-func (p *Result) FromProperty(prop datastore.Property) error {
-	data, err := prop.Project(datastore.PTBytes)
-	if err != nil {
-		return err
-	}
-	return proto.Unmarshal(data.([]byte), p)
-}
diff --git a/dm/api/service/v1/queries.go b/dm/api/service/v1/queries.go
deleted file mode 100644
index bfb5b38..0000000
--- a/dm/api/service/v1/queries.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-// AttemptListQuery returns a new GraphQuery for the given AttemptList.
-func AttemptListQuery(fanout *AttemptList) *GraphQuery {
-	return &GraphQuery{AttemptList: fanout}
-}
-
-// AttemptListQueryL returns a new GraphQuery for the given AttemptList
-// literal.
-func AttemptListQueryL(fanout map[string][]uint32) *GraphQuery {
-	return &GraphQuery{AttemptList: NewAttemptList(fanout)}
-}
-
-// AttemptRangeQuery returns a new GraphQuery for the given AttemptRange
-// specification.
-func AttemptRangeQuery(quest string, low, high uint32) *GraphQuery {
-	return &GraphQuery{
-		AttemptRange: []*GraphQuery_AttemptRange{{Quest: quest, Low: low, High: high}}}
-}
diff --git a/dm/api/service/v1/quest_desc_normalize.go b/dm/api/service/v1/quest_desc_normalize.go
deleted file mode 100644
index 65f9947..0000000
--- a/dm/api/service/v1/quest_desc_normalize.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"crypto/sha256"
-	"encoding/base64"
-	"fmt"
-
-	"google.golang.org/protobuf/proto"
-
-	"go.chromium.org/luci/common/data/text/templateproto"
-)
-
-// IsEmpty returns true if this metadata retry message only contains
-// zero-values.
-func (q *Quest_Desc_Meta_Retry) IsEmpty() bool {
-	return q.Crashed == 0 && q.Expired == 0 && q.Failed == 0 && q.TimedOut == 0
-}
-
-// Normalize ensures that all timeouts are >= 0
-func (t *Quest_Desc_Meta_Timeouts) Normalize() error {
-	if d := t.Start.AsDuration(); d < 0 {
-		return fmt.Errorf("desc.meta.timeouts.start < 0: %s", d)
-	}
-	if d := t.Run.AsDuration(); d < 0 {
-		return fmt.Errorf("desc.meta.timeouts.run < 0: %s", d)
-	}
-	if d := t.Stop.AsDuration(); d < 0 {
-		return fmt.Errorf("desc.meta.timeouts.stop < 0: %s", d)
-	}
-	return nil
-}
-
-// IsEmpty returns true if this metadata only contains zero-values.
-func (q *Quest_Desc_Meta) IsEmpty() bool {
-	return q.AsAccount == "" && q.Retry.IsEmpty()
-}
-
-var (
-	// QuestIDLength is the number of encoded bytes to use. It removes the
-	// single padding character.
-	QuestIDLength = base64.URLEncoding.EncodedLen(sha256.Size) - 1
-)
-
-// QuestDescPayloadMaxLength is the maximum length (in bytes) of an
-// un-normalized Quest payload.
-const QuestDescPayloadMaxLength = 256 * 1024
-
-// Normalize returns an error iff the Quest_Desc is invalid.
-func (q *Quest_Desc) Normalize() error {
-	if q.Meta == nil {
-		q.Meta = &Quest_Desc_Meta{
-			Retry:    &Quest_Desc_Meta_Retry{},
-			Timeouts: &Quest_Desc_Meta_Timeouts{},
-		}
-	} else {
-		if q.Meta.Retry == nil {
-			q.Meta.Retry = &Quest_Desc_Meta_Retry{}
-		}
-		if q.Meta.Timeouts == nil {
-			q.Meta.Timeouts = &Quest_Desc_Meta_Timeouts{}
-		}
-	}
-	if err := q.Meta.Timeouts.Normalize(); err != nil {
-		return err
-	}
-
-	length := len(q.Parameters) + len(q.DistributorParameters)
-	if length > QuestDescPayloadMaxLength {
-		return fmt.Errorf("quest payload is too large: %d > %d",
-			length, QuestDescPayloadMaxLength)
-	}
-	normed, err := templateproto.NormalizeJSON(q.Parameters, true)
-	if err != nil {
-		return fmt.Errorf("failed to normalize parameters: %s", err)
-	}
-	q.Parameters = normed
-
-	normed, err = templateproto.NormalizeJSON(q.DistributorParameters, true)
-	if err != nil {
-		return fmt.Errorf("failed to normalize distributor parameters: %s", err)
-	}
-	q.DistributorParameters = normed
-	return nil
-}
-
-// QuestID computes the DM compatible quest ID for this Quest_Desc. The
-// Quest_Desc should already be Normalize()'d.
-func (q *Quest_Desc) QuestID() string {
-	data, err := proto.Marshal(q)
-	if err != nil {
-		panic(err)
-	}
-	h := sha256.Sum256(data)
-	return base64.URLEncoding.EncodeToString(h[:])[:QuestIDLength]
-}
diff --git a/dm/api/service/v1/service.pb.go b/dm/api/service/v1/service.pb.go
deleted file mode 100644
index d06e485..0000000
--- a/dm/api/service/v1/service.pb.go
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/service/v1/service.proto
-
-package dm
-
-import prpc "go.chromium.org/luci/grpc/prpc"
-
-import (
-	context "context"
-	grpc "google.golang.org/grpc"
-	codes "google.golang.org/grpc/codes"
-	status "google.golang.org/grpc/status"
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	emptypb "google.golang.org/protobuf/types/known/emptypb"
-	reflect "reflect"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-var File_go_chromium_org_luci_dm_api_service_v1_service_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_service_v1_service_proto_rawDesc = []byte{
-	0x0a, 0x34, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x64, 0x6d, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74,
-	0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x37, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f,
-	0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d,
-	0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f,
-	0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x1a, 0x3e, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x5f,
-	0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x1a, 0x3f, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
-	0x65, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x1a, 0x3b, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f,
-	0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73,
-	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68,
-	0x5f, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x37,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x61, 0x6c, 0x6b, 0x5f, 0x67, 0x72, 0x61, 0x70,
-	0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xfd, 0x01, 0x0a, 0x04, 0x44, 0x65, 0x70, 0x73,
-	0x12, 0x41, 0x0a, 0x0f, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44,
-	0x61, 0x74, 0x61, 0x12, 0x16, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x47,
-	0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x64, 0x6d,
-	0x2e, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61,
-	0x52, 0x73, 0x70, 0x12, 0x45, 0x0a, 0x11, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45,
-	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x63,
-	0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52,
-	0x65, 0x71, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0d, 0x46, 0x69,
-	0x6e, 0x69, 0x73, 0x68, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x14, 0x2e, 0x64, 0x6d,
-	0x2e, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65,
-	0x71, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x2c, 0x0a, 0x09, 0x57, 0x61, 0x6c,
-	0x6b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x10, 0x2e, 0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c, 0x6b,
-	0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x64, 0x6d, 0x2e, 0x47, 0x72,
-	0x61, 0x70, 0x68, 0x44, 0x61, 0x74, 0x61, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x6f, 0x2e, 0x63, 0x68,
-	0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f,
-	0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76,
-	0x31, 0x3b, 0x64, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var file_go_chromium_org_luci_dm_api_service_v1_service_proto_goTypes = []interface{}{
-	(*EnsureGraphDataReq)(nil),   // 0: dm.EnsureGraphDataReq
-	(*ActivateExecutionReq)(nil), // 1: dm.ActivateExecutionReq
-	(*FinishAttemptReq)(nil),     // 2: dm.FinishAttemptReq
-	(*WalkGraphReq)(nil),         // 3: dm.WalkGraphReq
-	(*EnsureGraphDataRsp)(nil),   // 4: dm.EnsureGraphDataRsp
-	(*emptypb.Empty)(nil),        // 5: google.protobuf.Empty
-	(*GraphData)(nil),            // 6: dm.GraphData
-}
-var file_go_chromium_org_luci_dm_api_service_v1_service_proto_depIdxs = []int32{
-	0, // 0: dm.Deps.EnsureGraphData:input_type -> dm.EnsureGraphDataReq
-	1, // 1: dm.Deps.ActivateExecution:input_type -> dm.ActivateExecutionReq
-	2, // 2: dm.Deps.FinishAttempt:input_type -> dm.FinishAttemptReq
-	3, // 3: dm.Deps.WalkGraph:input_type -> dm.WalkGraphReq
-	4, // 4: dm.Deps.EnsureGraphData:output_type -> dm.EnsureGraphDataRsp
-	5, // 5: dm.Deps.ActivateExecution:output_type -> google.protobuf.Empty
-	5, // 6: dm.Deps.FinishAttempt:output_type -> google.protobuf.Empty
-	6, // 7: dm.Deps.WalkGraph:output_type -> dm.GraphData
-	4, // [4:8] is the sub-list for method output_type
-	0, // [0:4] is the sub-list for method input_type
-	0, // [0:0] is the sub-list for extension type_name
-	0, // [0:0] is the sub-list for extension extendee
-	0, // [0:0] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_service_v1_service_proto_init() }
-func file_go_chromium_org_luci_dm_api_service_v1_service_proto_init() {
-	if File_go_chromium_org_luci_dm_api_service_v1_service_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_init()
-	file_go_chromium_org_luci_dm_api_service_v1_ensure_graph_data_proto_init()
-	file_go_chromium_org_luci_dm_api_service_v1_activate_execution_proto_init()
-	file_go_chromium_org_luci_dm_api_service_v1_finish_attempt_proto_init()
-	file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_init()
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_service_v1_service_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   0,
-			NumExtensions: 0,
-			NumServices:   1,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_service_v1_service_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_service_v1_service_proto_depIdxs,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_service_v1_service_proto = out.File
-	file_go_chromium_org_luci_dm_api_service_v1_service_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_service_v1_service_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_service_v1_service_proto_depIdxs = nil
-}
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConnInterface
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion6
-
-// DepsClient is the client API for Deps service.
-//
-// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
-type DepsClient interface {
-	// allows you to add additional data to the current dependency graph.
-	EnsureGraphData(ctx context.Context, in *EnsureGraphDataReq, opts ...grpc.CallOption) (*EnsureGraphDataRsp, error)
-	// is called by Execution clients to activate themselves with DM.
-	ActivateExecution(ctx context.Context, in *ActivateExecutionReq, opts ...grpc.CallOption) (*emptypb.Empty, error)
-	// is called by Execution clients to indicate that an Attempt is finished.
-	FinishAttempt(ctx context.Context, in *FinishAttemptReq, opts ...grpc.CallOption) (*emptypb.Empty, error)
-	// runs queries, and walks along the dependency graph from the query results.
-	WalkGraph(ctx context.Context, in *WalkGraphReq, opts ...grpc.CallOption) (*GraphData, error)
-}
-type depsPRPCClient struct {
-	client *prpc.Client
-}
-
-func NewDepsPRPCClient(client *prpc.Client) DepsClient {
-	return &depsPRPCClient{client}
-}
-
-func (c *depsPRPCClient) EnsureGraphData(ctx context.Context, in *EnsureGraphDataReq, opts ...grpc.CallOption) (*EnsureGraphDataRsp, error) {
-	out := new(EnsureGraphDataRsp)
-	err := c.client.Call(ctx, "dm.Deps", "EnsureGraphData", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *depsPRPCClient) ActivateExecution(ctx context.Context, in *ActivateExecutionReq, opts ...grpc.CallOption) (*emptypb.Empty, error) {
-	out := new(emptypb.Empty)
-	err := c.client.Call(ctx, "dm.Deps", "ActivateExecution", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *depsPRPCClient) FinishAttempt(ctx context.Context, in *FinishAttemptReq, opts ...grpc.CallOption) (*emptypb.Empty, error) {
-	out := new(emptypb.Empty)
-	err := c.client.Call(ctx, "dm.Deps", "FinishAttempt", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *depsPRPCClient) WalkGraph(ctx context.Context, in *WalkGraphReq, opts ...grpc.CallOption) (*GraphData, error) {
-	out := new(GraphData)
-	err := c.client.Call(ctx, "dm.Deps", "WalkGraph", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-type depsClient struct {
-	cc grpc.ClientConnInterface
-}
-
-func NewDepsClient(cc grpc.ClientConnInterface) DepsClient {
-	return &depsClient{cc}
-}
-
-func (c *depsClient) EnsureGraphData(ctx context.Context, in *EnsureGraphDataReq, opts ...grpc.CallOption) (*EnsureGraphDataRsp, error) {
-	out := new(EnsureGraphDataRsp)
-	err := c.cc.Invoke(ctx, "/dm.Deps/EnsureGraphData", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *depsClient) ActivateExecution(ctx context.Context, in *ActivateExecutionReq, opts ...grpc.CallOption) (*emptypb.Empty, error) {
-	out := new(emptypb.Empty)
-	err := c.cc.Invoke(ctx, "/dm.Deps/ActivateExecution", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *depsClient) FinishAttempt(ctx context.Context, in *FinishAttemptReq, opts ...grpc.CallOption) (*emptypb.Empty, error) {
-	out := new(emptypb.Empty)
-	err := c.cc.Invoke(ctx, "/dm.Deps/FinishAttempt", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *depsClient) WalkGraph(ctx context.Context, in *WalkGraphReq, opts ...grpc.CallOption) (*GraphData, error) {
-	out := new(GraphData)
-	err := c.cc.Invoke(ctx, "/dm.Deps/WalkGraph", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-// DepsServer is the server API for Deps service.
-type DepsServer interface {
-	// allows you to add additional data to the current dependency graph.
-	EnsureGraphData(context.Context, *EnsureGraphDataReq) (*EnsureGraphDataRsp, error)
-	// is called by Execution clients to activate themselves with DM.
-	ActivateExecution(context.Context, *ActivateExecutionReq) (*emptypb.Empty, error)
-	// is called by Execution clients to indicate that an Attempt is finished.
-	FinishAttempt(context.Context, *FinishAttemptReq) (*emptypb.Empty, error)
-	// runs queries, and walks along the dependency graph from the query results.
-	WalkGraph(context.Context, *WalkGraphReq) (*GraphData, error)
-}
-
-// UnimplementedDepsServer can be embedded to have forward compatible implementations.
-type UnimplementedDepsServer struct {
-}
-
-func (*UnimplementedDepsServer) EnsureGraphData(context.Context, *EnsureGraphDataReq) (*EnsureGraphDataRsp, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method EnsureGraphData not implemented")
-}
-func (*UnimplementedDepsServer) ActivateExecution(context.Context, *ActivateExecutionReq) (*emptypb.Empty, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method ActivateExecution not implemented")
-}
-func (*UnimplementedDepsServer) FinishAttempt(context.Context, *FinishAttemptReq) (*emptypb.Empty, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method FinishAttempt not implemented")
-}
-func (*UnimplementedDepsServer) WalkGraph(context.Context, *WalkGraphReq) (*GraphData, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method WalkGraph not implemented")
-}
-
-func RegisterDepsServer(s prpc.Registrar, srv DepsServer) {
-	s.RegisterService(&_Deps_serviceDesc, srv)
-}
-
-func _Deps_EnsureGraphData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(EnsureGraphDataReq)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(DepsServer).EnsureGraphData(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/dm.Deps/EnsureGraphData",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(DepsServer).EnsureGraphData(ctx, req.(*EnsureGraphDataReq))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Deps_ActivateExecution_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(ActivateExecutionReq)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(DepsServer).ActivateExecution(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/dm.Deps/ActivateExecution",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(DepsServer).ActivateExecution(ctx, req.(*ActivateExecutionReq))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Deps_FinishAttempt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(FinishAttemptReq)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(DepsServer).FinishAttempt(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/dm.Deps/FinishAttempt",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(DepsServer).FinishAttempt(ctx, req.(*FinishAttemptReq))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Deps_WalkGraph_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(WalkGraphReq)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(DepsServer).WalkGraph(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/dm.Deps/WalkGraph",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(DepsServer).WalkGraph(ctx, req.(*WalkGraphReq))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-var _Deps_serviceDesc = grpc.ServiceDesc{
-	ServiceName: "dm.Deps",
-	HandlerType: (*DepsServer)(nil),
-	Methods: []grpc.MethodDesc{
-		{
-			MethodName: "EnsureGraphData",
-			Handler:    _Deps_EnsureGraphData_Handler,
-		},
-		{
-			MethodName: "ActivateExecution",
-			Handler:    _Deps_ActivateExecution_Handler,
-		},
-		{
-			MethodName: "FinishAttempt",
-			Handler:    _Deps_FinishAttempt_Handler,
-		},
-		{
-			MethodName: "WalkGraph",
-			Handler:    _Deps_WalkGraph_Handler,
-		},
-	},
-	Streams:  []grpc.StreamDesc{},
-	Metadata: "go.chromium.org/luci/dm/api/service/v1/service.proto",
-}
diff --git a/dm/api/service/v1/service.proto b/dm/api/service/v1/service.proto
deleted file mode 100644
index e3249d7..0000000
--- a/dm/api/service/v1/service.proto
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/service/v1;dm";
-
-import "google/protobuf/empty.proto";
-
-import "go.chromium.org/luci/dm/api/service/v1/graph_data.proto";
-
-import "go.chromium.org/luci/dm/api/service/v1/ensure_graph_data.proto";
-import "go.chromium.org/luci/dm/api/service/v1/activate_execution.proto";
-import "go.chromium.org/luci/dm/api/service/v1/finish_attempt.proto";
-import "go.chromium.org/luci/dm/api/service/v1/walk_graph.proto";
-
-package dm;
-
-// DM's Dependency Server API.
-service Deps {
-  // allows you to add additional data to the current dependency graph.
-  rpc EnsureGraphData(dm.EnsureGraphDataReq) returns (dm.EnsureGraphDataRsp);
-
-  // is called by Execution clients to activate themselves with DM.
-  rpc ActivateExecution(dm.ActivateExecutionReq) returns (google.protobuf.Empty);
-
-  // is called by Execution clients to indicate that an Attempt is finished.
-  rpc FinishAttempt(dm.FinishAttemptReq) returns (google.protobuf.Empty);
-
-  // runs queries, and walks along the dependency graph from the query results.
-  rpc WalkGraph(dm.WalkGraphReq) returns (dm.GraphData);
-}
diff --git a/dm/api/service/v1/types.pb.go b/dm/api/service/v1/types.pb.go
deleted file mode 100644
index 3a15bc8..0000000
--- a/dm/api/service/v1/types.pb.go
+++ /dev/null
@@ -1,477 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/service/v1/types.proto
-
-package dm
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	emptypb "google.golang.org/protobuf/types/known/emptypb"
-	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type MultiPropertyValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Values []*PropertyValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"`
-}
-
-func (x *MultiPropertyValue) Reset() {
-	*x = MultiPropertyValue{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *MultiPropertyValue) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*MultiPropertyValue) ProtoMessage() {}
-
-func (x *MultiPropertyValue) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use MultiPropertyValue.ProtoReflect.Descriptor instead.
-func (*MultiPropertyValue) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *MultiPropertyValue) GetValues() []*PropertyValue {
-	if x != nil {
-		return x.Values
-	}
-	return nil
-}
-
-type PropertyValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Types that are assignable to Value:
-	//	*PropertyValue_Str
-	//	*PropertyValue_Dat
-	//	*PropertyValue_Num
-	//	*PropertyValue_Bin
-	//	*PropertyValue_Time
-	//	*PropertyValue_Null
-	Value isPropertyValue_Value `protobuf_oneof:"value"`
-}
-
-func (x *PropertyValue) Reset() {
-	*x = PropertyValue{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *PropertyValue) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*PropertyValue) ProtoMessage() {}
-
-func (x *PropertyValue) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use PropertyValue.ProtoReflect.Descriptor instead.
-func (*PropertyValue) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescGZIP(), []int{1}
-}
-
-func (m *PropertyValue) GetValue() isPropertyValue_Value {
-	if m != nil {
-		return m.Value
-	}
-	return nil
-}
-
-func (x *PropertyValue) GetStr() string {
-	if x, ok := x.GetValue().(*PropertyValue_Str); ok {
-		return x.Str
-	}
-	return ""
-}
-
-func (x *PropertyValue) GetDat() []byte {
-	if x, ok := x.GetValue().(*PropertyValue_Dat); ok {
-		return x.Dat
-	}
-	return nil
-}
-
-func (x *PropertyValue) GetNum() int64 {
-	if x, ok := x.GetValue().(*PropertyValue_Num); ok {
-		return x.Num
-	}
-	return 0
-}
-
-func (x *PropertyValue) GetBin() bool {
-	if x, ok := x.GetValue().(*PropertyValue_Bin); ok {
-		return x.Bin
-	}
-	return false
-}
-
-func (x *PropertyValue) GetTime() *timestamppb.Timestamp {
-	if x, ok := x.GetValue().(*PropertyValue_Time); ok {
-		return x.Time
-	}
-	return nil
-}
-
-func (x *PropertyValue) GetNull() *emptypb.Empty {
-	if x, ok := x.GetValue().(*PropertyValue_Null); ok {
-		return x.Null
-	}
-	return nil
-}
-
-type isPropertyValue_Value interface {
-	isPropertyValue_Value()
-}
-
-type PropertyValue_Str struct {
-	Str string `protobuf:"bytes,1,opt,name=str,proto3,oneof"`
-}
-
-type PropertyValue_Dat struct {
-	Dat []byte `protobuf:"bytes,2,opt,name=dat,proto3,oneof"`
-}
-
-type PropertyValue_Num struct {
-	Num int64 `protobuf:"varint,3,opt,name=num,proto3,oneof"`
-}
-
-type PropertyValue_Bin struct {
-	Bin bool `protobuf:"varint,5,opt,name=bin,proto3,oneof"`
-}
-
-type PropertyValue_Time struct {
-	// Time should only be used with the start/end PropertyValues in
-	// GraphQuerySearch. If specified in a filter map, it will be ignored.
-	Time *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=time,proto3,oneof"`
-}
-
-type PropertyValue_Null struct {
-	Null *emptypb.Empty `protobuf:"bytes,7,opt,name=null,proto3,oneof"`
-}
-
-func (*PropertyValue_Str) isPropertyValue_Value() {}
-
-func (*PropertyValue_Dat) isPropertyValue_Value() {}
-
-func (*PropertyValue_Num) isPropertyValue_Value() {}
-
-func (*PropertyValue_Bin) isPropertyValue_Value() {}
-
-func (*PropertyValue_Time) isPropertyValue_Value() {}
-
-func (*PropertyValue_Null) isPropertyValue_Value() {}
-
-// AttemptList is logically a listing of unique attempts, which has a compact
-// representation in the common scenario of listing multiple attempts of the
-// same quest(s).
-type AttemptList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// To is a map of quests-to-attempts to depend on. So if you want to depend
-	// on the attempt "foo|1", "foo|2" and "bar|1", this would look like:
-	//   {
-	//     "foo": [1, 2],
-	//     "bar": [1],
-	//   }
-	To map[string]*AttemptList_Nums `protobuf:"bytes,2,rep,name=to,proto3" json:"to,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-}
-
-func (x *AttemptList) Reset() {
-	*x = AttemptList{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *AttemptList) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AttemptList) ProtoMessage() {}
-
-func (x *AttemptList) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use AttemptList.ProtoReflect.Descriptor instead.
-func (*AttemptList) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescGZIP(), []int{2}
-}
-
-func (x *AttemptList) GetTo() map[string]*AttemptList_Nums {
-	if x != nil {
-		return x.To
-	}
-	return nil
-}
-
-type AttemptList_Nums struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Nums []uint32 `protobuf:"varint,1,rep,packed,name=nums,proto3" json:"nums,omitempty"`
-}
-
-func (x *AttemptList_Nums) Reset() {
-	*x = AttemptList_Nums{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[3]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *AttemptList_Nums) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AttemptList_Nums) ProtoMessage() {}
-
-func (x *AttemptList_Nums) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[3]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use AttemptList_Nums.ProtoReflect.Descriptor instead.
-func (*AttemptList_Nums) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescGZIP(), []int{2, 0}
-}
-
-func (x *AttemptList_Nums) GetNums() []uint32 {
-	if x != nil {
-		return x.Nums
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_service_v1_types_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDesc = []byte{
-	0x0a, 0x32, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x64, 0x6d, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
-	0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3f, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x50,
-	0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x29, 0x0a, 0x06,
-	0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x64,
-	0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
-	0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xce, 0x01, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x70,
-	0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x73, 0x74, 0x72,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x73, 0x74, 0x72, 0x12, 0x12, 0x0a,
-	0x03, 0x64, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x03, 0x64, 0x61,
-	0x74, 0x12, 0x12, 0x0a, 0x03, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00,
-	0x52, 0x03, 0x6e, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x03, 0x62, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01,
-	0x28, 0x08, 0x48, 0x00, 0x52, 0x03, 0x62, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x69, 0x6d,
-	0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
-	0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x6e,
-	0x75, 0x6c, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
-	0x79, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x75, 0x6c, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c,
-	0x75, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xa3, 0x01, 0x0a, 0x0b, 0x41, 0x74, 0x74,
-	0x65, 0x6d, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02,
-	0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70,
-	0x74, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x54, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x02, 0x74,
-	0x6f, 0x1a, 0x1e, 0x0a, 0x04, 0x4e, 0x75, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x04, 0x6e, 0x75, 0x6d,
-	0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x75, 0x6d,
-	0x73, 0x1a, 0x4b, 0x0a, 0x07, 0x54, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
-	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e,
-	0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x4e,
-	0x75, 0x6d, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x2b,
-	0x5a, 0x29, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescData = file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
-var file_go_chromium_org_luci_dm_api_service_v1_types_proto_goTypes = []interface{}{
-	(*MultiPropertyValue)(nil),    // 0: dm.MultiPropertyValue
-	(*PropertyValue)(nil),         // 1: dm.PropertyValue
-	(*AttemptList)(nil),           // 2: dm.AttemptList
-	(*AttemptList_Nums)(nil),      // 3: dm.AttemptList.Nums
-	nil,                           // 4: dm.AttemptList.ToEntry
-	(*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp
-	(*emptypb.Empty)(nil),         // 6: google.protobuf.Empty
-}
-var file_go_chromium_org_luci_dm_api_service_v1_types_proto_depIdxs = []int32{
-	1, // 0: dm.MultiPropertyValue.values:type_name -> dm.PropertyValue
-	5, // 1: dm.PropertyValue.time:type_name -> google.protobuf.Timestamp
-	6, // 2: dm.PropertyValue.null:type_name -> google.protobuf.Empty
-	4, // 3: dm.AttemptList.to:type_name -> dm.AttemptList.ToEntry
-	3, // 4: dm.AttemptList.ToEntry.value:type_name -> dm.AttemptList.Nums
-	5, // [5:5] is the sub-list for method output_type
-	5, // [5:5] is the sub-list for method input_type
-	5, // [5:5] is the sub-list for extension type_name
-	5, // [5:5] is the sub-list for extension extendee
-	0, // [0:5] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_service_v1_types_proto_init() }
-func file_go_chromium_org_luci_dm_api_service_v1_types_proto_init() {
-	if File_go_chromium_org_luci_dm_api_service_v1_types_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*MultiPropertyValue); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*PropertyValue); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*AttemptList); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*AttemptList_Nums); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes[1].OneofWrappers = []interface{}{
-		(*PropertyValue_Str)(nil),
-		(*PropertyValue_Dat)(nil),
-		(*PropertyValue_Num)(nil),
-		(*PropertyValue_Bin)(nil),
-		(*PropertyValue_Time)(nil),
-		(*PropertyValue_Null)(nil),
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   5,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_service_v1_types_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_service_v1_types_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_service_v1_types_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_service_v1_types_proto = out.File
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_depIdxs = nil
-}
diff --git a/dm/api/service/v1/types.proto b/dm/api/service/v1/types.proto
deleted file mode 100644
index 4a67bdf..0000000
--- a/dm/api/service/v1/types.proto
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/service/v1;dm";
-
-import "google/protobuf/timestamp.proto";
-import "google/protobuf/empty.proto";
-
-package dm;
-
-message MultiPropertyValue {
-  repeated PropertyValue values = 1;
-}
-
-message PropertyValue {
-  // reserve 4 for floats. This is omitted because equality-comparison with
-  // floats is notoriously difficult. In the initial implementation of DM,
-  // payloads and results with floats will be rejected. Hopefully they're not
-  // needed, and we don't need to support them.
-  reserved 4;
-
-  oneof value {
-    string str = 1;
-    bytes  dat = 2;
-    int64  num = 3;
-    bool   bin = 5;
-
-    // Time should only be used with the start/end PropertyValues in
-    // GraphQuerySearch. If specified in a filter map, it will be ignored.
-    google.protobuf.Timestamp time = 6;
-
-    google.protobuf.Empty null = 7;
-  }
-}
-
-// AttemptList is logically a listing of unique attempts, which has a compact
-// representation in the common scenario of listing multiple attempts of the
-// same quest(s).
-message AttemptList {
-  message Nums {
-    repeated uint32 nums = 1 [packed=true];
-  }
-
-  // To is a map of quests-to-attempts to depend on. So if you want to depend
-  // on the attempt "foo|1", "foo|2" and "bar|1", this would look like:
-  //   {
-  //     "foo": [1, 2],
-  //     "bar": [1],
-  //   }
-  map<string, Nums> to = 2;
-}
diff --git a/dm/api/service/v1/walk_graph.pb.go b/dm/api/service/v1/walk_graph.pb.go
deleted file mode 100644
index a15be45..0000000
--- a/dm/api/service/v1/walk_graph.pb.go
+++ /dev/null
@@ -1,818 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/service/v1/walk_graph.proto
-
-package dm
-
-import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	durationpb "google.golang.org/protobuf/types/known/durationpb"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// Direction indicates that direction of dependencies that the request should
-// walk.
-type WalkGraphReq_Mode_Direction int32
-
-const (
-	WalkGraphReq_Mode_FORWARDS  WalkGraphReq_Mode_Direction = 0
-	WalkGraphReq_Mode_BACKWARDS WalkGraphReq_Mode_Direction = 1
-	WalkGraphReq_Mode_BOTH      WalkGraphReq_Mode_Direction = 2
-)
-
-// Enum value maps for WalkGraphReq_Mode_Direction.
-var (
-	WalkGraphReq_Mode_Direction_name = map[int32]string{
-		0: "FORWARDS",
-		1: "BACKWARDS",
-		2: "BOTH",
-	}
-	WalkGraphReq_Mode_Direction_value = map[string]int32{
-		"FORWARDS":  0,
-		"BACKWARDS": 1,
-		"BOTH":      2,
-	}
-)
-
-func (x WalkGraphReq_Mode_Direction) Enum() *WalkGraphReq_Mode_Direction {
-	p := new(WalkGraphReq_Mode_Direction)
-	*p = x
-	return p
-}
-
-func (x WalkGraphReq_Mode_Direction) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (WalkGraphReq_Mode_Direction) Descriptor() protoreflect.EnumDescriptor {
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_enumTypes[0].Descriptor()
-}
-
-func (WalkGraphReq_Mode_Direction) Type() protoreflect.EnumType {
-	return &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_enumTypes[0]
-}
-
-func (x WalkGraphReq_Mode_Direction) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Use WalkGraphReq_Mode_Direction.Descriptor instead.
-func (WalkGraphReq_Mode_Direction) EnumDescriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescGZIP(), []int{0, 0, 0}
-}
-
-// WalkGraphReq allows you to walk from one or more Quests through their
-// Attempt's forward dependencies.
-//
-//
-// The handler will evaluate all of the queries, executing them in parallel.
-// For each attempt or quest produced by the query, it will queue a walk
-// operation for that node, respecting the options set (max_depth, etc.).
-type WalkGraphReq struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Optional. See Include.AttemptResult for restrictions.
-	Auth *Execution_Auth `protobuf:"bytes,1,opt,name=auth,proto3" json:"auth,omitempty"`
-	// Query specifies a list of queries to start the graph traversal on. The
-	// traversal will occur as a union of the query results. Redundant
-	// specification will not cause additional heavy work; every graph node will
-	// be processed exactly once, regardless of how many times it appears in the
-	// query results. However, redundancy in the queries will cause the server to
-	// retrieve and discard more information.
-	Query *GraphQuery         `protobuf:"bytes,2,opt,name=query,proto3" json:"query,omitempty"`
-	Mode  *WalkGraphReq_Mode  `protobuf:"bytes,3,opt,name=mode,proto3" json:"mode,omitempty"`
-	Limit *WalkGraphReq_Limit `protobuf:"bytes,4,opt,name=limit,proto3" json:"limit,omitempty"`
-	// Include allows you to add additional information to the returned
-	// GraphData which is typically medium-to-large sized.
-	Include *WalkGraphReq_Include `protobuf:"bytes,5,opt,name=include,proto3" json:"include,omitempty"`
-	Exclude *WalkGraphReq_Exclude `protobuf:"bytes,6,opt,name=exclude,proto3" json:"exclude,omitempty"`
-}
-
-func (x *WalkGraphReq) Reset() {
-	*x = WalkGraphReq{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *WalkGraphReq) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WalkGraphReq) ProtoMessage() {}
-
-func (x *WalkGraphReq) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use WalkGraphReq.ProtoReflect.Descriptor instead.
-func (*WalkGraphReq) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *WalkGraphReq) GetAuth() *Execution_Auth {
-	if x != nil {
-		return x.Auth
-	}
-	return nil
-}
-
-func (x *WalkGraphReq) GetQuery() *GraphQuery {
-	if x != nil {
-		return x.Query
-	}
-	return nil
-}
-
-func (x *WalkGraphReq) GetMode() *WalkGraphReq_Mode {
-	if x != nil {
-		return x.Mode
-	}
-	return nil
-}
-
-func (x *WalkGraphReq) GetLimit() *WalkGraphReq_Limit {
-	if x != nil {
-		return x.Limit
-	}
-	return nil
-}
-
-func (x *WalkGraphReq) GetInclude() *WalkGraphReq_Include {
-	if x != nil {
-		return x.Include
-	}
-	return nil
-}
-
-func (x *WalkGraphReq) GetExclude() *WalkGraphReq_Exclude {
-	if x != nil {
-		return x.Exclude
-	}
-	return nil
-}
-
-type WalkGraphReq_Mode struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// DFS sets whether this is a Depth-first (ish) or a Breadth-first (ish) load.
-	// Since the load operation is multi-threaded, the search order is best
-	// effort, but will actually be some hybrid between DFS and BFS. This setting
-	// controls the bias direction of the hybrid loading algorithm.
-	Dfs       bool                        `protobuf:"varint,1,opt,name=dfs,proto3" json:"dfs,omitempty"`
-	Direction WalkGraphReq_Mode_Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=dm.WalkGraphReq_Mode_Direction" json:"direction,omitempty"`
-}
-
-func (x *WalkGraphReq_Mode) Reset() {
-	*x = WalkGraphReq_Mode{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *WalkGraphReq_Mode) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WalkGraphReq_Mode) ProtoMessage() {}
-
-func (x *WalkGraphReq_Mode) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use WalkGraphReq_Mode.ProtoReflect.Descriptor instead.
-func (*WalkGraphReq_Mode) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescGZIP(), []int{0, 0}
-}
-
-func (x *WalkGraphReq_Mode) GetDfs() bool {
-	if x != nil {
-		return x.Dfs
-	}
-	return false
-}
-
-func (x *WalkGraphReq_Mode) GetDirection() WalkGraphReq_Mode_Direction {
-	if x != nil {
-		return x.Direction
-	}
-	return WalkGraphReq_Mode_FORWARDS
-}
-
-type WalkGraphReq_Limit struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// MaxDepth sets the number of attempts to traverse; 0 means 'immediate'
-	// (no dependencies), -1 means 'no limit', and >0 is a limit.
-	//
-	// Any negative value besides -1 is an error.
-	MaxDepth int64 `protobuf:"varint,1,opt,name=max_depth,json=maxDepth,proto3" json:"max_depth,omitempty"`
-	// MaxTime sets the maximum amount of time that the query processor should
-	// take. Application of this deadline is 'best effort', which means the query
-	// may take a bit longer than this timeout and still attempt to return data.
-	//
-	// This is different than the grpc timeout header, which will set a hard
-	// deadline for the request.
-	MaxTime *durationpb.Duration `protobuf:"bytes,2,opt,name=max_time,json=maxTime,proto3" json:"max_time,omitempty"`
-	// MaxDataSize sets the maximum amount of 'Data' (in bytes) that can be
-	// returned, if include.quest_data, include.attempt_data, and/or
-	// include.attempt_result are set. If this limit is hit, then the
-	// appropriate 'partial' value will be set for that object, but the base
-	// object would still be included in the result.
-	//
-	// If this limit is 0, a default limit of 16MB will be used. If this limit
-	// exceeds 30MB, it will be reduced to 30MB.
-	MaxDataSize uint32 `protobuf:"varint,3,opt,name=max_data_size,json=maxDataSize,proto3" json:"max_data_size,omitempty"`
-}
-
-func (x *WalkGraphReq_Limit) Reset() {
-	*x = WalkGraphReq_Limit{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *WalkGraphReq_Limit) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WalkGraphReq_Limit) ProtoMessage() {}
-
-func (x *WalkGraphReq_Limit) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use WalkGraphReq_Limit.ProtoReflect.Descriptor instead.
-func (*WalkGraphReq_Limit) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescGZIP(), []int{0, 1}
-}
-
-func (x *WalkGraphReq_Limit) GetMaxDepth() int64 {
-	if x != nil {
-		return x.MaxDepth
-	}
-	return 0
-}
-
-func (x *WalkGraphReq_Limit) GetMaxTime() *durationpb.Duration {
-	if x != nil {
-		return x.MaxTime
-	}
-	return nil
-}
-
-func (x *WalkGraphReq_Limit) GetMaxDataSize() uint32 {
-	if x != nil {
-		return x.MaxDataSize
-	}
-	return 0
-}
-
-type WalkGraphReq_Include struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Quest     *WalkGraphReq_Include_Options `protobuf:"bytes,1,opt,name=quest,proto3" json:"quest,omitempty"`
-	Attempt   *WalkGraphReq_Include_Options `protobuf:"bytes,2,opt,name=attempt,proto3" json:"attempt,omitempty"`
-	Execution *WalkGraphReq_Include_Options `protobuf:"bytes,3,opt,name=execution,proto3" json:"execution,omitempty"`
-	// Executions is the number of Executions to include per Attempt. If this
-	// is 0, then the execution data will be omitted completely.
-	//
-	// Executions included are from high ids to low ids. So setting this to `1`
-	// would return the LAST execution made for this Attempt.
-	NumExecutions uint32 `protobuf:"varint,4,opt,name=num_executions,json=numExecutions,proto3" json:"num_executions,omitempty"`
-	// FwdDeps instructs WalkGraph to include forward dependency information
-	// from the result. This only changes the presence of information in the
-	// result; if the query is walking forward attempt dependencies, that will
-	// still occur even if this is false.
-	FwdDeps bool `protobuf:"varint,5,opt,name=fwd_deps,json=fwdDeps,proto3" json:"fwd_deps,omitempty"`
-	// BackDeps instructs WalkGraph to include the backwards dependency
-	// information. This only changes the presence of information in the result;
-	// if the query is walking backward attempt dependencies, that will still
-	// occur even if this is false.
-	BackDeps bool `protobuf:"varint,6,opt,name=back_deps,json=backDeps,proto3" json:"back_deps,omitempty"`
-}
-
-func (x *WalkGraphReq_Include) Reset() {
-	*x = WalkGraphReq_Include{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[3]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *WalkGraphReq_Include) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WalkGraphReq_Include) ProtoMessage() {}
-
-func (x *WalkGraphReq_Include) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[3]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use WalkGraphReq_Include.ProtoReflect.Descriptor instead.
-func (*WalkGraphReq_Include) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescGZIP(), []int{0, 2}
-}
-
-func (x *WalkGraphReq_Include) GetQuest() *WalkGraphReq_Include_Options {
-	if x != nil {
-		return x.Quest
-	}
-	return nil
-}
-
-func (x *WalkGraphReq_Include) GetAttempt() *WalkGraphReq_Include_Options {
-	if x != nil {
-		return x.Attempt
-	}
-	return nil
-}
-
-func (x *WalkGraphReq_Include) GetExecution() *WalkGraphReq_Include_Options {
-	if x != nil {
-		return x.Execution
-	}
-	return nil
-}
-
-func (x *WalkGraphReq_Include) GetNumExecutions() uint32 {
-	if x != nil {
-		return x.NumExecutions
-	}
-	return 0
-}
-
-func (x *WalkGraphReq_Include) GetFwdDeps() bool {
-	if x != nil {
-		return x.FwdDeps
-	}
-	return false
-}
-
-func (x *WalkGraphReq_Include) GetBackDeps() bool {
-	if x != nil {
-		return x.BackDeps
-	}
-	return false
-}
-
-type WalkGraphReq_Exclude struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Do not include data from the following quests in the response.
-	Quests []string `protobuf:"bytes,1,rep,name=quests,proto3" json:"quests,omitempty"`
-	// Do not include data from the following attempts in the response.
-	Attempts *AttemptList `protobuf:"bytes,2,opt,name=attempts,proto3" json:"attempts,omitempty"`
-}
-
-func (x *WalkGraphReq_Exclude) Reset() {
-	*x = WalkGraphReq_Exclude{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[4]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *WalkGraphReq_Exclude) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WalkGraphReq_Exclude) ProtoMessage() {}
-
-func (x *WalkGraphReq_Exclude) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[4]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use WalkGraphReq_Exclude.ProtoReflect.Descriptor instead.
-func (*WalkGraphReq_Exclude) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescGZIP(), []int{0, 3}
-}
-
-func (x *WalkGraphReq_Exclude) GetQuests() []string {
-	if x != nil {
-		return x.Quests
-	}
-	return nil
-}
-
-func (x *WalkGraphReq_Exclude) GetAttempts() *AttemptList {
-	if x != nil {
-		return x.Attempts
-	}
-	return nil
-}
-
-type WalkGraphReq_Include_Options struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Fills the 'id' field.
-	//
-	// If this is false, it will be omitted.
-	//
-	// Note that there's enough information contextually to derive these ids
-	// on the client side, though it can be handy to have the server produce
-	// them for you.
-	Ids bool `protobuf:"varint,1,opt,name=ids,proto3" json:"ids,omitempty"`
-	// Instructs the request to include the Data field
-	Data bool `protobuf:"varint,2,opt,name=data,proto3" json:"data,omitempty"`
-	// Instructs finished objects to include the Result field.
-	//
-	// If the requestor is an execution, the query logic will only include the
-	// result if the execution's Attempt depends on it, otherwise it will be
-	// blank.
-	//
-	// If the request's cumulative result data would be more than
-	// limit.max_data_size of data, the remaining results will have their
-	// Partial.Result set to DATA_SIZE_LIMIT.
-	//
-	// Has no effect for Quests.
-	Result bool `protobuf:"varint,3,opt,name=result,proto3" json:"result,omitempty"`
-	// If set to true, objects with an abnormal termination will be included.
-	Abnormal bool `protobuf:"varint,4,opt,name=abnormal,proto3" json:"abnormal,omitempty"`
-	// If set to true, expired objects will be included.
-	Expired bool `protobuf:"varint,5,opt,name=expired,proto3" json:"expired,omitempty"`
-}
-
-func (x *WalkGraphReq_Include_Options) Reset() {
-	*x = WalkGraphReq_Include_Options{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[5]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *WalkGraphReq_Include_Options) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WalkGraphReq_Include_Options) ProtoMessage() {}
-
-func (x *WalkGraphReq_Include_Options) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[5]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use WalkGraphReq_Include_Options.ProtoReflect.Descriptor instead.
-func (*WalkGraphReq_Include_Options) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescGZIP(), []int{0, 2, 0}
-}
-
-func (x *WalkGraphReq_Include_Options) GetIds() bool {
-	if x != nil {
-		return x.Ids
-	}
-	return false
-}
-
-func (x *WalkGraphReq_Include_Options) GetData() bool {
-	if x != nil {
-		return x.Data
-	}
-	return false
-}
-
-func (x *WalkGraphReq_Include_Options) GetResult() bool {
-	if x != nil {
-		return x.Result
-	}
-	return false
-}
-
-func (x *WalkGraphReq_Include_Options) GetAbnormal() bool {
-	if x != nil {
-		return x.Abnormal
-	}
-	return false
-}
-
-func (x *WalkGraphReq_Include_Options) GetExpired() bool {
-	if x != nil {
-		return x.Expired
-	}
-	return false
-}
-
-var File_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDesc = []byte{
-	0x0a, 0x37, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x61, 0x6c, 0x6b, 0x5f, 0x67, 0x72,
-	0x61, 0x70, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x64, 0x6d, 0x1a, 0x1e, 0x67,
-	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64,
-	0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x37, 0x67,
-	0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c,
-	0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69,
-	0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x38, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d,
-	0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f,
-	0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67,
-	0x72, 0x61, 0x70, 0x68, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x1a, 0x32, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x22, 0x99, 0x08, 0x0a, 0x0c, 0x57, 0x61, 0x6c, 0x6b, 0x47, 0x72, 0x61,
-	0x70, 0x68, 0x52, 0x65, 0x71, 0x12, 0x26, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x6d, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
-	0x6f, 0x6e, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x24, 0x0a,
-	0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x64,
-	0x6d, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75,
-	0x65, 0x72, 0x79, 0x12, 0x29, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x15, 0x2e, 0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c, 0x6b, 0x47, 0x72, 0x61, 0x70, 0x68,
-	0x52, 0x65, 0x71, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x2c,
-	0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e,
-	0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c, 0x6b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x2e,
-	0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x32, 0x0a, 0x07,
-	0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e,
-	0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c, 0x6b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x2e,
-	0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x07, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
-	0x12, 0x32, 0x0a, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x18, 0x2e, 0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c, 0x6b, 0x47, 0x72, 0x61, 0x70, 0x68,
-	0x52, 0x65, 0x71, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x07, 0x65, 0x78, 0x63,
-	0x6c, 0x75, 0x64, 0x65, 0x1a, 0x8b, 0x01, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a,
-	0x03, 0x64, 0x66, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x64, 0x66, 0x73, 0x12,
-	0x3d, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c, 0x6b, 0x47, 0x72, 0x61, 0x70,
-	0x68, 0x52, 0x65, 0x71, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74,
-	0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x32,
-	0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0c, 0x0a, 0x08, 0x46,
-	0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x53, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x42, 0x41, 0x43,
-	0x4b, 0x57, 0x41, 0x52, 0x44, 0x53, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x4f, 0x54, 0x48,
-	0x10, 0x02, 0x1a, 0x7e, 0x0a, 0x05, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d,
-	0x61, 0x78, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08,
-	0x6d, 0x61, 0x78, 0x44, 0x65, 0x70, 0x74, 0x68, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f,
-	0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22,
-	0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x74, 0x61, 0x53, 0x69,
-	0x7a, 0x65, 0x1a, 0x9b, 0x03, 0x0a, 0x07, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x12, 0x36,
-	0x0a, 0x05, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
-	0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c, 0x6b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x2e,
-	0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
-	0x05, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70,
-	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c,
-	0x6b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x2e, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64,
-	0x65, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d,
-	0x70, 0x74, 0x12, 0x3e, 0x0a, 0x09, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x64, 0x6d, 0x2e, 0x57, 0x61, 0x6c, 0x6b, 0x47,
-	0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x2e, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x2e,
-	0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x09, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
-	0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74,
-	0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x45,
-	0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x77, 0x64,
-	0x5f, 0x64, 0x65, 0x70, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x66, 0x77, 0x64,
-	0x44, 0x65, 0x70, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x70,
-	0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x62, 0x61, 0x63, 0x6b, 0x44, 0x65, 0x70,
-	0x73, 0x1a, 0x7d, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x10, 0x0a, 0x03,
-	0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x69, 0x64, 0x73, 0x12, 0x12,
-	0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x61,
-	0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x62,
-	0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x62,
-	0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65,
-	0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64,
-	0x1a, 0x4e, 0x0a, 0x07, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x6d, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d,
-	0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73,
-	0x42, 0x2b, 0x5a, 0x29, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e,
-	0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f,
-	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x6d, 0x62, 0x06, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescData = file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
-var file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_goTypes = []interface{}{
-	(WalkGraphReq_Mode_Direction)(0),     // 0: dm.WalkGraphReq.Mode.Direction
-	(*WalkGraphReq)(nil),                 // 1: dm.WalkGraphReq
-	(*WalkGraphReq_Mode)(nil),            // 2: dm.WalkGraphReq.Mode
-	(*WalkGraphReq_Limit)(nil),           // 3: dm.WalkGraphReq.Limit
-	(*WalkGraphReq_Include)(nil),         // 4: dm.WalkGraphReq.Include
-	(*WalkGraphReq_Exclude)(nil),         // 5: dm.WalkGraphReq.Exclude
-	(*WalkGraphReq_Include_Options)(nil), // 6: dm.WalkGraphReq.Include.Options
-	(*Execution_Auth)(nil),               // 7: dm.Execution.Auth
-	(*GraphQuery)(nil),                   // 8: dm.GraphQuery
-	(*durationpb.Duration)(nil),          // 9: google.protobuf.Duration
-	(*AttemptList)(nil),                  // 10: dm.AttemptList
-}
-var file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_depIdxs = []int32{
-	7,  // 0: dm.WalkGraphReq.auth:type_name -> dm.Execution.Auth
-	8,  // 1: dm.WalkGraphReq.query:type_name -> dm.GraphQuery
-	2,  // 2: dm.WalkGraphReq.mode:type_name -> dm.WalkGraphReq.Mode
-	3,  // 3: dm.WalkGraphReq.limit:type_name -> dm.WalkGraphReq.Limit
-	4,  // 4: dm.WalkGraphReq.include:type_name -> dm.WalkGraphReq.Include
-	5,  // 5: dm.WalkGraphReq.exclude:type_name -> dm.WalkGraphReq.Exclude
-	0,  // 6: dm.WalkGraphReq.Mode.direction:type_name -> dm.WalkGraphReq.Mode.Direction
-	9,  // 7: dm.WalkGraphReq.Limit.max_time:type_name -> google.protobuf.Duration
-	6,  // 8: dm.WalkGraphReq.Include.quest:type_name -> dm.WalkGraphReq.Include.Options
-	6,  // 9: dm.WalkGraphReq.Include.attempt:type_name -> dm.WalkGraphReq.Include.Options
-	6,  // 10: dm.WalkGraphReq.Include.execution:type_name -> dm.WalkGraphReq.Include.Options
-	10, // 11: dm.WalkGraphReq.Exclude.attempts:type_name -> dm.AttemptList
-	12, // [12:12] is the sub-list for method output_type
-	12, // [12:12] is the sub-list for method input_type
-	12, // [12:12] is the sub-list for extension type_name
-	12, // [12:12] is the sub-list for extension extendee
-	0,  // [0:12] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_init() }
-func file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_init() {
-	if File_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto != nil {
-		return
-	}
-	file_go_chromium_org_luci_dm_api_service_v1_graph_data_proto_init()
-	file_go_chromium_org_luci_dm_api_service_v1_graph_query_proto_init()
-	file_go_chromium_org_luci_dm_api_service_v1_types_proto_init()
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*WalkGraphReq); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*WalkGraphReq_Mode); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*WalkGraphReq_Limit); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*WalkGraphReq_Include); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*WalkGraphReq_Exclude); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*WalkGraphReq_Include_Options); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDesc,
-			NumEnums:      1,
-			NumMessages:   6,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_depIdxs,
-		EnumInfos:         file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_enumTypes,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto = out.File
-	file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_service_v1_walk_graph_proto_depIdxs = nil
-}
diff --git a/dm/api/service/v1/walk_graph.proto b/dm/api/service/v1/walk_graph.proto
deleted file mode 100644
index 722b2eb..0000000
--- a/dm/api/service/v1/walk_graph.proto
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/service/v1;dm";
-
-import "google/protobuf/duration.proto";
-
-import "go.chromium.org/luci/dm/api/service/v1/graph_data.proto";
-import "go.chromium.org/luci/dm/api/service/v1/graph_query.proto";
-import "go.chromium.org/luci/dm/api/service/v1/types.proto";
-
-package dm;
-
-// WalkGraphReq allows you to walk from one or more Quests through their
-// Attempt's forward dependencies.
-//
-//
-// The handler will evaluate all of the queries, executing them in parallel.
-// For each attempt or quest produced by the query, it will queue a walk
-// operation for that node, respecting the options set (max_depth, etc.).
-message WalkGraphReq {
-  // Optional. See Include.AttemptResult for restrictions.
-  dm.Execution.Auth auth = 1;
-
-  // Query specifies a list of queries to start the graph traversal on. The
-  // traversal will occur as a union of the query results. Redundant
-  // specification will not cause additional heavy work; every graph node will
-  // be processed exactly once, regardless of how many times it appears in the
-  // query results. However, redundancy in the queries will cause the server to
-  // retrieve and discard more information.
-  GraphQuery query = 2;
-
-  message Mode {
-    // DFS sets whether this is a Depth-first (ish) or a Breadth-first (ish) load.
-    // Since the load operation is multi-threaded, the search order is best
-    // effort, but will actually be some hybrid between DFS and BFS. This setting
-    // controls the bias direction of the hybrid loading algorithm.
-    bool dfs = 1;
-
-    // Direction indicates that direction of dependencies that the request should
-    // walk.
-    enum Direction {
-      FORWARDS = 0;
-      BACKWARDS = 1;
-      BOTH = 2;
-    }
-    Direction direction = 2;
-  }
-  Mode mode = 3;
-
-  message Limit {
-    // MaxDepth sets the number of attempts to traverse; 0 means 'immediate'
-    // (no dependencies), -1 means 'no limit', and >0 is a limit.
-    //
-    // Any negative value besides -1 is an error.
-    int64 max_depth = 1;
-
-    // MaxTime sets the maximum amount of time that the query processor should
-    // take. Application of this deadline is 'best effort', which means the query
-    // may take a bit longer than this timeout and still attempt to return data.
-    //
-    // This is different than the grpc timeout header, which will set a hard
-    // deadline for the request.
-    google.protobuf.Duration max_time = 2;
-
-    // MaxDataSize sets the maximum amount of 'Data' (in bytes) that can be
-    // returned, if include.quest_data, include.attempt_data, and/or
-    // include.attempt_result are set. If this limit is hit, then the
-    // appropriate 'partial' value will be set for that object, but the base
-    // object would still be included in the result.
-    //
-    // If this limit is 0, a default limit of 16MB will be used. If this limit
-    // exceeds 30MB, it will be reduced to 30MB.
-    uint32 max_data_size = 3;
-  }
-  Limit limit = 4;
-
-  message Include {
-    message Options {
-      // Fills the 'id' field.
-      //
-      // If this is false, it will be omitted.
-      //
-      // Note that there's enough information contextually to derive these ids
-      // on the client side, though it can be handy to have the server produce
-      // them for you.
-      bool ids = 1;
-
-      // Instructs the request to include the Data field
-      bool data = 2;
-
-      // Instructs finished objects to include the Result field.
-      //
-      // If the requestor is an execution, the query logic will only include the
-      // result if the execution's Attempt depends on it, otherwise it will be
-      // blank.
-      //
-      // If the request's cumulative result data would be more than
-      // limit.max_data_size of data, the remaining results will have their
-      // Partial.Result set to DATA_SIZE_LIMIT.
-      //
-      // Has no effect for Quests.
-      bool result = 3;
-
-      // If set to true, objects with an abnormal termination will be included.
-      bool abnormal = 4;
-
-      // If set to true, expired objects will be included.
-      bool expired = 5;
-    }
-    Options quest = 1;
-    Options attempt = 2;
-    Options execution = 3;
-
-    // Executions is the number of Executions to include per Attempt. If this
-    // is 0, then the execution data will be omitted completely.
-    //
-    // Executions included are from high ids to low ids. So setting this to `1`
-    // would return the LAST execution made for this Attempt.
-    uint32 num_executions = 4;
-
-    // FwdDeps instructs WalkGraph to include forward dependency information
-    // from the result. This only changes the presence of information in the
-    // result; if the query is walking forward attempt dependencies, that will
-    // still occur even if this is false.
-    bool fwd_deps = 5;
-
-    // BackDeps instructs WalkGraph to include the backwards dependency
-    // information. This only changes the presence of information in the result;
-    // if the query is walking backward attempt dependencies, that will still
-    // occur even if this is false.
-    bool back_deps = 6;
-  }
-  // Include allows you to add additional information to the returned
-  // GraphData which is typically medium-to-large sized.
-  Include include = 5;
-
-  message Exclude {
-    // Do not include data from the following quests in the response.
-    repeated string quests = 1;
-
-    // Do not include data from the following attempts in the response.
-    dm.AttemptList attempts = 2;
-  }
-  Exclude exclude = 6;
-}
diff --git a/dm/api/service/v1/walk_graph_normalize.go b/dm/api/service/v1/walk_graph_normalize.go
deleted file mode 100644
index 580d582..0000000
--- a/dm/api/service/v1/walk_graph_normalize.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dm
-
-import (
-	"math"
-	"sort"
-
-	"github.com/xtgo/set"
-	"go.chromium.org/luci/common/errors"
-)
-
-const (
-	// DefaultLimitMaxDataSize is the default MaxDataSize value (16MB).
-	DefaultLimitMaxDataSize = 16 * 1024 * 1024
-
-	// MaxLimitMaxDataSize is the maximum MaxDataSize value (30MB).
-	MaxLimitMaxDataSize = 30 * 1024 * 1024
-)
-
-// MakeWalkGraphIncludeAll makes a new WalkGraphReq_Include which has all the
-// boxes ticked. This should only be used when your application plans to dump
-// the resulting graph query data to some logging/debugging trace for humans.
-//
-// If you don't plan on dumping it for humans, please set the Include options
-// appropriately in order to avoid wasting bandwidth/cpu/datastore query time on
-// the server (and draining your DM quotas unnecessarially).
-func MakeWalkGraphIncludeAll() *WalkGraphReq_Include {
-	return &WalkGraphReq_Include{
-		Quest: &WalkGraphReq_Include_Options{
-			Ids:  true,
-			Data: true,
-		},
-		Attempt: &WalkGraphReq_Include_Options{
-			Ids:      true,
-			Data:     true,
-			Result:   true,
-			Abnormal: true,
-			Expired:  true,
-		},
-		Execution: &WalkGraphReq_Include_Options{
-			Ids:      true,
-			Data:     true,
-			Result:   true,
-			Abnormal: true,
-			Expired:  true,
-		},
-		NumExecutions: math.MaxUint32,
-		FwdDeps:       true,
-		BackDeps:      true,
-	}
-}
-
-// Normalize returns an error iff the WalkGraphReq_Exclude is invalid.
-func (e *WalkGraphReq_Exclude) Normalize() error {
-	if len(e.Quests) > 0 {
-		e.Quests = e.Quests[:set.Uniq(sort.StringSlice(e.Quests))]
-	}
-	return e.Attempts.Normalize()
-}
-
-// Normalize returns an error iff the WalkGraphReq is invalid.
-func (w *WalkGraphReq) Normalize() error {
-	if w.Auth != nil {
-		if err := w.Auth.Normalize(); err != nil {
-			return err
-		}
-	}
-
-	if w.Query == nil {
-		return errors.New("must specify a Query")
-	}
-	if err := w.Query.Normalize(); err != nil {
-		return err
-	}
-
-	if w.Mode == nil {
-		w.Mode = &WalkGraphReq_Mode{}
-	}
-
-	if w.Limit != nil {
-		if w.Limit.MaxDepth < -1 {
-			return errors.New("limit.max_depth must be >= -1")
-		}
-		if w.Limit.GetMaxTime().AsDuration() < 0 {
-			return errors.New("limit.max_time must be positive")
-		}
-	} else {
-		w.Limit = &WalkGraphReq_Limit{}
-	}
-	if w.Limit.MaxDataSize == 0 {
-		w.Limit.MaxDataSize = DefaultLimitMaxDataSize
-	}
-	if w.Limit.MaxDataSize > MaxLimitMaxDataSize {
-		w.Limit.MaxDataSize = MaxLimitMaxDataSize
-	}
-
-	if w.Include == nil {
-		w.Include = &WalkGraphReq_Include{
-			Quest:     &WalkGraphReq_Include_Options{},
-			Attempt:   &WalkGraphReq_Include_Options{},
-			Execution: &WalkGraphReq_Include_Options{},
-		}
-	} else {
-		if w.Include.Quest == nil {
-			w.Include.Quest = &WalkGraphReq_Include_Options{}
-		} else if w.Include.Quest.Result || w.Include.Quest.Abnormal || w.Include.Quest.Expired {
-			return errors.New("include.quest does not support result, abnormal or expired")
-		}
-
-		if w.Include.Attempt == nil {
-			w.Include.Attempt = &WalkGraphReq_Include_Options{}
-		} else {
-			if w.Include.Attempt.Result {
-				w.Include.Attempt.Data = true
-			}
-		}
-
-		if w.Include.Execution == nil {
-			w.Include.Execution = &WalkGraphReq_Include_Options{}
-		}
-	}
-
-	if w.Exclude == nil {
-		w.Exclude = &WalkGraphReq_Exclude{}
-	}
-	return w.Exclude.Normalize()
-}
diff --git a/dm/api/template/gen.go b/dm/api/template/gen.go
deleted file mode 100644
index b8b5fb6..0000000
--- a/dm/api/template/gen.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dmTemplate
-
-//go:generate cproto
diff --git a/dm/api/template/loader.go b/dm/api/template/loader.go
deleted file mode 100644
index b2c7e50..0000000
--- a/dm/api/template/loader.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dmTemplate
-
-import (
-	"context"
-	"fmt"
-
-	"go.chromium.org/luci/common/data/text/templateproto"
-	"go.chromium.org/luci/config"
-	"go.chromium.org/luci/config/cfgclient"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-// LoadFile loads a File by configSet and path.
-func LoadFile(c context.Context, project string) (file *File, vers string, err error) {
-	// If ref is "", this will be a standard project config set.
-	cfgSet := config.ProjectSet(project)
-
-	file = &File{}
-	var meta config.Meta
-	if err = cfgclient.Get(c, cfgSet, "dm/quest_templates.cfg", cfgclient.ProtoText(file), &meta); err != nil {
-		return
-	}
-	vers = meta.ContentHash
-	err = file.Normalize()
-	return
-}
-
-// Render renders the specified template with the given parameters.
-func (f *File) Render(spec *templateproto.Specifier) (*dm.Quest_Desc, error) {
-	t := f.Template[spec.TemplateName]
-	params, err := t.Parameters.Render(spec.Params)
-	if err != nil {
-		return nil, fmt.Errorf("rendering %q: field distributor parameters: %s", spec.TemplateName, err)
-	}
-	distribParams, err := t.DistributorParameters.Render(spec.Params)
-	if err != nil {
-		return nil, fmt.Errorf("rendering %q: field distributor parameters: %s", spec.TemplateName, err)
-	}
-	return &dm.Quest_Desc{
-		DistributorConfigName: t.DistributorConfigName,
-		Parameters:            params,
-		DistributorParameters: distribParams,
-		Meta:                  t.Meta,
-	}, nil
-}
diff --git a/dm/api/template/normalize.go b/dm/api/template/normalize.go
deleted file mode 100644
index 091c51a..0000000
--- a/dm/api/template/normalize.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dmTemplate
-
-import "fmt"
-
-// Normalize will normalize all of the Templates in this message, returning an
-// error if any are invalid.
-func (f *File) Normalize() error {
-	for tempName, t := range f.Template {
-		if err := t.Normalize(); err != nil {
-			return fmt.Errorf("template %q: %s", tempName, err)
-		}
-	}
-	return nil
-}
-
-// Normalize will normalize this Template, returning an error if it is invalid.
-func (t *File_Template) Normalize() error {
-	if t.DistributorConfigName == "" {
-		return fmt.Errorf("missing distributor_config_name")
-	}
-	if err := t.Parameters.Normalize(); err != nil {
-		return err
-	}
-	if err := t.DistributorParameters.Normalize(); err != nil {
-		return err
-	}
-	return nil
-}
diff --git a/dm/api/template/template.pb.go b/dm/api/template/template.pb.go
deleted file mode 100644
index e2d21ee..0000000
--- a/dm/api/template/template.pb.go
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.27.1
-// 	protoc        v3.17.3
-// source: go.chromium.org/luci/dm/api/template/template.proto
-
-package dmTemplate
-
-import (
-	templateproto "go.chromium.org/luci/common/data/text/templateproto"
-	v1 "go.chromium.org/luci/dm/api/service/v1"
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// File represents a file full of DM template definitions.
-type File struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Template map[string]*File_Template `protobuf:"bytes,1,rep,name=template,proto3" json:"template,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-}
-
-func (x *File) Reset() {
-	*x = File{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_template_template_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *File) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*File) ProtoMessage() {}
-
-func (x *File) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_template_template_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use File.ProtoReflect.Descriptor instead.
-func (*File) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_template_template_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *File) GetTemplate() map[string]*File_Template {
-	if x != nil {
-		return x.Template
-	}
-	return nil
-}
-
-// Template defines a single template.
-type File_Template struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	DistributorConfigName string                       `protobuf:"bytes,1,opt,name=distributor_config_name,json=distributorConfigName,proto3" json:"distributor_config_name,omitempty"`
-	Parameters            *templateproto.File_Template `protobuf:"bytes,2,opt,name=parameters,proto3" json:"parameters,omitempty"`
-	DistributorParameters *templateproto.File_Template `protobuf:"bytes,3,opt,name=distributor_parameters,json=distributorParameters,proto3" json:"distributor_parameters,omitempty"`
-	Meta                  *v1.Quest_Desc_Meta          `protobuf:"bytes,4,opt,name=meta,proto3" json:"meta,omitempty"`
-}
-
-func (x *File_Template) Reset() {
-	*x = File_Template{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_go_chromium_org_luci_dm_api_template_template_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *File_Template) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*File_Template) ProtoMessage() {}
-
-func (x *File_Template) ProtoReflect() protoreflect.Message {
-	mi := &file_go_chromium_org_luci_dm_api_template_template_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use File_Template.ProtoReflect.Descriptor instead.
-func (*File_Template) Descriptor() ([]byte, []int) {
-	return file_go_chromium_org_luci_dm_api_template_template_proto_rawDescGZIP(), []int{0, 0}
-}
-
-func (x *File_Template) GetDistributorConfigName() string {
-	if x != nil {
-		return x.DistributorConfigName
-	}
-	return ""
-}
-
-func (x *File_Template) GetParameters() *templateproto.File_Template {
-	if x != nil {
-		return x.Parameters
-	}
-	return nil
-}
-
-func (x *File_Template) GetDistributorParameters() *templateproto.File_Template {
-	if x != nil {
-		return x.DistributorParameters
-	}
-	return nil
-}
-
-func (x *File_Template) GetMeta() *v1.Quest_Desc_Meta {
-	if x != nil {
-		return x.Meta
-	}
-	return nil
-}
-
-var File_go_chromium_org_luci_dm_api_template_template_proto protoreflect.FileDescriptor
-
-var file_go_chromium_org_luci_dm_api_template_template_proto_rawDesc = []byte{
-	0x0a, 0x33, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x65,
-	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x64, 0x6d, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
-	0x65, 0x1a, 0x42, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f,
-	0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x64,
-	0x61, 0x74, 0x61, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
-	0x65, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x37, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69,
-	0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61,
-	0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72,
-	0x61, 0x70, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9b,
-	0x03, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c,
-	0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x64, 0x6d, 0x54, 0x65,
-	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x54, 0x65, 0x6d, 0x70,
-	0x6c, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c,
-	0x61, 0x74, 0x65, 0x1a, 0xfe, 0x01, 0x0a, 0x08, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
-	0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x5f,
-	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x15, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x43, 0x6f,
-	0x6e, 0x66, 0x69, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61,
-	0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74,
-	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c,
-	0x65, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61,
-	0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x53, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69,
-	0x62, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
-	0x65, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x54, 0x65, 0x6d, 0x70,
-	0x6c, 0x61, 0x74, 0x65, 0x52, 0x15, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f,
-	0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x27, 0x0a, 0x04, 0x6d,
-	0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x6d, 0x2e, 0x51,
-	0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04,
-	0x6d, 0x65, 0x74, 0x61, 0x1a, 0x56, 0x0a, 0x0d, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
-	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x6d, 0x54, 0x65, 0x6d, 0x70, 0x6c,
-	0x61, 0x74, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
-	0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x31, 0x5a, 0x2f,
-	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
-	0x6c, 0x75, 0x63, 0x69, 0x2f, 0x64, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x65, 0x6d, 0x70,
-	0x6c, 0x61, 0x74, 0x65, 0x3b, 0x64, 0x6d, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x62,
-	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_go_chromium_org_luci_dm_api_template_template_proto_rawDescOnce sync.Once
-	file_go_chromium_org_luci_dm_api_template_template_proto_rawDescData = file_go_chromium_org_luci_dm_api_template_template_proto_rawDesc
-)
-
-func file_go_chromium_org_luci_dm_api_template_template_proto_rawDescGZIP() []byte {
-	file_go_chromium_org_luci_dm_api_template_template_proto_rawDescOnce.Do(func() {
-		file_go_chromium_org_luci_dm_api_template_template_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_dm_api_template_template_proto_rawDescData)
-	})
-	return file_go_chromium_org_luci_dm_api_template_template_proto_rawDescData
-}
-
-var file_go_chromium_org_luci_dm_api_template_template_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
-var file_go_chromium_org_luci_dm_api_template_template_proto_goTypes = []interface{}{
-	(*File)(nil),                        // 0: dmTemplate.File
-	(*File_Template)(nil),               // 1: dmTemplate.File.Template
-	nil,                                 // 2: dmTemplate.File.TemplateEntry
-	(*templateproto.File_Template)(nil), // 3: templateproto.File.Template
-	(*v1.Quest_Desc_Meta)(nil),          // 4: dm.Quest.Desc.Meta
-}
-var file_go_chromium_org_luci_dm_api_template_template_proto_depIdxs = []int32{
-	2, // 0: dmTemplate.File.template:type_name -> dmTemplate.File.TemplateEntry
-	3, // 1: dmTemplate.File.Template.parameters:type_name -> templateproto.File.Template
-	3, // 2: dmTemplate.File.Template.distributor_parameters:type_name -> templateproto.File.Template
-	4, // 3: dmTemplate.File.Template.meta:type_name -> dm.Quest.Desc.Meta
-	1, // 4: dmTemplate.File.TemplateEntry.value:type_name -> dmTemplate.File.Template
-	5, // [5:5] is the sub-list for method output_type
-	5, // [5:5] is the sub-list for method input_type
-	5, // [5:5] is the sub-list for extension type_name
-	5, // [5:5] is the sub-list for extension extendee
-	0, // [0:5] is the sub-list for field type_name
-}
-
-func init() { file_go_chromium_org_luci_dm_api_template_template_proto_init() }
-func file_go_chromium_org_luci_dm_api_template_template_proto_init() {
-	if File_go_chromium_org_luci_dm_api_template_template_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_go_chromium_org_luci_dm_api_template_template_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*File); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_go_chromium_org_luci_dm_api_template_template_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*File_Template); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_go_chromium_org_luci_dm_api_template_template_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   3,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_go_chromium_org_luci_dm_api_template_template_proto_goTypes,
-		DependencyIndexes: file_go_chromium_org_luci_dm_api_template_template_proto_depIdxs,
-		MessageInfos:      file_go_chromium_org_luci_dm_api_template_template_proto_msgTypes,
-	}.Build()
-	File_go_chromium_org_luci_dm_api_template_template_proto = out.File
-	file_go_chromium_org_luci_dm_api_template_template_proto_rawDesc = nil
-	file_go_chromium_org_luci_dm_api_template_template_proto_goTypes = nil
-	file_go_chromium_org_luci_dm_api_template_template_proto_depIdxs = nil
-}
diff --git a/dm/api/template/template.proto b/dm/api/template/template.proto
deleted file mode 100644
index e81a0c2..0000000
--- a/dm/api/template/template.proto
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-syntax = "proto3";
-
-option go_package = "go.chromium.org/luci/dm/api/template;dmTemplate";
-
-import "go.chromium.org/luci/common/data/text/templateproto/template.proto";
-import "go.chromium.org/luci/dm/api/service/v1/graph_data.proto";
-
-package dmTemplate;
-
-// File represents a file full of DM template definitions.
-message File {
-  // Template defines a single template.
-  message Template {
-    string distributor_config_name = 1;
-    templateproto.File.Template parameters = 2;
-    templateproto.File.Template distributor_parameters = 3;
-    dm.Quest.Desc.Meta meta = 4;
-  }
-  map<string, Template> template = 1;
-}
diff --git a/dm/appengine/.gitignore b/dm/appengine/.gitignore
deleted file mode 100644
index 9a08a60..0000000
--- a/dm/appengine/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Integration tests use devcfg directory (a symlink actually) to supply configs
-# to the locally running DM instance. See integration_tests/*.
-devcfg
diff --git a/dm/appengine/deps/activate_execution.go b/dm/appengine/deps/activate_execution.go
deleted file mode 100644
index 29dfddb..0000000
--- a/dm/appengine/deps/activate_execution.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"context"
-
-	"google.golang.org/protobuf/types/known/emptypb"
-
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/mutate"
-)
-
-func (d *deps) ActivateExecution(c context.Context, req *dm.ActivateExecutionReq) (ret *emptypb.Empty, err error) {
-	ret = &emptypb.Empty{}
-	logging.Fields{"execution": req.Auth.Id}.Infof(c, "activating")
-	err = tumbleNow(c, &mutate.ActivateExecution{
-		Auth:   req.Auth,
-		NewTok: req.ExecutionToken,
-	})
-	return
-}
diff --git a/dm/appengine/deps/activate_execution_test.go b/dm/appengine/deps/activate_execution_test.go
deleted file mode 100644
index 87e47d8..0000000
--- a/dm/appengine/deps/activate_execution_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor/fake"
-)
-
-func TestActivateExecution(t *testing.T) {
-	t.Parallel()
-
-	Convey("Test ActivateExecution", t, func() {
-		ttest, c, dist, s := testSetup()
-
-		qid := s.ensureQuest(c, "foo", 1)
-		ttest.Drain(c)
-
-		eid := dm.NewExecutionID(qid, 1, 1)
-		dist.RunTask(c, eid, func(tsk *fake.Task) error {
-			req := &dm.ActivateExecutionReq{
-				Auth:           &dm.Execution_Auth{Id: eid},
-				ExecutionToken: []byte("sufficiently long new 'random' token"),
-			}
-
-			Convey("bad", func() {
-				Convey("wrong token", func() {
-					_, err := s.ActivateExecution(c, req)
-					So(err, ShouldBeRPCPermissionDenied, "failed to activate")
-				})
-
-				Convey("wrong token (already activated)", func() {
-					req.Auth.Token = tsk.Auth.Token
-					_, err := s.ActivateExecution(c, req)
-					So(err, ShouldBeNil)
-
-					req.Auth.Token = []byte("bad sekret")
-					req.ExecutionToken = []byte("random other super duper long token")
-					_, err = s.ActivateExecution(c, req)
-					So(err, ShouldBeRPCPermissionDenied, "failed to activate")
-				})
-
-				Convey("concurrent activation", func() {
-					req.Auth.Token = tsk.Auth.Token
-					_, err := s.ActivateExecution(c, req)
-					So(err, ShouldBeNil)
-
-					req.ExecutionToken = append(req.ExecutionToken, []byte(" (but incorrect)")...)
-					_, err = s.ActivateExecution(c, req)
-					So(err, ShouldBeRPCPermissionDenied, "failed to activate")
-				})
-			})
-
-			Convey("good", func() {
-				req.Auth.Token = tsk.Auth.Token
-
-				Convey("normal activation", func() {
-					_, err := s.ActivateExecution(c, req)
-					So(err, ShouldBeNil)
-				})
-
-				Convey("repeated activation", func() {
-					_, err := s.ActivateExecution(c, req)
-					So(err, ShouldBeNil)
-					_, err = s.ActivateExecution(c, req)
-					So(err, ShouldBeNil)
-				})
-			})
-			return nil
-		})
-	})
-}
diff --git a/dm/appengine/deps/add_deps_test.go b/dm/appengine/deps/add_deps_test.go
deleted file mode 100644
index bd745cc..0000000
--- a/dm/appengine/deps/add_deps_test.go
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"testing"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor/fake"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestAddDeps(t *testing.T) {
-	t.Parallel()
-
-	Convey("EnsureGraphData (Adding deps)", t, func() {
-		ttest, c, dist, s := testSetup()
-		c = writer(c)
-
-		qid := s.ensureQuest(c, "quest", 1)
-
-		Convey("Bad", func() {
-			req := &dm.EnsureGraphDataReq{
-				RawAttempts: dm.NewAttemptList(map[string][]uint32{
-					"fakeQuestId": {1},
-				}),
-			}
-
-			Convey("No such originating attempt", func() {
-				dist.RunTask(c, dm.NewExecutionID(qid, 1, 1), func(tsk *fake.Task) error {
-					aTsk := tsk.MustActivate(c, s)
-
-					_, err := aTsk.EnsureGraphData(req)
-					So(err, ShouldBeRPCInvalidArgument, `cannot create attempts for absent quest "-asJkTOx8ORdkGZsg7Bc-w2Z_0FIB4vgD1afzInkwNE"`)
-					return nil
-				})
-			})
-		})
-
-		toQuest := s.ensureQuest(c, "to", 1)
-		toQuestDesc := fake.QuestDesc("to")
-		req := &dm.EnsureGraphDataReq{
-			RawAttempts: dm.NewAttemptList(map[string][]uint32{
-				toQuest: {1},
-			}),
-		}
-		fwd := model.FwdDepsFromList(c,
-			dm.NewAttemptID(qid, 1),
-			dm.NewAttemptList(map[string][]uint32{toQuest: {1}}),
-		)[0]
-		ttest.Drain(c)
-
-		Convey("Good", func() {
-			Convey("deps already exist", func() {
-				err := dist.RunTask(c, dm.NewExecutionID(qid, 1, 1), func(tsk *fake.Task) error {
-					aTsk := tsk.MustActivate(c, s)
-
-					rsp, err := aTsk.EnsureGraphData(req)
-					So(err, ShouldBeNil)
-					rsp.Result.PurgeTimestamps()
-					So(rsp, ShouldResemble, &dm.EnsureGraphDataRsp{
-						Accepted:   true,
-						ShouldHalt: true,
-					})
-					return nil
-				})
-				So(err, ShouldBeNil)
-			})
-
-			Convey("deps already done", func() {
-				err := dist.RunTask(c, dm.NewExecutionID(toQuest, 1, 1), func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).Finish(`{"done":true}`)
-					return nil
-				})
-				So(err, ShouldBeNil)
-				ttest.Drain(c)
-
-				err = dist.RunTask(c, dm.NewExecutionID(qid, 1, 1), func(tsk *fake.Task) error {
-					aTsk := tsk.MustActivate(c, s)
-
-					req.Normalize() // to ensure the next assignment works
-					req.Include.Attempt.Result = true
-
-					rsp, err := aTsk.EnsureGraphData(req)
-					So(err, ShouldBeNil)
-					rsp.Result.PurgeTimestamps()
-					exAttempt := dm.NewAttemptFinished(dm.NewJsonResult(`{"done":true}`))
-					exAttempt.Data.NumExecutions = 1
-					So(rsp, ShouldResembleProto, &dm.EnsureGraphDataRsp{
-						Accepted: true,
-						Result: &dm.GraphData{Quests: map[string]*dm.Quest{
-							toQuest: {
-								Data: &dm.Quest_Data{
-									Desc:    toQuestDesc,
-									BuiltBy: []*dm.Quest_TemplateSpec{},
-								},
-								Attempts: map[uint32]*dm.Attempt{1: exAttempt},
-							},
-						}},
-					})
-					return nil
-				})
-				So(err, ShouldBeNil)
-
-				ttest.Drain(c)
-
-				So(ds.Get(c, fwd), ShouldBeNil)
-			})
-
-			Convey("adding new deps", func() {
-				err := dist.RunTask(c, dm.NewExecutionID(qid, 1, 1), func(tsk *fake.Task) error {
-					aTsk := tsk.MustActivate(c, s)
-
-					rsp, err := aTsk.EnsureGraphData(req)
-					So(err, ShouldBeNil)
-					So(rsp, ShouldResemble, &dm.EnsureGraphDataRsp{
-						Accepted:   true,
-						ShouldHalt: true,
-					})
-
-					So(ds.Get(c, fwd), ShouldBeNil)
-					a := model.AttemptFromID(dm.NewAttemptID(qid, 1))
-					So(ds.Get(c, a), ShouldBeNil)
-					So(a.State, ShouldEqual, dm.Attempt_EXECUTING)
-					e := model.ExecutionFromID(c, dm.NewExecutionID(qid, 1, 1))
-					So(ds.Get(c, e), ShouldBeNil)
-					So(e.State, ShouldEqual, dm.Execution_STOPPING)
-					return nil
-				})
-				So(err, ShouldBeNil)
-			})
-
-		})
-	})
-}
diff --git a/dm/appengine/deps/auth.go b/dm/appengine/deps/auth.go
deleted file mode 100644
index a0e2cc6..0000000
--- a/dm/appengine/deps/auth.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"context"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/retry/transient"
-	"go.chromium.org/luci/config/cfgclient"
-	"go.chromium.org/luci/dm/api/acls"
-	"go.chromium.org/luci/grpc/grpcutil"
-	"go.chromium.org/luci/server/auth"
-
-	"google.golang.org/grpc/codes"
-)
-
-func loadAcls(c context.Context) (ret *acls.Acls, err error) {
-	ret = &acls.Acls{}
-	if err := cfgclient.Get(c, "services/${appid}", "acls.cfg", cfgclient.ProtoText(ret), nil); err != nil {
-		return nil, errors.Annotate(err, "").Tag(transient.Tag).
-			InternalReason("loading config :: acls.cfg").Err()
-	}
-	return
-}
-
-func inGroups(c context.Context, groups []string) error {
-	for _, grp := range groups {
-		ok, err := auth.IsMember(c, grp)
-		if err != nil {
-			return grpcAnnotate(err, codes.Internal, "failed group check").Err()
-		}
-		if ok {
-			return nil
-		}
-	}
-	logging.Fields{
-		"ident":  auth.CurrentIdentity(c),
-		"groups": groups,
-	}.Infof(c, "not authorized")
-	return grpcutil.Errf(codes.PermissionDenied, "not authorized")
-}
-
-func canRead(c context.Context) (err error) {
-	acl, err := loadAcls(c)
-	if err != nil {
-		return
-	}
-	if err = inGroups(c, acl.Readers); grpcutil.Code(err) == codes.PermissionDenied {
-		err = inGroups(c, acl.Writers)
-	}
-	return
-}
-
-func canWrite(c context.Context) (err error) {
-	acl, err := loadAcls(c)
-	if err != nil {
-		return
-	}
-	return inGroups(c, acl.Writers)
-}
diff --git a/dm/appengine/deps/common_test.go b/dm/appengine/deps/common_test.go
deleted file mode 100644
index 4ca9465..0000000
--- a/dm/appengine/deps/common_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"context"
-	"fmt"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor/fake"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/dm/appengine/mutate"
-	"go.chromium.org/luci/server/auth"
-	"go.chromium.org/luci/server/auth/authtest"
-	"go.chromium.org/luci/tumble"
-)
-
-func testSetup() (ttest *tumble.Testing, c context.Context, dist *fake.Distributor, s testDepsServer) {
-	ttest, c, dist = fake.Setup(mutate.FinishExecutionFn)
-	s = testDepsServer{newDecoratedDeps()}
-	return
-}
-
-func reader(c context.Context) context.Context {
-	return auth.WithState(c, &authtest.FakeState{
-		Identity:       "test@example.com",
-		IdentityGroups: []string{"reader_group"},
-	})
-}
-
-func writer(c context.Context) context.Context {
-	return auth.WithState(c, &authtest.FakeState{
-		Identity:       "test@example.com",
-		IdentityGroups: []string{"reader_group", "writer_group"},
-	})
-}
-
-type testDepsServer struct {
-	dm.DepsServer
-}
-
-func (s testDepsServer) ensureQuest(c context.Context, name string, aids ...uint32) string {
-	desc := fake.QuestDesc(name)
-	q := model.NewQuest(c, desc)
-	qsts, err := s.EnsureGraphData(writer(c), &dm.EnsureGraphDataReq{
-		Quest:        []*dm.Quest_Desc{desc},
-		QuestAttempt: []*dm.AttemptList_Nums{{Nums: aids}},
-	})
-	if err != nil {
-		panic(err)
-	}
-	for qid := range qsts.Result.Quests {
-		if qid != q.ID {
-			panic(fmt.Errorf("non matching quest ID!? got %q, expected %q", qid, q.ID))
-		}
-		return qid
-	}
-	panic("impossible")
-}
diff --git a/dm/appengine/deps/doc.go b/dm/appengine/deps/doc.go
deleted file mode 100644
index fb29de2..0000000
--- a/dm/appengine/deps/doc.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package deps implements DM's Deps RPC methods. It mostly coordinates code
-// between other DM subpackages, notably 'mutate', 'model' and 'display'.
-package deps
diff --git a/dm/appengine/deps/ensure_attempt_test.go b/dm/appengine/deps/ensure_attempt_test.go
deleted file mode 100644
index d642e6e..0000000
--- a/dm/appengine/deps/ensure_attempt_test.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"testing"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestEnsureAttempt(t *testing.T) {
-	t.Parallel()
-
-	Convey("EnsureGraphData (Ensuring attempts)", t, func() {
-		ttest, c, _, s := testSetup()
-
-		Convey("bad", func() {
-			Convey("no quest", func() {
-				_, err := s.EnsureGraphData(writer(c), &dm.EnsureGraphDataReq{
-					RawAttempts: dm.NewAttemptList(map[string][]uint32{"quest": {1}}),
-				})
-				So(err, ShouldBeRPCInvalidArgument,
-					`cannot create attempts for absent quest "quest"`)
-			})
-			Convey("mismatched quest", func() {
-				_, err := s.EnsureGraphData(writer(c), &dm.EnsureGraphDataReq{
-					Quest: []*dm.Quest_Desc{dm.NewQuestDesc("fakeDistributor", "{}", "{}", nil)},
-				})
-				So(err, ShouldErrLike, "mismatched quest_attempt v. quest lengths")
-			})
-			Convey("no auth", func() {
-				desc := dm.NewQuestDesc("fakeDistributor", `{"hi": "there"}`, "{}", nil)
-				_, err := s.EnsureGraphData(c, &dm.EnsureGraphDataReq{
-					Quest:        []*dm.Quest_Desc{desc},
-					QuestAttempt: []*dm.AttemptList_Nums{{Nums: []uint32{1}}},
-				})
-				So(err, ShouldBeRPCPermissionDenied, `not authorized`)
-			})
-		})
-
-		Convey("good", func() {
-			desc := dm.NewQuestDesc("fakeDistributor", `{"hi": "there"}`, "{}", nil)
-			So(desc.Normalize(), ShouldBeNil)
-			q := model.NewQuest(c, desc)
-			rsp, err := s.EnsureGraphData(writer(c), &dm.EnsureGraphDataReq{
-				Quest:        []*dm.Quest_Desc{desc},
-				QuestAttempt: []*dm.AttemptList_Nums{{Nums: []uint32{1}}},
-			})
-			So(err, ShouldBeNil)
-			So(rsp.Accepted, ShouldBeTrue)
-			ttest.Drain(c)
-			So(ds.Get(c, &model.Attempt{ID: *dm.NewAttemptID(q.ID, 1)}), ShouldBeNil)
-		})
-
-	})
-}
diff --git a/dm/appengine/deps/ensure_graph_data.go b/dm/appengine/deps/ensure_graph_data.go
deleted file mode 100644
index 3ad7fff..0000000
--- a/dm/appengine/deps/ensure_graph_data.go
+++ /dev/null
@@ -1,399 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"context"
-	"fmt"
-
-	"google.golang.org/grpc/codes"
-
-	"google.golang.org/protobuf/proto"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	"go.chromium.org/luci/common/data/stringset"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/sync/parallel"
-	"go.chromium.org/luci/grpc/grpcutil"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	dmTemplate "go.chromium.org/luci/dm/api/template"
-
-	"go.chromium.org/luci/tumble"
-
-	"go.chromium.org/luci/dm/appengine/distributor"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/dm/appengine/mutate"
-)
-
-func (d *deps) runEnsureGraphDepsWalk(c context.Context, req *dm.EnsureGraphDataReq, newAttempts *dm.AttemptList) (*dm.GraphData, error) {
-	// first lets run a query to load all of the proposed attempts.
-	wgreq := &dm.WalkGraphReq{
-		Query: dm.AttemptListQuery(newAttempts),
-		Limit: &dm.WalkGraphReq_Limit{
-			MaxDepth:    1,
-			MaxDataSize: req.Limit.MaxDataSize,
-		},
-		Include: &dm.WalkGraphReq_Include{
-			Quest: &dm.WalkGraphReq_Include_Options{Data: true},
-			Attempt: &dm.WalkGraphReq_Include_Options{
-				Abnormal: true,
-				Expired:  true,
-				Data:     true,
-				Result:   req.Include.Attempt.Result,
-			},
-		},
-	}
-	if err := wgreq.Normalize(); err != nil {
-		panic(err)
-	}
-	qryRsp, err := doGraphWalk(c, wgreq)
-	if err != nil {
-		return nil, err
-	}
-	if qryRsp.HadErrors {
-		return nil, grpcutil.Internal
-	}
-	return qryRsp, nil
-}
-
-func allFinished(gd *dm.GraphData) bool {
-	for _, qst := range gd.Quests {
-		if qst.DNE {
-			return false
-		}
-		for _, atmpt := range qst.Attempts {
-			if atmpt.DNE || atmpt.Data.GetFinished() == nil {
-				return false
-			}
-		}
-	}
-	return true
-}
-
-func filterQuestsByNewTemplateData(g *dm.GraphData, newQuests []*model.Quest) (ret []*model.Quest, quests stringset.Set) {
-	quests = stringset.New(0)
-	for _, q := range newQuests {
-		curQuest := g.Quests[q.ID]
-		if curQuest.DNE || !q.BuiltBy.EqualsData(curQuest.Data.BuiltBy) {
-			ret = append(ret, q)
-			quests.Add(q.ID)
-		}
-	}
-	return
-}
-
-func filterAttemptsByDNE(gd *dm.GraphData, newAttempts *dm.AttemptList, newQuestSet stringset.Set) (ret *dm.AttemptList, count int, err error) {
-	ret = dm.NewAttemptList(nil)
-	tmpAID := &dm.Attempt_ID{}
-	nums := &dm.AttemptList_Nums{}
-	for tmpAID.Quest, nums = range newAttempts.To {
-		if gd.Quests[tmpAID.Quest].DNE && !newQuestSet.Has(tmpAID.Quest) {
-			err = fmt.Errorf("cannot create attempts for absent quest %q", tmpAID.Quest)
-			return
-		}
-		for _, tmpAID.Id = range nums.Nums {
-			if gd.Quests[tmpAID.Quest].Attempts[tmpAID.Id].DNE {
-				count++
-				ret.AddAIDs(tmpAID)
-			}
-		}
-	}
-	return
-}
-
-func depsFromMissing(c context.Context, fwdDepKeys []*ds.Key, exists ds.BoolList) (ret *dm.AttemptList) {
-	ret = dm.NewAttemptList(nil)
-	tmpAID := &dm.Attempt_ID{}
-	for i, fkey := range fwdDepKeys {
-		if !exists[i] {
-			if err := tmpAID.SetDMEncoded(fkey.StringID()); err != nil {
-				logging.Fields{
-					logging.ErrorKey:  err,
-					"FwdDep.StringID": fkey.StringID(),
-				}.Errorf(c, "impossible parsing error")
-				panic(err)
-			}
-			ret.AddAIDs(tmpAID)
-		}
-	}
-	return
-}
-
-func journalQuestAttempts(c context.Context, newQuests []*model.Quest, newAttempts *dm.AttemptList) error {
-	if len(newQuests) == 0 && len(newAttempts.To) == 0 {
-		return nil
-	}
-	newAttempts = newAttempts.Dup()
-	muts := make([]tumble.Mutation, 0, len(newQuests)+len(newAttempts.To))
-	for _, q := range newQuests {
-		mut := &mutate.EnsureQuestAttempts{Quest: q}
-		if nums, ok := newAttempts.To[q.ID]; ok {
-			delete(newAttempts.To, q.ID)
-			mut.AIDs = nums.Nums
-		}
-		muts = append(muts, mut)
-	}
-	for qid, nums := range newAttempts.To {
-		muts = append(muts, &mutate.EnsureQuestAttempts{
-			Quest:           &model.Quest{ID: qid},
-			AIDs:            nums.Nums,
-			DoNotMergeQuest: true,
-		})
-	}
-	return grpcAnnotate(tumble.AddToJournal(c, muts...), codes.Internal, "attempting to journal").Err()
-}
-
-func (d *deps) ensureGraphData(c context.Context, req *dm.EnsureGraphDataReq, newQuests []*model.Quest, newAttempts *dm.AttemptList, rsp *dm.EnsureGraphDataRsp) (err error) {
-	var (
-		fwdDepExists *ds.ExistsResult
-		fwdDepKeys   []*ds.Key
-	)
-	if req.ForExecution != nil {
-		fwdDepKeys = model.FwdDepKeysFromList(c, req.ForExecution.Id.AttemptID(), newAttempts)
-	}
-	// Do a graph walk for all of the newAttempts, and also check the existence
-	// of all proposed deps (if needed).
-	err = parallel.FanOutIn(func(gen chan<- func() error) {
-		gen <- func() error {
-			rsp.Result, err = d.runEnsureGraphDepsWalk(c, req, newAttempts)
-			if err != nil {
-				err = fmt.Errorf("while walking graph: %s", err)
-			}
-			return err
-		}
-		if req.ForExecution != nil {
-			gen <- func() (err error) {
-				fwdDepExists, err = ds.Exists(c, fwdDepKeys)
-				if err != nil {
-					err = fmt.Errorf("while finding FwdDeps: %s", err)
-				}
-				return err
-			}
-		}
-	})
-	if err != nil {
-		return grpcAnnotate(err, codes.Internal, "failed to gather prerequisites").Err()
-	}
-
-	// Now that we've walked the graph, prune the lists of new Quest and Attempts
-	// by the information retrieved in the graph walk. newQuest and newAttempts
-	// will be reduced to contain only the missing information.
-	newQuests, newQuestSet := filterQuestsByNewTemplateData(rsp.Result, newQuests)
-	newAttempts, newAttemptsLen, err := filterAttemptsByDNE(rsp.Result, newAttempts, newQuestSet)
-	if err != nil {
-		return grpcAnnotate(err, codes.InvalidArgument, "filterAttemptsByDNE").Err()
-	}
-
-	// we're just asserting nodes, no edges, so journal whatever's left
-	if req.ForExecution == nil {
-		logging.Fields{"qs": len(newQuests), "atmpts": newAttemptsLen}.Infof(c,
-			"journaling without deps")
-		err := journalQuestAttempts(c, newQuests, newAttempts)
-		rsp.Accepted = err == nil
-		return err
-	}
-
-	// we're asserting nodes+edges
-	missingDeps := depsFromMissing(c, fwdDepKeys, fwdDepExists.List(0))
-
-	// we have no missing deps, or all the attempts we want are finished already
-	if len(missingDeps.To) == 0 || allFinished(rsp.Result) {
-		// if we have new quests to journal, or deps to add, journal them.
-		if len(newQuests) > 0 || len(missingDeps.To) > 0 {
-			err = tumbleNow(c, &mutate.AddFinishedDeps{
-				Auth:             req.ForExecution,
-				MergeQuests:      newQuests,
-				FinishedAttempts: missingDeps,
-			})
-			rsp.Accepted = err == nil
-			return
-		}
-
-		// otherwise we're done already
-		rsp.Accepted = true
-		return nil
-	}
-
-	// not all of the attemps exist/are finished, we have to block.
-	rsp.Result = nil
-	err = tumbleNow(c, &mutate.AddDeps{
-		Auth:   req.ForExecution,
-		Quests: newQuests,
-		// Attempts we think are missing
-		Attempts: newAttempts,
-		// Deps we think are missing (>= newAttempts)
-		Deps: missingDeps,
-	})
-	if err == nil {
-		rsp.Accepted = true
-		rsp.ShouldHalt = true
-	}
-	return err
-}
-
-type templateFile struct {
-	file    *dmTemplate.File
-	version string
-}
-
-type templateFileCache map[string]templateFile // project => templateFile
-
-func (cache templateFileCache) render(c context.Context, inst *dm.TemplateInstantiation) (desc *dm.Quest_Desc, vers string, err error) {
-	f, ok := cache[inst.Project]
-	if !ok {
-		f.file, f.version, err = dmTemplate.LoadFile(c, inst.Project)
-		if err != nil {
-			err = fmt.Errorf("failed to load templates %q: %s", inst.Project, err)
-			return
-		}
-		cache[inst.Project] = f
-	}
-	vers = f.version
-	desc, err = f.file.Render(inst.Specifier)
-	return
-}
-
-func renderRequest(c context.Context, req *dm.EnsureGraphDataReq) (rsp *dm.EnsureGraphDataRsp, newQuests map[string]*model.Quest, newAttempts *dm.AttemptList, err error) {
-	rsp = &dm.EnsureGraphDataRsp{}
-
-	setTemplateErr := func(i int, err error) bool {
-		if err == nil {
-			return false
-		}
-		if rsp.TemplateError == nil {
-			rsp.TemplateError = make([]string, len(req.TemplateQuest))
-		}
-		rsp.TemplateError[i] = err.Error()
-		return true
-	}
-
-	dists := map[string]distributor.D{}
-
-	newQuests = make(map[string]*model.Quest, len(req.Quest)+len(req.TemplateQuest))
-	newAttempts = proto.Clone(req.RawAttempts).(*dm.AttemptList)
-	if newAttempts == nil {
-		newAttempts = dm.NewAttemptList(nil)
-	}
-
-	reg := distributor.GetRegistry(c)
-
-	// render all quest descriptions
-	for i, qDesc := range req.Quest {
-		q := model.NewQuest(c, qDesc)
-
-		d, ok := dists[qDesc.DistributorConfigName]
-		if !ok {
-			if d, _, err = reg.MakeDistributor(c, qDesc.DistributorConfigName); err != nil {
-				return
-			}
-			dists[qDesc.DistributorConfigName] = d
-		}
-
-		if err = d.Validate(qDesc.DistributorParameters); err != nil {
-			err = grpcAnnotate(err, codes.InvalidArgument,
-				"JSON distributor parameters are invalid for this distributor configuration.").Err()
-			return
-		}
-
-		if _, ok := newQuests[q.ID]; !ok {
-			newQuests[q.ID] = q
-		}
-		rsp.QuestIds = append(rsp.QuestIds, dm.NewQuestID(q.ID))
-		anums := newAttempts.To[q.ID]
-		if anums == nil {
-			anums = &dm.AttemptList_Nums{}
-			newAttempts.To[q.ID] = anums
-		}
-		anums.Nums = append(anums.Nums, req.QuestAttempt[i].Nums...)
-		if err := anums.Normalize(); err != nil {
-			logging.Errorf(c, "impossible: these inputs were already validated: %s", err)
-			panic(err)
-		}
-	}
-
-	// render all templates and template attempts into newQuests
-	templateFiles := templateFileCache{}
-	for i := 0; i < len(req.TemplateQuest); i++ {
-		inst := req.TemplateQuest[i]
-
-		var vers string
-		var desc *dm.Quest_Desc
-		if desc, vers, err = templateFiles.render(c, inst); setTemplateErr(i, err) {
-			continue
-		}
-		if setTemplateErr(i, desc.Normalize()) {
-			continue
-		}
-
-		q := model.NewQuest(c, desc)
-
-		rsp.TemplateIds = append(rsp.TemplateIds, dm.NewQuestID(q.ID))
-
-		// if we have any errors going on, might as well skip the rest
-		if len(rsp.TemplateError) > 0 {
-			continue
-		}
-
-		anums := newAttempts.To[q.ID]
-		anums.Nums = append(anums.Nums, req.TemplateAttempt[i].Nums...)
-		if err := anums.Normalize(); err != nil {
-			logging.WithError(err).Errorf(c, "impossible: these inputs were already validated")
-			panic(err)
-		}
-
-		toAddTemplateInfo, ok := newQuests[q.ID]
-		if !ok {
-			toAddTemplateInfo = q
-			newQuests[q.ID] = q
-		}
-		toAddTemplateInfo.BuiltBy.Add(dm.Quest_TemplateSpec{
-			Project: inst.Project, Ref: inst.Ref, Version: vers,
-			Name: inst.Specifier.TemplateName})
-	}
-
-	return
-}
-
-func (d *deps) EnsureGraphData(c context.Context, req *dm.EnsureGraphDataReq) (rsp *dm.EnsureGraphDataRsp, err error) {
-	if req.ForExecution != nil {
-		logging.Fields{"execution": req.ForExecution.Id}.Infof(c, "on behalf of")
-		_, _, err := model.AuthenticateExecution(c, req.ForExecution)
-		if err != nil {
-			return nil, grpcAnnotate(err, codes.Unauthenticated, "bad execution auth").Err()
-		}
-	} else {
-		if err = canWrite(c); err != nil {
-			return
-		}
-	}
-
-	// render any quest descriptions, templates and template attempts into
-	// a single merged set of new quests and new attempts
-	rsp, newQuests, newAttempts, err := renderRequest(c, req)
-	if err != nil || len(rsp.TemplateError) > 0 {
-		return
-	}
-
-	newQuestList := make([]*model.Quest, 0, len(newQuests))
-	for _, q := range newQuests {
-		newQuestList = append(newQuestList, q)
-	}
-
-	err = d.ensureGraphData(c, req, newQuestList, newAttempts, rsp)
-
-	return
-}
diff --git a/dm/appengine/deps/ensure_quests_test.go b/dm/appengine/deps/ensure_quests_test.go
deleted file mode 100644
index 5f3242b..0000000
--- a/dm/appengine/deps/ensure_quests_test.go
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"testing"
-	"time"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/clock/testclock"
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestEnsureQuests(t *testing.T) {
-	t.Parallel()
-
-	desc := func(payload string) *dm.Quest_Desc {
-		return &dm.Quest_Desc{
-			DistributorConfigName: "fakeDistributor",
-			Parameters:            payload,
-			DistributorParameters: "{}",
-		}
-	}
-
-	assertSameQuests := func(a, b map[string]*dm.Quest) {
-		So(a, ShouldHaveLength, len(b))
-		for id := range a {
-			So(a[id], ShouldResembleProto, b[id])
-		}
-	}
-
-	Convey("EnsureGraphData (Ensure Quests)", t, func() {
-		ttest, c, _, s := testSetup()
-		c = writer(c)
-		clk := clock.Get(c).(testclock.TestClock)
-
-		Convey("bad", func() {
-			// TODO(riannucci): restore this once moving to the new distributor scheme
-			/*
-				Convey("missing distributor", func() {
-					_, err := s.EnsureQuests(c, &dm.EnsureQuestsReq{
-						ToEnsure: []*dm.Quest_Desc{desc("{}")},
-					})
-					So(err, ShouldErrLike, "unknown distributors")
-				})
-			*/
-		})
-
-		Convey("good", func() {
-			// TODO(riannucci): add fakeDistributor distributor configuration
-
-			qd := desc(`{"data": "yes"}`)
-			So(qd.Normalize(), ShouldBeNil)
-			q := model.NewQuest(c, qd)
-
-			qd2 := desc(`{"data": "way yes"}`)
-			So(qd2.Normalize(), ShouldBeNil)
-			q2 := model.NewQuest(c, qd2)
-
-			req := &dm.EnsureGraphDataReq{
-				Quest: []*dm.Quest_Desc{qd, qd2},
-				QuestAttempt: []*dm.AttemptList_Nums{
-					{Nums: []uint32{1}},
-					{Nums: []uint32{2}},
-				}}
-
-			Convey("0/2 exist", func() {
-				rsp, err := s.EnsureGraphData(c, req)
-				So(err, ShouldBeNil)
-				assertSameQuests(rsp.Result.Quests, map[string]*dm.Quest{
-					q.ID:  {DNE: true, Attempts: map[uint32]*dm.Attempt{1: {DNE: true}}},
-					q2.ID: {DNE: true, Attempts: map[uint32]*dm.Attempt{2: {DNE: true}}},
-				})
-				ttest.Drain(c)
-				rsp, err = s.EnsureGraphData(c, req)
-				So(err, ShouldBeNil)
-				rsp.Result.PurgeTimestamps()
-				assertSameQuests(rsp.Result.Quests, map[string]*dm.Quest{
-					q.ID: {
-						Data: &dm.Quest_Data{
-							Desc:    qd,
-							BuiltBy: []*dm.Quest_TemplateSpec{},
-						},
-						Attempts: map[uint32]*dm.Attempt{1: dm.NewAttemptExecuting(1)}},
-					q2.ID: {
-						Data: &dm.Quest_Data{
-							Desc:    qd2,
-							BuiltBy: []*dm.Quest_TemplateSpec{},
-						},
-						Attempts: map[uint32]*dm.Attempt{2: dm.NewAttemptExecuting(1)}},
-				})
-			})
-
-			Convey("1/2 exist", func() {
-				So(ds.Put(c, q), ShouldBeNil)
-
-				clk.Add(time.Minute)
-
-				rsp, err := s.EnsureGraphData(c, req)
-				So(err, ShouldBeNil)
-				rsp.Result.PurgeTimestamps()
-				assertSameQuests(rsp.Result.Quests, map[string]*dm.Quest{
-					q.ID: {
-						Data: &dm.Quest_Data{
-							Desc:    qd,
-							BuiltBy: []*dm.Quest_TemplateSpec{},
-						},
-						Attempts: map[uint32]*dm.Attempt{1: {DNE: true}},
-					},
-					q2.ID: {DNE: true, Attempts: map[uint32]*dm.Attempt{2: {DNE: true}}},
-				})
-				now := clk.Now()
-				ttest.Drain(c)
-
-				qNew := &model.Quest{ID: q.ID}
-				So(ds.Get(c, qNew), ShouldBeNil)
-				So(qNew.Created, ShouldResemble, q.Created)
-
-				q2New := &model.Quest{ID: q2.ID}
-				So(ds.Get(c, q2New), ShouldBeNil)
-				So(q2New.Created, ShouldResemble, now.Round(time.Microsecond))
-			})
-
-			Convey("all exist", func() {
-				So(ds.Put(c, q), ShouldBeNil)
-				So(ds.Put(c, q2), ShouldBeNil)
-
-				rsp, err := s.EnsureGraphData(c, req)
-				So(err, ShouldBeNil)
-				rsp.Result.PurgeTimestamps()
-				assertSameQuests(rsp.Result.Quests, map[string]*dm.Quest{
-					q.ID: {
-						Data: &dm.Quest_Data{
-							Desc:    qd,
-							BuiltBy: []*dm.Quest_TemplateSpec{},
-						},
-						Attempts: map[uint32]*dm.Attempt{1: {DNE: true}}},
-					q2.ID: {
-						Data: &dm.Quest_Data{
-							Desc:    qd2,
-							BuiltBy: []*dm.Quest_TemplateSpec{},
-						},
-						Attempts: map[uint32]*dm.Attempt{2: {DNE: true}}},
-				})
-
-				qNew := &model.Quest{ID: q.ID}
-				So(ds.Get(c, qNew), ShouldBeNil)
-				So(qNew.Created, ShouldResemble, q.Created)
-			})
-		})
-	})
-}
diff --git a/dm/appengine/deps/finish_attempt.go b/dm/appengine/deps/finish_attempt.go
deleted file mode 100644
index 50267a3..0000000
--- a/dm/appengine/deps/finish_attempt.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"context"
-
-	"google.golang.org/protobuf/types/known/emptypb"
-
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/mutate"
-)
-
-func (d *deps) FinishAttempt(c context.Context, req *dm.FinishAttemptReq) (_ *emptypb.Empty, err error) {
-	logging.Fields{"execution": req.Auth.Id}.Infof(c, "finishing")
-	return &emptypb.Empty{}, tumbleNow(c, &mutate.FinishAttempt{
-		FinishAttemptReq: *req})
-}
diff --git a/dm/appengine/deps/finish_attempt_test.go b/dm/appengine/deps/finish_attempt_test.go
deleted file mode 100644
index d465386..0000000
--- a/dm/appengine/deps/finish_attempt_test.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"testing"
-
-	"go.chromium.org/luci/common/clock/testclock"
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestFinishAttempt(t *testing.T) {
-	t.Parallel()
-
-	Convey("FinishAttempt", t, func() {
-		_, c, _, s := testSetup()
-
-		So(ds.Put(c, &model.Quest{ID: "quest"}), ShouldBeNil)
-		a := &model.Attempt{
-			ID:           *dm.NewAttemptID("quest", 1),
-			State:        dm.Attempt_EXECUTING,
-			CurExecution: 1,
-		}
-		e := model.ExecutionFromID(c, dm.NewExecutionID("quest", 1, 1))
-		ar := &model.AttemptResult{Attempt: ds.KeyForObj(c, a)}
-		So(ds.Put(c, a), ShouldBeNil)
-		So(ds.Put(c, &model.Execution{
-			ID: 1, Attempt: ds.KeyForObj(c, a), Token: []byte("exKey"),
-			State: dm.Execution_RUNNING}), ShouldBeNil)
-
-		req := &dm.FinishAttemptReq{
-			Auth: &dm.Execution_Auth{
-				Id:    dm.NewExecutionID(a.ID.Quest, a.ID.Id, 1),
-				Token: []byte("exKey"),
-			},
-			Data: dm.NewJsonResult(`{"something": "valid"}`, testclock.TestTimeUTC),
-		}
-
-		Convey("bad", func() {
-			Convey("bad Token", func() {
-				req.Auth.Token = []byte("fake")
-				_, err := s.FinishAttempt(c, req)
-				So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-			})
-
-			Convey("not real json", func() {
-				req.Data = dm.NewJsonResult(`i am not valid json`)
-				_, err := s.FinishAttempt(c, req)
-				So(err, ShouldErrLike, "invalid character 'i'")
-			})
-		})
-
-		Convey("good", func() {
-			_, err := s.FinishAttempt(c, req)
-			So(err, ShouldBeNil)
-
-			So(ds.Get(c, a, ar, e), ShouldBeNil)
-			So(a.State, ShouldEqual, dm.Attempt_EXECUTING)
-			So(e.State, ShouldEqual, dm.Execution_STOPPING)
-
-			So(a.Result.Data.Size, ShouldEqual, 21)
-			So(ar.Data.Size, ShouldEqual, 21)
-		})
-
-	})
-}
diff --git a/dm/appengine/deps/service.go b/dm/appengine/deps/service.go
deleted file mode 100644
index af86173..0000000
--- a/dm/appengine/deps/service.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"context"
-	"os"
-
-	"github.com/golang/protobuf/proto"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/grpc/grpcutil"
-	"go.chromium.org/luci/grpc/prpc"
-	"go.chromium.org/luci/tumble"
-
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/codes"
-)
-
-const ek = logging.ErrorKey
-
-type deps struct{}
-
-var _ dm.DepsServer = (*deps)(nil)
-
-func depsServerPrelude(c context.Context, methodName string, req proto.Message) (context.Context, error) {
-	// Many of the DM request messages can be Normalize'd. This checks them for
-	// basic validity and normalizes cases where multiple representations can mean
-	// the same thing so that the service handlers only need to check for the
-	// canonical representation.
-	if norm, ok := req.(interface {
-		Normalize() error
-	}); ok {
-		if err := norm.Normalize(); err != nil {
-			return nil, grpcAnnotate(err, codes.InvalidArgument, "invalid request").Err()
-		}
-	}
-	return c, nil
-}
-
-const postludeDebugEnvvar = "DUMP_ALL_STACKS"
-
-var postludeOmitCodes = map[codes.Code]struct{}{
-	codes.OK:                 {},
-	codes.Unauthenticated:    {},
-	codes.AlreadyExists:      {},
-	codes.FailedPrecondition: {},
-	codes.InvalidArgument:    {},
-	codes.NotFound:           {},
-	codes.OutOfRange:         {},
-	codes.Aborted:            {},
-}
-
-func depsServerPostlude(c context.Context, methodName string, rsp proto.Message, err error) error {
-	retErr := grpcutil.ToGRPCErr(err)
-	if err != nil {
-		code := codes.OK
-		_, printStack := os.LookupEnv(postludeDebugEnvvar)
-		if !printStack {
-			code = grpc.Code(retErr)
-			_, omitStack := postludeOmitCodes[code]
-			printStack = !omitStack
-		}
-		if printStack {
-			errors.Log(c, err)
-		} else {
-			logging.Infof(c, "returning gRPC code: %s", code)
-		}
-	}
-	return retErr
-}
-
-func newDecoratedDeps() dm.DepsServer {
-	return &dm.DecoratedDeps{
-		Service:  &deps{},
-		Prelude:  depsServerPrelude,
-		Postlude: depsServerPostlude,
-	}
-}
-
-// RegisterDepsServer registers an implementation of the dm.DepsServer with
-// the provided Registrar.
-func RegisterDepsServer(svr prpc.Registrar) {
-	dm.RegisterDepsServer(svr, newDecoratedDeps())
-}
-
-// tumbleNow will run the mutation immediately, converting any non grpc errors
-// to codes.Internal.
-func tumbleNow(c context.Context, m tumble.Mutation) error {
-	err := tumble.RunMutation(c, m)
-	if grpc.Code(err) == codes.Unknown {
-		logging.WithError(err).Errorf(c, "unknown error while applying mutation %v", m)
-		err = grpcutil.Internal
-	}
-	logging.Fields{"root": m.Root(c)}.Infof(c, "tumbleNow success")
-	return err
-}
diff --git a/dm/appengine/deps/size_limit.go b/dm/appengine/deps/size_limit.go
deleted file mode 100644
index dae38eb..0000000
--- a/dm/appengine/deps/size_limit.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"sync/atomic"
-)
-
-type sizeLimit struct {
-	// current must only be accessed via sync/atomic
-	current uint32
-
-	// is read-only and may be accessed directly.
-	max uint32
-}
-
-func (s *sizeLimit) PossiblyOK(amount uint32) bool {
-	if s.max == 0 {
-		return true
-	}
-	if amount > s.max {
-		return false
-	}
-	// 0 <= 10 - 6
-	return atomic.LoadUint32(&s.current) <= (s.max - amount)
-}
-
-func (s *sizeLimit) Add(amount uint32) bool {
-	if s.max == 0 {
-		return true
-	}
-	if amount > s.max {
-		return false
-	}
-	lim := s.max - amount
-	for {
-		cur := atomic.LoadUint32(&s.current)
-		if cur > lim {
-			return false
-		}
-		if atomic.CompareAndSwapUint32(&s.current, cur, cur+amount) {
-			return true
-		}
-	}
-}
diff --git a/dm/appengine/deps/size_limit_test.go b/dm/appengine/deps/size_limit_test.go
deleted file mode 100644
index cbb5546..0000000
--- a/dm/appengine/deps/size_limit_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"errors"
-	"math"
-	"runtime"
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"go.chromium.org/luci/common/sync/parallel"
-)
-
-func TestSizeLimit(t *testing.T) {
-	t.Parallel()
-
-	Convey("Test SizeLimit", t, func() {
-		Convey("no max", func() {
-			l := sizeLimit{}
-			So(l.PossiblyOK(100), ShouldBeTrue)
-			So(l.Add(100), ShouldBeTrue)
-		})
-
-		Convey("some max", func() {
-			l := sizeLimit{max: 100}
-			So(l.PossiblyOK(100), ShouldBeTrue)
-			So(l.PossiblyOK(101), ShouldBeFalse)
-			So(l.Add(101), ShouldBeFalse)
-			So(l.Add(20), ShouldBeTrue)
-			So(l.PossiblyOK(100), ShouldBeFalse)
-			So(l.Add(20), ShouldBeTrue)
-			So(l.Add(20), ShouldBeTrue)
-			So(l.Add(20), ShouldBeTrue)
-			So(l.Add(20), ShouldBeTrue)
-			So(l.Add(20), ShouldBeFalse)
-		})
-
-		Convey("check overflow", func() {
-			l := sizeLimit{current: math.MaxUint32 - 5, max: math.MaxUint32}
-			So(l.PossiblyOK(math.MaxUint32), ShouldBeFalse)
-			So(l.Add(math.MaxUint32), ShouldBeFalse)
-			So(l.PossiblyOK(5), ShouldBeTrue)
-			So(l.PossiblyOK(6), ShouldBeFalse)
-			So(l.Add(4), ShouldBeTrue)
-			So(l.PossiblyOK(5), ShouldBeFalse)
-			So(l.PossiblyOK(1), ShouldBeTrue)
-			So(l.Add(1), ShouldBeTrue)
-			So(l.Add(1), ShouldBeFalse)
-			So(l.Add(math.MaxUint32), ShouldBeFalse)
-			So(l.PossiblyOK(1), ShouldBeFalse)
-		})
-
-		Convey("concurrency", func() {
-			prev := runtime.GOMAXPROCS(512)
-			defer runtime.GOMAXPROCS(prev)
-			sl := sizeLimit{max: 512}
-			err := parallel.FanOutIn(func(pool chan<- func() error) {
-				for i := 0; i < 512; i++ {
-					pool <- func() error {
-						if !sl.Add(1) {
-							return errors.New("failed to add")
-						}
-						return nil
-					}
-				}
-			})
-			So(err, ShouldBeNil)
-			So(sl.current, ShouldEqual, 512)
-		})
-	})
-}
diff --git a/dm/appengine/deps/util.go b/dm/appengine/deps/util.go
deleted file mode 100644
index 72753ad..0000000
--- a/dm/appengine/deps/util.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/grpc/grpcutil"
-	"google.golang.org/grpc/codes"
-)
-
-func grpcAnnotate(err error, code codes.Code, reason string, args ...interface{}) *errors.Annotator {
-	return errors.Annotate(err, reason, args...).Tag(grpcutil.Tag.With(code))
-}
diff --git a/dm/appengine/deps/walk_graph.go b/dm/appengine/deps/walk_graph.go
deleted file mode 100644
index 802a9ac..0000000
--- a/dm/appengine/deps/walk_graph.go
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"context"
-	"fmt"
-	"math"
-	"sort"
-	"sync"
-	"time"
-
-	"google.golang.org/grpc/codes"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/sync/parallel"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/grpc/grpcutil"
-)
-
-const numWorkers = 16
-
-const maxTimeout = 55 * time.Second // GAE limit is 60s
-
-// queryBatchSize is a default datastore query batch size.
-//
-// We end up doing a lot of long queries in here, so use a batcher to
-// prevent datastore timeouts.
-const queryBatchSize = int32(500)
-
-type node struct {
-	aid                 *dm.Attempt_ID
-	depth               int64
-	canSeeAttemptResult bool
-}
-
-func (g *graphWalker) runSearchQuery(send func(*dm.Attempt_ID) error, s *dm.GraphQuery_Search) func() error {
-	return func() error {
-		logging.Errorf(g, "SearchQuery not implemented")
-		return grpcutil.Errf(codes.Unimplemented, "GraphQuery.Search is not implemented")
-	}
-}
-
-func isCtxErr(err error) bool {
-	return err == context.Canceled || err == context.DeadlineExceeded
-}
-
-func (g *graphWalker) runAttemptListQuery(send func(*dm.Attempt_ID) error) func() error {
-	return func() error {
-		for qst, anum := range g.req.Query.AttemptList.To {
-			if len(anum.Nums) == 0 {
-				qry := model.QueryAttemptsForQuest(g, qst)
-				if !g.req.Include.Attempt.Abnormal {
-					qry = qry.Eq("IsAbnormal", false)
-				}
-				if !g.req.Include.Attempt.Expired {
-					qry = qry.Eq("IsExpired", false)
-				}
-				err := ds.RunBatch(g, queryBatchSize, qry, func(k *ds.Key) error {
-					aid := &dm.Attempt_ID{}
-					if err := aid.SetDMEncoded(k.StringID()); err != nil {
-						logging.WithError(err).Errorf(g, "Attempt_ID.SetDMEncoded returned an error with input: %q", k.StringID())
-						panic(fmt.Errorf("in AttemptListQuery: %s", err))
-					}
-					return send(aid)
-				})
-				if err != nil {
-					if !isCtxErr(err) {
-						logging.WithError(err).Errorf(g, "in AttemptListQuery")
-					}
-					return err
-				}
-			} else {
-				for _, num := range anum.Nums {
-					if err := send(dm.NewAttemptID(qst, num)); err != nil {
-						return err
-					}
-				}
-			}
-		}
-		return nil
-	}
-}
-
-func (g *graphWalker) runAttemptRangeQuery(send func(*dm.Attempt_ID) error, ar *dm.GraphQuery_AttemptRange) func() error {
-	return func() error {
-		for i := ar.Low; i < ar.High; i++ {
-			if err := send(dm.NewAttemptID(ar.Quest, i)); err != nil {
-				return err
-			}
-		}
-		return nil
-	}
-}
-
-func (g *graphWalker) questDataLoader(qid string, dst *dm.Quest) func() error {
-	return func() error {
-		qst := &model.Quest{ID: qid}
-		if err := ds.Get(g, qst); err != nil {
-			if err == ds.ErrNoSuchEntity {
-				dst.DNE = true
-				dst.Partial = false
-				return nil
-			}
-			logging.Fields{ek: err, "qid": qid}.Errorf(g, "while loading quest")
-			return err
-		}
-		dst.Data = qst.DataProto()
-		dst.Partial = false
-		return nil
-	}
-}
-
-func (g *graphWalker) loadEdges(send func(*dm.Attempt_ID) error, typ string, base *ds.Key, fan *dm.AttemptList, doSend bool) error {
-	return ds.RunBatch(g, queryBatchSize, ds.NewQuery(typ).Ancestor(base), func(k *ds.Key) error {
-		if g.Err() != nil {
-			return ds.Stop
-		}
-		aid := &dm.Attempt_ID{}
-		if err := aid.SetDMEncoded(k.StringID()); err != nil {
-			logging.WithError(err).Errorf(g, "Attempt_ID.SetDMEncoded returned an error with input: %q", k.StringID())
-			panic(fmt.Errorf("in AttemptListQuery: %s", err))
-		}
-		if fan != nil {
-			fan.AddAIDs(aid)
-		}
-		if doSend {
-			if err := send(aid); err != nil {
-				return err
-			}
-		}
-		return nil
-	})
-}
-
-func (g *graphWalker) loadExecutions(includeResult bool, atmpt *model.Attempt, akey *ds.Key, dst *dm.Attempt) error {
-	numEx := g.req.Include.NumExecutions
-	if atmpt.CurExecution < numEx {
-		numEx = atmpt.CurExecution
-	}
-
-	dst.Executions = map[uint32]*dm.Execution{}
-	q := ds.NewQuery("Execution").Ancestor(akey)
-	if numEx > math.MaxInt32 {
-		q = q.Limit(math.MaxInt32)
-	} else {
-		q = q.Limit(int32(numEx))
-	}
-	if !g.req.Include.Execution.Abnormal {
-		q = q.Eq("IsAbnormal", false)
-	}
-	if !g.req.Include.Execution.Expired {
-		q = q.Eq("IsExpired", false)
-	}
-
-	return ds.RunBatch(g, queryBatchSize, q, func(e *model.Execution) error {
-		if g.Err() != nil {
-			return ds.Stop
-		}
-		p := e.ToProto(g.req.Include.Execution.Ids)
-		d, err := g.getDist(p.Data.DistributorInfo.ConfigName)
-		if err != nil {
-			return err
-		}
-		p.Data.DistributorInfo.Url = d.InfoURL(distributor.Token(p.Data.DistributorInfo.Token))
-		if d := p.Data.GetFinished().GetData(); d != nil {
-			if !includeResult || !g.lim.Add(d.Size) {
-				d.Object = ""
-			}
-		}
-		dst.Executions[uint32(e.ID)] = p
-		return nil
-	})
-}
-
-func (g *graphWalker) attemptResultLoader(aid *dm.Attempt_ID, rsltSize uint32, akey *ds.Key, dst *dm.Attempt) func() error {
-	return func() error {
-		siz := rsltSize
-		if !g.lim.PossiblyOK(siz) {
-			dst.Partial.Result = dm.Attempt_Partial_DATA_SIZE_LIMIT
-			logging.Infof(g, "skipping load of AttemptResult %s (size limit)", aid)
-			return nil
-		}
-		r := &model.AttemptResult{Attempt: akey}
-		if err := ds.Get(g, r); err != nil {
-			logging.Fields{ek: err, "aid": aid}.Errorf(g, "failed to load AttemptResult")
-			return err
-		}
-		if g.lim.Add(siz) {
-			dst.Data.GetFinished().Data = &r.Data
-			dst.Partial.Result = dm.Attempt_Partial_LOADED
-		} else {
-			dst.Partial.Result = dm.Attempt_Partial_DATA_SIZE_LIMIT
-			logging.Infof(g, "loaded AttemptResult %s, but hit size limit after", aid)
-		}
-		return nil
-	}
-}
-
-func (g *graphWalker) checkCanLoadResultData(aid *dm.Attempt_ID) (bool, error) {
-	// We're running this query from a human, or internally in DM, not a bot.
-	if g.req.Auth == nil {
-		return true, nil
-	}
-
-	// This query is from a bot, and we didn't get to this Attempt by walking
-	// a dependency, so we need to verify that the dependency exists.
-	from := g.req.Auth.Id.AttemptID().DMEncoded()
-	to := aid.DMEncoded()
-	fdepKey := ds.MakeKey(g, "Attempt", from, "FwdDep", to)
-	exist, err := ds.Exists(g, fdepKey)
-	if err != nil {
-		logging.Fields{ek: err, "key": fdepKey}.Errorf(g, "failed to determine if FwdDep exists")
-		return false, err
-	}
-	if !exist.All() {
-		return false, nil
-	}
-
-	return true, nil
-}
-
-func (g *graphWalker) attemptLoader(aid *dm.Attempt_ID, authedForResult bool, dst *dm.Attempt, send func(aid *dm.Attempt_ID, fwd bool) error) func() error {
-	return func() error {
-		atmpt := &model.Attempt{ID: *aid}
-		akey := ds.KeyForObj(g, atmpt)
-		if err := ds.Get(g, atmpt); err != nil {
-			if err == ds.ErrNoSuchEntity {
-				dst.DNE = true
-				dst.Partial = nil
-				return nil
-			}
-			return err
-		}
-		if !g.req.Include.Attempt.Abnormal && atmpt.IsAbnormal {
-			return nil
-		}
-		if !g.req.Include.Attempt.Expired && atmpt.IsExpired {
-			return nil
-		}
-
-		if g.req.Include.Attempt.Data {
-			dst.Data = atmpt.DataProto()
-			dst.Partial.Data = false
-		}
-
-		canLoadResultData := false
-		if g.req.Include.Attempt.Result {
-			// We loaded this by walking from the Attempt, so we don't need to do any
-			// additional checks.
-			if authedForResult {
-				canLoadResultData = true
-			} else {
-				canLoad, err := g.checkCanLoadResultData(aid)
-				if !canLoad {
-					dst.Partial.Result = dm.Attempt_Partial_NOT_AUTHORIZED
-				}
-				if err != nil {
-					return err
-				}
-				canLoadResultData = canLoad
-			}
-		}
-
-		errChan := parallel.Run(0, func(ch chan<- func() error) {
-			if g.req.Include.Attempt.Result {
-				if atmpt.State == dm.Attempt_FINISHED {
-					if canLoadResultData {
-						ch <- g.attemptResultLoader(aid, atmpt.Result.Data.Size, akey, dst)
-					}
-				} else {
-					dst.Partial.Result = dm.Attempt_Partial_LOADED
-				}
-			}
-
-			if g.req.Include.NumExecutions > 0 {
-				ch <- func() error {
-					err := g.loadExecutions(canLoadResultData, atmpt, akey, dst)
-					if err != nil {
-						logging.Fields{ek: err, "aid": aid}.Errorf(g, "error loading executions")
-					} else {
-						dst.Partial.Executions = false
-					}
-					return err
-				}
-			}
-
-			writeFwd := g.req.Include.FwdDeps
-			walkFwd := (g.req.Mode.Direction == dm.WalkGraphReq_Mode_BOTH ||
-				g.req.Mode.Direction == dm.WalkGraphReq_Mode_FORWARDS) && send != nil
-			loadFwd := writeFwd || walkFwd
-
-			if loadFwd {
-				isAuthed := g.req.Auth != nil && g.req.Auth.Id.AttemptID().Equals(aid)
-				subSend := func(aid *dm.Attempt_ID) error {
-					return send(aid, isAuthed)
-				}
-				if writeFwd {
-					dst.FwdDeps = dm.NewAttemptList(nil)
-				}
-				ch <- func() error {
-					err := g.loadEdges(subSend, "FwdDep", akey, dst.FwdDeps, walkFwd)
-					if err == nil && dst.Partial != nil {
-						dst.Partial.FwdDeps = false
-					} else if err != nil {
-						logging.Fields{"aid": aid, ek: err}.Errorf(g, "while loading FwdDeps")
-					}
-					return err
-				}
-			}
-
-			writeBack := g.req.Include.BackDeps
-			walkBack := (g.req.Mode.Direction == dm.WalkGraphReq_Mode_BOTH ||
-				g.req.Mode.Direction == dm.WalkGraphReq_Mode_BACKWARDS) && send != nil
-			loadBack := writeBack || walkBack
-
-			if loadBack {
-				if writeBack {
-					dst.BackDeps = dm.NewAttemptList(nil)
-				}
-				subSend := func(aid *dm.Attempt_ID) error {
-					return send(aid, false)
-				}
-				bdg := &model.BackDepGroup{Dependee: atmpt.ID}
-				bdgKey := ds.KeyForObj(g, bdg)
-				ch <- func() error {
-					err := g.loadEdges(subSend, "BackDep", bdgKey, dst.BackDeps, walkBack)
-					if err == nil && dst.Partial != nil {
-						dst.Partial.BackDeps = false
-					} else if err != nil {
-						logging.Fields{"aid": aid, ek: err}.Errorf(g, "while loading FwdDeps")
-					}
-					return err
-				}
-			}
-		})
-		hadErr := false
-		for err := range errChan {
-			if err == nil {
-				continue
-			}
-			if err != nil {
-				hadErr = true
-			}
-		}
-		dst.NormalizePartial()
-		if hadErr {
-			return fmt.Errorf("had one or more errors loading attempt")
-		}
-		return nil
-	}
-}
-
-type graphWalker struct {
-	context.Context
-	req *dm.WalkGraphReq
-
-	lim *sizeLimit
-	reg distributor.Registry
-
-	distCacheLock sync.Mutex
-	distCache     map[string]distributor.D
-}
-
-func (g *graphWalker) getDist(cfgName string) (distributor.D, error) {
-	g.distCacheLock.Lock()
-	defer g.distCacheLock.Unlock()
-
-	dist := g.distCache[cfgName]
-	if dist != nil {
-		return dist, nil
-	}
-
-	dist, _, err := g.reg.MakeDistributor(g, cfgName)
-	if err != nil {
-		logging.Fields{
-			ek: err, "cfgName": cfgName,
-		}.Errorf(g, "unable to load distributor")
-		return nil, err
-	}
-
-	if g.distCache == nil {
-		g.distCache = map[string]distributor.D{}
-	}
-	g.distCache[cfgName] = dist
-	return dist, nil
-}
-
-func (g *graphWalker) excludedQuest(qid string) bool {
-	qsts := g.req.Exclude.Quests
-	if len(qsts) == 0 {
-		return false
-	}
-	idx := sort.Search(len(qsts), func(i int) bool { return qsts[i] >= qid })
-	return idx < len(qsts) && qsts[idx] == qid
-}
-
-func (g *graphWalker) excludedAttempt(aid *dm.Attempt_ID) bool {
-	to := g.req.Exclude.Attempts.GetTo()
-	if len(to) == 0 {
-		return false
-	}
-	toNums, ok := to[aid.Quest]
-	if !ok {
-		return false
-	}
-	nums := toNums.Nums
-	if nums == nil { // a nil Nums list means 'ALL nums for this quest'
-		return true
-	}
-	idx := sort.Search(len(nums), func(i int) bool { return nums[i] >= aid.Id })
-	return idx < len(nums) && nums[idx] == aid.Id
-}
-
-func doGraphWalk(ctx context.Context, req *dm.WalkGraphReq) (rsp *dm.GraphData, err error) {
-	timeoutProto := req.Limit.MaxTime
-	timeout := timeoutProto.AsDuration()
-	if timeoutProto == nil || timeout > maxTimeout {
-		timeout = maxTimeout
-	}
-	ctx, cancel := clock.WithTimeout(ctx, timeout)
-	defer cancel()
-
-	// nodeChan recieves attempt nodes to process. If it recieves the
-	// `finishedJob` sentinel node, that indicates that an outstanding worker is
-	// finished.
-	nodeChan := make(chan *node, numWorkers)
-	defer close(nodeChan)
-
-	g := graphWalker{Context: ctx, req: req}
-
-	sendNodeAuthed := func(depth int64) func(*dm.Attempt_ID, bool) error {
-		if req.Limit.MaxDepth != -1 && depth > req.Limit.MaxDepth {
-			return nil
-		}
-		return func(aid *dm.Attempt_ID, isAuthed bool) error {
-			select {
-			case nodeChan <- &node{aid: aid, depth: depth, canSeeAttemptResult: isAuthed}:
-				return nil
-			case <-ctx.Done():
-				return ctx.Err()
-			}
-		}
-	}
-
-	sendNode := func(depth int64) func(*dm.Attempt_ID) error {
-		return func(aid *dm.Attempt_ID) error {
-			select {
-			case nodeChan <- &node{aid: aid, depth: depth}:
-				return nil
-			case <-ctx.Done():
-				return ctx.Err()
-			}
-		}
-	}
-
-	buf := parallel.Buffer{}
-	defer buf.Close()
-	buf.Maximum = numWorkers + 1 // +1 job for queries
-	buf.Sustained = numWorkers
-	buf.SetFIFO(!req.Mode.Dfs)
-
-	allErrs := make(chan error, numWorkers)
-	outstandingJobs := 0
-
-	addJob := func(f func() error) {
-		if ctx.Err() != nil { // we're done adding work, ignore this job
-			return
-		}
-		outstandingJobs++
-		buf.WorkC() <- parallel.WorkItem{F: f, ErrC: allErrs}
-	}
-
-	addJob(func() error {
-		return parallel.FanOutIn(func(pool chan<- func() error) {
-			snd := sendNode(0)
-			if req.Query.AttemptList != nil {
-				pool <- g.runAttemptListQuery(snd)
-			}
-			for _, rng := range req.Query.AttemptRange {
-				pool <- g.runAttemptRangeQuery(snd, rng)
-			}
-			for _, srch := range req.Query.Search {
-				pool <- g.runSearchQuery(snd, srch)
-			}
-		})
-	})
-
-	g.lim = &sizeLimit{0, req.Limit.MaxDataSize}
-	g.reg = distributor.GetRegistry(ctx)
-	rsp = &dm.GraphData{Quests: map[string]*dm.Quest{}}
-	// main graph walk processing loop
-	for outstandingJobs > 0 || len(nodeChan) > 0 {
-		select {
-		case err := <-allErrs:
-			outstandingJobs--
-			if err == nil {
-				break
-			}
-			if !isCtxErr(err) {
-				rsp.HadErrors = true
-			}
-			// assume that contextualized logging already happened
-
-		case n := <-nodeChan:
-			if g.excludedAttempt(n.aid) {
-				continue
-			}
-
-			qst, ok := rsp.GetQuest(n.aid.Quest)
-			if !ok {
-				if !req.Include.Quest.Ids {
-					qst.Id = nil
-				}
-				if req.Include.Quest.Data && !g.excludedQuest(n.aid.Quest) {
-					addJob(g.questDataLoader(n.aid.Quest, qst))
-				}
-			}
-			if _, ok := qst.Attempts[n.aid.Id]; !ok {
-				atmpt := &dm.Attempt{Partial: &dm.Attempt_Partial{
-					Data:       req.Include.Attempt.Data,
-					Executions: req.Include.NumExecutions != 0,
-					FwdDeps:    req.Include.FwdDeps,
-					BackDeps:   req.Include.BackDeps,
-				}}
-				if req.Include.Attempt.Result {
-					atmpt.Partial.Result = dm.Attempt_Partial_NOT_LOADED
-				}
-
-				atmpt.NormalizePartial() // in case they're all false
-				if req.Include.Attempt.Ids {
-					atmpt.Id = n.aid
-				}
-				qst.Attempts[n.aid.Id] = atmpt
-				if req.Limit.MaxDepth == -1 || n.depth <= req.Limit.MaxDepth {
-					addJob(g.attemptLoader(n.aid, n.canSeeAttemptResult, atmpt,
-						sendNodeAuthed(n.depth+1)))
-				}
-			}
-			// otherwise, we've dealt with this attempt before, so ignore it.
-		}
-	}
-
-	if ctx.Err() != nil {
-		rsp.HadMore = true
-	}
-	return
-}
-
-// WalkGraph does all the graph walking in parallel. Theoretically, the
-// goroutines look like:
-//
-//   main:
-//     WorkPool(MaxWorkers+1) as pool
-//       jobBuf.add(FanOutIn(Query1->nodeChan ... QueryN->nodeChan))
-//       runningWorkers = 0
-//       while runningWorkers > 0 or jobBuf is not empty:
-//         select {
-//           pool <- jobBuf.pop(): // only if jobBuf !empty, otherwise skip this send
-//             runningWorkers++
-//           node = <- nodeChan:
-//             if node == finishedJob {
-//               runningWorkers--
-//             } else {
-//               if node mentions new quest:
-//                 jobBuf.add(questDataLoader()->nodeChan)
-//               if node mentions new attempt:
-//                 if node.depth < MaxDepth:
-//                   jobBuf.add(attemptLoader(node.depth+1)->nodeChan)
-//             }
-//         }
-//
-//   attemptLoader:
-//     a = get_attempt()
-//     if a exists {
-//       FanOutIn(
-//         maybeLoadAttemptResult,
-//         maybeLoadExecutions,
-//         maybeLoadFwdDeps, // sends to nodeChan if walking direction Fwd|Both
-//         maybeLoadBackDeps // sends to nodeChan if walking direction Back|Both
-//       )
-//     }
-func (d *deps) WalkGraph(ctx context.Context, req *dm.WalkGraphReq) (rsp *dm.GraphData, err error) {
-	if req.Auth != nil {
-		logging.Fields{"execution": req.Auth.Id}.Debugf(ctx, "on behalf of")
-	} else {
-		if err = canRead(ctx); err != nil {
-			return
-		}
-	}
-	return doGraphWalk(ctx, req)
-}
diff --git a/dm/appengine/deps/walk_graph_test.go b/dm/appengine/deps/walk_graph_test.go
deleted file mode 100644
index fa746be..0000000
--- a/dm/appengine/deps/walk_graph_test.go
+++ /dev/null
@@ -1,490 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package deps
-
-import (
-	"context"
-	"fmt"
-	"testing"
-	"time"
-
-	"google.golang.org/protobuf/types/known/durationpb"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/clock/testclock"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor/fake"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-type breakFwdDepLoads struct {
-	ds.RawInterface
-}
-
-func (b breakFwdDepLoads) GetMulti(keys []*ds.Key, mg ds.MultiMetaGetter, cb ds.GetMultiCB) error {
-	for _, k := range keys {
-		if k.Kind() == "FwdDep" {
-			return fmt.Errorf("Loading FwdDeps is currently broken")
-		}
-	}
-	return b.RawInterface.GetMulti(keys, mg, cb)
-}
-
-func addDistributorInfo(id *dm.Execution_ID, e *dm.Execution) *dm.Execution {
-	e.Data.DistributorInfo = &dm.Execution_Data_DistributorInfo{
-		ConfigName:    "fakeDistributor",
-		ConfigVersion: "testing",
-		Token:         string(fake.MakeToken(id)),
-		Url:           fake.InfoURL(id),
-	}
-	return e
-}
-
-func TestWalkGraph(t *testing.T) {
-	t.Parallel()
-
-	Convey("WalkGraph", t, func() {
-		ttest, c, dist, s := testSetup()
-
-		req := &dm.WalkGraphReq{
-			Query: dm.AttemptListQueryL(map[string][]uint32{"quest": {1}}),
-		}
-		So(req.Normalize(), ShouldBeNil)
-
-		Convey("no read access", func() {
-			_, err := s.WalkGraph(c, req)
-			So(err, ShouldBeRPCPermissionDenied, "not authorized")
-		})
-
-		c = reader(c)
-
-		Convey("no attempt", func() {
-			So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-				Quests: map[string]*dm.Quest{"quest": {
-					Attempts: map[uint32]*dm.Attempt{
-						1: {DNE: true},
-					},
-				}},
-			})
-		})
-
-		Convey("good", func() {
-			ds.GetTestable(c).Consistent(true)
-
-			wDesc := fake.QuestDesc("w")
-			w := s.ensureQuest(c, "w", 1)
-			ttest.Drain(c)
-
-			req.Query.AttemptList = dm.NewAttemptList(
-				map[string][]uint32{w: {1}})
-
-			Convey("include nothing", func() {
-				So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-					Quests: map[string]*dm.Quest{
-						w: {
-							Attempts: map[uint32]*dm.Attempt{1: {}},
-						},
-					},
-				})
-			})
-
-			Convey("quest dne", func() {
-				req.Include.Quest.Data = true
-				req.Query.AttemptList = dm.NewAttemptList(
-					map[string][]uint32{"noex": {1}})
-				So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-					Quests: map[string]*dm.Quest{
-						"noex": {
-							DNE:      true,
-							Attempts: map[uint32]*dm.Attempt{1: {DNE: true}},
-						},
-					},
-				})
-			})
-
-			Convey("no dependencies", func() {
-				req.Include.Attempt.Data = true
-				req.Include.Quest.Data = true
-				req.Include.NumExecutions = 128
-				aExpect := dm.NewAttemptExecuting(1)
-				aExpect.Executions = map[uint32]*dm.Execution{
-					1: addDistributorInfo(
-						dm.NewExecutionID(w, 1, 1),
-						dm.NewExecutionScheduling())}
-				So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-					Quests: map[string]*dm.Quest{
-						w: {
-							Data: &dm.Quest_Data{
-								Desc: wDesc,
-							},
-							Attempts: map[uint32]*dm.Attempt{1: aExpect},
-						},
-					},
-				})
-			})
-
-			Convey("finished", func() {
-				wEx := dm.NewExecutionID(w, 1, 1)
-				dist.RunTask(c, wEx, func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).Finish(
-						`{"data": ["very", "yes"]}`, clock.Now(c).Add(time.Hour*24*4))
-					tsk.State = dm.NewJsonResult(`{"distributorState": true}`)
-					return nil
-				})
-				ttest.Drain(c)
-
-				req.Include.Attempt.Data = true
-				req.Include.Attempt.Result = true
-				req.Include.NumExecutions = 128
-				data := `{"data":["very","yes"]}`
-				aExpect := dm.NewAttemptFinished(dm.NewJsonResult(data))
-				aExpect.Data.NumExecutions = 1
-				aExpect.Executions = map[uint32]*dm.Execution{
-					1: addDistributorInfo(
-						dm.NewExecutionID(w, 1, 1),
-						dm.NewExecutionFinished(dm.NewJsonResult(`{"distributorState":true}`))),
-				}
-
-				So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-					Quests: map[string]*dm.Quest{
-						w: {
-							Attempts: map[uint32]*dm.Attempt{1: aExpect},
-						},
-					},
-				})
-			})
-
-			Convey("limited attempt results", func() {
-				wEx := dm.NewExecutionID(w, 1, 1)
-				dist.RunTask(c, wEx, func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).Finish(
-						`{"data": ["very", "yes"]}`, clock.Now(c).Add(time.Hour*24*4))
-					tsk.State = dm.NewJsonResult(`{"distributorState": true}`)
-					return nil
-				})
-				ttest.Drain(c)
-
-				req.Include.Attempt.Result = true
-				req.Limit.MaxDataSize = 10
-				data := `{"data":["very","yes"]}`
-				aExpect := dm.NewAttemptFinished(dm.NewDatalessJsonResult(uint32(len(data))))
-				aExpect.Data.NumExecutions = 1
-				aExpect.Partial = &dm.Attempt_Partial{Result: dm.Attempt_Partial_DATA_SIZE_LIMIT}
-				So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-					Quests: map[string]*dm.Quest{
-						w: {
-							Attempts: map[uint32]*dm.Attempt{1: aExpect},
-						},
-					},
-				})
-			})
-
-			Convey("attemptRange", func() {
-				x := s.ensureQuest(c, "x", 1)
-				ttest.Drain(c)
-
-				wEx := dm.NewExecutionID(w, 1, 1)
-				dist.RunTask(c, wEx, func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).DepOn(
-						dm.NewAttemptID(x, 1), dm.NewAttemptID(x, 2), dm.NewAttemptID(x, 3),
-						dm.NewAttemptID(x, 4))
-					return nil
-				})
-				ttest.Drain(c)
-
-				Convey("normal", func() {
-					req.Query = dm.AttemptRangeQuery(x, 2, 4)
-					So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-						Quests: map[string]*dm.Quest{
-							x: {Attempts: map[uint32]*dm.Attempt{2: {}, 3: {}}},
-						},
-					})
-				})
-
-				Convey("oob range", func() {
-					req.Query = dm.AttemptRangeQuery(x, 2, 6)
-					So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-						Quests: map[string]*dm.Quest{
-							x: {Attempts: map[uint32]*dm.Attempt{
-								2: {}, 3: {}, 4: {}, 5: {DNE: true}}},
-						},
-					})
-				})
-			})
-
-			Convey("filtered attempt results", func() {
-				x := s.ensureQuest(c, "x", 2)
-				ttest.Drain(c)
-
-				dist.RunTask(c, dm.NewExecutionID(w, 1, 1), func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).DepOn(dm.NewAttemptID(x, 1))
-					tsk.State = dm.NewJsonResult(`{ "originalState": true }`)
-					return nil
-				})
-				ttest.Drain(c)
-
-				exp := ds.RoundTime(clock.Now(c).Add(time.Hour * 24 * 4))
-
-				x1data := `{"data":["I can see this"]}`
-				dist.RunTask(c, dm.NewExecutionID(x, 1, 1), func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).Finish(x1data, exp)
-					tsk.State = dm.NewJsonResult(`{ "atmpt1": true }`)
-					return nil
-				})
-
-				x2data := `{"data":["nope"]}`
-				dist.RunTask(c, dm.NewExecutionID(x, 2, 1), func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).Finish(x2data, exp)
-					tsk.State = dm.NewJsonResult(`{ "atmpt2": true }`)
-					return nil
-				})
-
-				// This Drain does:
-				//   RecordCompletion -> AckFwdDep -> ScheduleExecution
-				// which attempts to load the configuration from the context, and
-				// panics if it's missing.
-				ttest.Drain(c)
-
-				wEID := dm.NewExecutionID(w, 1, 2)
-				wEx := model.ExecutionFromID(c, wEID)
-				So(ds.Get(c, wEx), ShouldBeNil)
-
-				dist.RunTask(c, wEID, func(tsk *fake.Task) error {
-					So(tsk.State, ShouldResemble, dm.NewJsonResult(`{"originalState":true}`))
-
-					act := tsk.MustActivate(c, s)
-					req.Limit.MaxDepth = 1
-					req.Include.Attempt.Result = true
-					req.Include.NumExecutions = 1
-					req.Query = dm.AttemptListQueryL(map[string][]uint32{x: nil})
-
-					x1Expect := dm.NewAttemptFinished(dm.NewJsonResult(x1data))
-					x1Expect.Data.NumExecutions = 1
-					x1Expect.Executions = map[uint32]*dm.Execution{
-						1: addDistributorInfo(
-							dm.NewExecutionID(x, 1, 1),
-							dm.NewExecutionFinished(dm.NewJsonResult(`{"atmpt1":true}`))),
-					}
-
-					x2Expect := dm.NewAttemptFinished(dm.NewDatalessJsonResult(uint32(len(x2data))))
-					x2Expect.Partial = &dm.Attempt_Partial{Result: dm.Attempt_Partial_NOT_AUTHORIZED}
-					x2Expect.Data.NumExecutions = 1
-					x2Expect.Executions = map[uint32]*dm.Execution{
-						1: addDistributorInfo(
-							dm.NewExecutionID(x, 2, 1),
-							dm.NewExecutionFinished(dm.NewDatalessJsonResult(15))),
-					}
-
-					So(req, act.WalkShouldReturn, &dm.GraphData{
-						Quests: map[string]*dm.Quest{
-							x: {Attempts: map[uint32]*dm.Attempt{
-								1: x1Expect,
-								2: x2Expect,
-							}},
-						},
-					})
-					return nil
-				})
-			})
-
-			Convey("own attempt results", func() {
-				x := s.ensureQuest(c, "x", 2)
-				ttest.Drain(c)
-				dist.RunTask(c, dm.NewExecutionID(w, 1, 1), func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).DepOn(dm.NewAttemptID(x, 1))
-					return nil
-				})
-				ttest.Drain(c)
-
-				exp := ds.RoundTime(clock.Now(c).Add(time.Hour * 24 * 4))
-
-				x1data := `{"data":["I can see this"]}`
-				dist.RunTask(c, dm.NewExecutionID(x, 1, 1), func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).Finish(x1data, exp)
-					tsk.State = dm.NewJsonResult(`{"state": true}`)
-					return nil
-				})
-				ttest.Drain(c)
-
-				dist.RunTask(c, dm.NewExecutionID(w, 1, 2), func(tsk *fake.Task) error {
-					act := tsk.MustActivate(c, s)
-					req.Limit.MaxDepth = 1
-					req.Include.Attempt.Result = true
-					req.Include.NumExecutions = 1
-					req.Query = dm.AttemptListQueryL(map[string][]uint32{w: {1}})
-
-					x1Expect := dm.NewAttemptFinished(dm.NewJsonResult(x1data))
-					x1Expect.Data.NumExecutions = 1
-					x1Expect.Executions = map[uint32]*dm.Execution{
-						1: addDistributorInfo(
-							dm.NewExecutionID(x, 1, 1),
-							dm.NewExecutionFinished(dm.NewJsonResult(`{"state":true}`))),
-					}
-
-					w1Exepct := dm.NewAttemptExecuting(2)
-					w1Exepct.Data.NumExecutions = 2
-					w1Exepct.Executions = map[uint32]*dm.Execution{
-						2: addDistributorInfo(dm.NewExecutionID(w, 1, 2), dm.NewExecutionRunning()),
-					}
-
-					// This filter ensures that WalkShouldReturn is using the optimized
-					// path for deps traversal when starting from an authed attempt.
-					c = ds.AddRawFilters(c, func(c context.Context, ri ds.RawInterface) ds.RawInterface {
-						return breakFwdDepLoads{ri}
-					})
-
-					So(req, act.WalkShouldReturn, &dm.GraphData{
-						Quests: map[string]*dm.Quest{
-							w: {Attempts: map[uint32]*dm.Attempt{1: w1Exepct}},
-							x: {Attempts: map[uint32]*dm.Attempt{1: x1Expect}},
-						},
-					})
-					return nil
-				})
-			})
-
-			Convey("deps (no dest attempts)", func() {
-				req.Limit.MaxDepth = 2
-
-				x := s.ensureQuest(c, "x", 1)
-				ttest.Drain(c)
-
-				dist.RunTask(c, dm.NewExecutionID(w, 1, 1), func(tsk *fake.Task) error {
-					tsk.MustActivate(c, s).DepOn(dm.NewAttemptID(x, 1), dm.NewAttemptID(x, 2))
-
-					Convey("before tumble", func() {
-						req.Include.FwdDeps = true
-						// didn't run tumble, so that x|1 and x|2 don't get created.
-						// don't use act.WalkShouldReturn; we want to observe the graph
-						// state from
-						So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-							Quests: map[string]*dm.Quest{
-								w: {Attempts: map[uint32]*dm.Attempt{1: {
-									FwdDeps: dm.NewAttemptList(map[string][]uint32{
-										x: {2, 1},
-									}),
-								}}},
-								x: {Attempts: map[uint32]*dm.Attempt{
-									1: {FwdDeps: &dm.AttemptList{}}, // exists, but has no fwddeps
-									2: {DNE: true},
-								}},
-							},
-						})
-					})
-					return nil
-				})
-
-				Convey("after tumble", func() {
-					ttest.Drain(c)
-
-					Convey("deps (with dest attempts)", func() {
-						req.Include.FwdDeps = true
-						req.Include.BackDeps = true
-						So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-							Quests: map[string]*dm.Quest{
-								w: {Attempts: map[uint32]*dm.Attempt{1: {
-									FwdDeps:  dm.NewAttemptList(map[string][]uint32{x: {2, 1}}),
-									BackDeps: &dm.AttemptList{},
-								}}},
-								x: {Attempts: map[uint32]*dm.Attempt{1: {
-									FwdDeps:  &dm.AttemptList{},
-									BackDeps: dm.NewAttemptList(map[string][]uint32{w: {1}}),
-								}, 2: {
-									FwdDeps:  &dm.AttemptList{},
-									BackDeps: dm.NewAttemptList(map[string][]uint32{w: {1}}),
-								}}},
-							},
-						})
-					})
-
-					Convey("diamond", func() {
-						z := s.ensureQuest(c, "z", 1)
-						ttest.Drain(c)
-
-						dist.RunTask(c, dm.NewExecutionID(x, 1, 1), func(tsk *fake.Task) error {
-							tsk.MustActivate(c, s).DepOn(dm.NewAttemptID(z, 1))
-							return nil
-						})
-						dist.RunTask(c, dm.NewExecutionID(x, 2, 1), func(tsk *fake.Task) error {
-							tsk.MustActivate(c, s).DepOn(dm.NewAttemptID(z, 1))
-							return nil
-						})
-						ttest.Drain(c)
-
-						Convey("walk", func() {
-							So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-								Quests: map[string]*dm.Quest{
-									w: {Attempts: map[uint32]*dm.Attempt{1: {}}},
-									x: {Attempts: map[uint32]*dm.Attempt{1: {}, 2: {}}},
-									z: {Attempts: map[uint32]*dm.Attempt{1: {}}},
-								},
-							})
-						})
-
-						Convey("walk (dfs)", func() {
-							req.Mode.Dfs = true
-							So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-								Quests: map[string]*dm.Quest{
-									w: {Attempts: map[uint32]*dm.Attempt{1: {}}},
-									x: {Attempts: map[uint32]*dm.Attempt{1: {}, 2: {}}},
-									z: {Attempts: map[uint32]*dm.Attempt{1: {}}},
-								},
-							})
-						})
-
-					})
-
-					Convey("attemptlist", func() {
-						req.Include.Quest.Ids = true
-						req.Include.Attempt.Ids = true
-						req.Query = dm.AttemptListQueryL(map[string][]uint32{x: nil})
-						So(req, fake.WalkShouldReturn(c, s), &dm.GraphData{
-							Quests: map[string]*dm.Quest{
-								x: {
-									Id: dm.NewQuestID(x),
-									Attempts: map[uint32]*dm.Attempt{
-										1: {Id: dm.NewAttemptID(x, 1)},
-										2: {Id: dm.NewAttemptID(x, 2)},
-									},
-								},
-							},
-						})
-					})
-
-				})
-
-				// This is disabled because it was flaky.
-				// BUG: crbug.com/621170
-				SkipConvey("early stop", func() {
-					req.Limit.MaxDepth = 100
-					req.Limit.MaxTime = durationpb.New(time.Nanosecond)
-					tc := clock.Get(c).(testclock.TestClock)
-					tc.SetTimerCallback(func(d time.Duration, t clock.Timer) {
-						tc.Add(d + time.Second)
-					})
-					ret, err := s.WalkGraph(c, req)
-					So(err, ShouldBeNil)
-					So(ret.HadMore, ShouldBeTrue)
-				})
-
-			})
-		})
-	})
-}
diff --git a/dm/appengine/dispatch.yaml b/dm/appengine/dispatch.yaml
deleted file mode 100644
index a5cb355..0000000
--- a/dm/appengine/dispatch.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-dispatch:
-  - url: "*/rpcexplorer/*"
-    module: static
-  - url: "*/static/*"
-    module: static
diff --git a/dm/appengine/distributor/config.go b/dm/appengine/distributor/config.go
deleted file mode 100644
index 4905c7b..0000000
--- a/dm/appengine/distributor/config.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package distributor
-
-import (
-	"context"
-	"fmt"
-
-	"google.golang.org/protobuf/proto"
-
-	"go.chromium.org/luci/common/gcloud/pubsub"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/gae/service/info"
-	tq "go.chromium.org/luci/gae/service/taskqueue"
-)
-
-// Config represents the configuration for a single instance of a given
-// distributor implementation at a given point in time (e.g. version).
-type Config struct {
-	// DMHost is the host for the DM API. This may be used by the distributor
-	// implementation to pass to jobs so that they can call back into DM's api.
-	DMHost string
-
-	// Name is the name of this distributor configuration. This is always the
-	// fully-resolved name of the configuration (i.e. aliases are dereferenced).
-	Name string
-
-	// Version is the version of the distributor configuration retrieved from
-	// luci-config.
-	Version string
-
-	// Content is the actual parsed implementation-specific configuration.
-	Content proto.Message
-}
-
-// EnqueueTask allows a Distributor to enqueue a TaskQueue task that will be
-// handled by the Distributor's HandleTaskQueueTask method.
-func (cfg *Config) EnqueueTask(c context.Context, tsk *tq.Task) error {
-	tsk.Path = handlerPath(cfg.Name)
-	return tq.Add(c, "", tsk)
-}
-
-// PrepareTopic returns a pubsub topic that notifications should be sent to, and
-// is meant to be called from the D.Run method.
-//
-// It returns the full name of the topic and a token that will be used to route
-// PubSub messages back to the Distributor. The publisher to the topic must be
-// instructed to put the token into the 'auth_token' attribute of PubSub
-// messages. DM will know how to route such messages to D.HandleNotification.
-func (cfg *Config) PrepareTopic(c context.Context, eid *dm.Execution_ID) (topic pubsub.Topic, token string, err error) {
-	topic = pubsub.NewTopic(info.TrimmedAppID(c), notifyTopicSuffix)
-	if err := topic.Validate(); err != nil {
-		panic(fmt.Errorf("failed to validate Topic %q: %s", topic, err))
-	}
-	token, err = encodeAuthToken(c, eid, cfg.Name)
-	return
-}
diff --git a/dm/appengine/distributor/distributor.go b/dm/appengine/distributor/distributor.go
deleted file mode 100644
index fdf999b..0000000
--- a/dm/appengine/distributor/distributor.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package distributor contains all the adaptors for the various supported
-// distributor protocols. At a high level, it works like this:
-//   * Quests specify a distributor configuration by name as part of their
-//     identity.
-//   * When an Execution for that Quest NeedsExecution, DM reads configuration
-//     (distributor.proto) from luci-config. This configuration is stored
-//     as part of the Execution so that for the duration of a given Exectuion,
-//     DM always interacts with the same distributor in the same way (barring
-//     code changes in DM's adapter logic itself).
-//   * DM uses the selected distributor implementation to start a task and
-//     record its Token. Additionally, the distributor SHOULD publish on DM's
-//     pubsub topic to update DM's state. When publishing updates, the
-//     distributor MUST include the token returned from PrepareTopic (or else
-//     the published update will be ignored).
-//   * When DM gets a hit on pubsub, it will load the Execution, load its cached
-//     distributor configuration, and then call HandleNotification for the
-//     adapter to parse the notification body and return the state of the task.
-//
-// Adding a new distributor requires:
-//   * Add a new subdir of protos with the configuration proto for the new
-//     distributor. Each distributor implementation must have its own unique
-//     Config message.
-//   * Add a matching subdir of this package for the implementation of the
-//     distributor.
-//   * In the implementation, add a Register method that registers the
-//     implementation with this package appropriately.
-//   * In the DM frontend, import your new package implementation and run its
-//     Register method.
-package distributor
-
-import (
-	"context"
-	"net/http"
-	"time"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-// Token is an opaque token that a distributor should use to
-// uniquely identify a single DM execution.
-type Token string
-
-// Notification represents a notification from the distributor to DM that
-// a particular execution has a status update. Data and Attrs are interpreted
-// purely by the distributor implementation.
-type Notification struct {
-	ID    *dm.Execution_ID
-	Data  []byte
-	Attrs map[string]string
-}
-
-// D is the interface for all distributor implementations.
-//
-// Retries
-//
-// Unless otherwise noted, DM will retry methods here if they return an error
-// marked as Transient, up to some internal limit. If they return
-// a non-Transient error (or nil) DM will make a best effort not to duplicate
-// calls, but it can't guarantee that.
-type D interface {
-	// Run prepares and runs a new Task from the given parameters.
-	//
-	// Scheduling the same execution ID multiple times SHOULD return the same
-	// Token. It's OK if this doesn't happen, but only one of the scheduled tasks
-	// will be able to invoke ActivateExecution; the other one(s) will
-	// early-abort and/or timeout.
-	//
-	// If this returns a non-Transient error, the Execution will be marked as
-	// Rejected with the returned error message as the 'Reason'.
-	//
-	// The various time durations, if non-zero, will be used verbatim for DM to
-	// timeout that phase of the task's execution. If the task's execution times
-	// out in the 'STOPPING' phase, DM will poll the distributor's GetStatus
-	// method up to 3 times with a 30-second gap to attempt to retrieve the final
-	// information. After more than 3 times, DM will give up and mark the task as
-	// expired.
-	//
-	// If the distributor doesn't intend to use Pubsub for notifying DM about the
-	// final status of the job, set pollTimeout to the amount of time you want DM
-	// to wait before polling GetStatus. e.g. if after calling FinishAttempt or
-	// EnsureGraphData your distributor needs 10 seconds before it can correctly
-	// respond to a GetStatus request, you should set pollTimeout to >= 10s.
-	// Otherwise pollTimeout should be set fairly high (e.g. 12 hours) as a hedge
-	// against a broken pubsub notification pipeline.
-	//
-	// If you have the choice between pubsub or not, prefer to use pubsub as it
-	// allows DM to more proactively update the graph state (and unblock waiting
-	// Attempts, etc.)
-	Run(qst *dm.Quest_Desc, auth *dm.Execution_Auth, prevResult *dm.JsonResult) (tok Token, pollTimeout time.Duration, err error)
-
-	// Cancel attempts to cancel a running task. If a task is canceled more than
-	// once, this should return nil.
-	Cancel(*dm.Quest_Desc, Token) error
-
-	// GetStatus retrieves the current state of the task from the distributor.
-	//
-	// If this returns a non-Transient error more than 30 seconds after the task
-	// was Run(), the execution will be marked Missing with the returned error
-	// message as the 'Reason'. If it returns a non-Transient error within 30
-	// seconds of being run, DM will automatically treat that as Transient.
-	GetStatus(*dm.Quest_Desc, Token) (*dm.Result, error)
-
-	// InfoURL calculates a user-presentable information url for the task
-	// identified by Token. This should be a local operation, so it is not the
-	// implementation's responsibility to validate the token in this method (e.g.
-	// it could point to a non-existent job, etc.)
-	InfoURL(Token) string
-
-	// HandleNotification is called whenever DM receives a PubSub message sent to
-	// a topic created with Config.PrepareTopic. The Attrs map will omit
-	// the 'auth_token' field.
-	//
-	// Returning (nil, nil) will indicate that DM should ignore this notification.
-	//
-	// DM will convert pubsub Messages to a delayed GetStatus if a pubsub message
-	// is delivered which refers to an Attempt whose status is NeedsExecution,
-	// which could happen in the event of a not-fully-settled transacion.
-	//
-	// DM will ignore any notifications for executions which it doesn't know
-	// about.
-	HandleNotification(qst *dm.Quest_Desc, notification *Notification) (*dm.Result, error)
-
-	// HandleTaskQueueTask is called if the distributor used Config.EnqueueTask.
-	//
-	// It may return zero or more Notifications for DM about arbitrary Executions.
-	// These notifications will be handled 'later' by the HandleNotification
-	// implementation.
-	HandleTaskQueueTask(*http.Request) ([]*Notification, error)
-
-	// Validate should return a non-nil error if the given distributor parameters
-	// are not appropriate for this Distributor. Payload is guaranteed to be
-	// a valid JSON object. This should validate that the content of that JSON
-	// object is what the distributor expects.
-	Validate(parameters string) error
-}
-
-// Factory is a function which produces new distributor instance with the
-// provided configuration proto.
-//
-// c is guaranteed to be non-transactional.
-type Factory func(c context.Context, dist *Config) (D, error)
diff --git a/dm/appengine/distributor/fake/fake.go b/dm/appengine/distributor/fake/fake.go
deleted file mode 100644
index 1653bac..0000000
--- a/dm/appengine/distributor/fake/fake.go
+++ /dev/null
@@ -1,507 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package fake
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"net/http"
-	"sync"
-	"time"
-
-	"google.golang.org/protobuf/types/known/timestamppb"
-
-	"go.chromium.org/luci/auth/identity"
-	"go.chromium.org/luci/common/gcloud/pubsub"
-	"go.chromium.org/luci/common/testing/assertions"
-	"go.chromium.org/luci/config"
-	"go.chromium.org/luci/config/cfgclient"
-	config_mem "go.chromium.org/luci/config/impl/memory"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/server/auth"
-	"go.chromium.org/luci/server/auth/authtest"
-	"go.chromium.org/luci/server/secrets"
-	"go.chromium.org/luci/server/secrets/testsecrets"
-	"go.chromium.org/luci/tumble"
-
-	"google.golang.org/protobuf/proto"
-)
-
-// Setup creates a new combination of testing and context objects:
-//   * ttest - a tumble.Testing to allow you to control tumble's processing
-//     state
-//   * c - a context which includes a testing distributor registry, testsecrets,
-//     as well as everything that tumble.Testing.Context adds (datastore,
-//     memcache, etc.)
-//   * dist - a fake Distributor implementation with a RunTask method that
-//     allows your test to 'run' a scheduled task with the Distributor. This
-//     will automatically notify the deps service (by calling `fn`).
-//
-// You should pass mutate.FinishExecutionFn for fn. It's not done automatically
-// in order to break an import cycle. You could provide your own, but YMMV.
-//
-// This sets the following configuration using the memory configuration mock:
-//   services/app/acls.cfg:
-//     readers: "reader_group"
-//     writers: "writer_group"
-//
-// Usage:
-//   ttest, c, dist := fake.Setup(mutate.FinishExecutionFn)
-//   s := deps.NewDecoratedServer()
-//   # your tests
-func Setup(fn distributor.FinishExecutionFn) (ttest *tumble.Testing, c context.Context, dist *Distributor) {
-	ttest = &tumble.Testing{}
-	c = ttest.Context()
-	c = secrets.Use(c, &testsecrets.Store{})
-
-	c = cfgclient.Use(c, config_mem.New(map[config.Set]config_mem.Files{
-		"services/${appid}": {
-			"acls.cfg": `
-				readers: "reader_group"
-				writers: "writer_group"
-			`,
-		},
-	}))
-	c = auth.WithState(c, &authtest.FakeState{
-		Identity: identity.AnonymousIdentity,
-	})
-	dist = &Distributor{}
-	reg := distributor.NewTestingRegistry(distributor.TestFactoryMap{
-		"fakeDistributor": func(c context.Context, cfg *distributor.Config) distributor.D {
-			return &BoundDistributor{dist, c, cfg}
-		},
-	}, fn)
-	c = distributor.WithRegistry(c, reg)
-	return
-}
-
-// DistributorData is the blob of data that the fake.Distributor keeps when DM
-// calls its Run method. This is roughly equivalent to the state that
-// a distributor (like swarming) would store in its own datastore about a job.
-type DistributorData struct {
-	NotifyTopic pubsub.Topic
-	NotifyAuth  string
-
-	Auth *dm.Execution_Auth
-	Desc *dm.Quest_Desc
-
-	State *dm.JsonResult
-
-	done   bool
-	abnorm *dm.AbnormalFinish
-}
-
-// Task is the detail that the distributor task would get. This is roughly
-// equivalent to the input that the swarming task/recipe engine would get.
-type Task struct {
-	Auth *dm.Execution_Auth
-	Desc *dm.Quest_Desc
-	// State is read/writable.
-	State *dm.JsonResult
-}
-
-// Activate does the activation handshake with the provided DepsServer and
-// returns an ActivatedTask.
-func (t *Task) Activate(c context.Context, s dm.DepsServer) (*ActivatedTask, error) {
-	newTok := model.MakeRandomToken(c, 32)
-	_, err := s.ActivateExecution(c, &dm.ActivateExecutionReq{
-		Auth: t.Auth, ExecutionToken: newTok})
-	if err != nil {
-		return nil, err
-	}
-
-	return &ActivatedTask{
-		s,
-		c,
-		&dm.Execution_Auth{Id: t.Auth.Id, Token: newTok},
-		t.Desc,
-		t.State,
-	}, nil
-}
-
-// MustActivate does the same thing as Activate, but panics if err != nil.
-func (t *Task) MustActivate(c context.Context, s dm.DepsServer) *ActivatedTask {
-	ret, err := t.Activate(c, s)
-	panicIf(err)
-	return ret
-}
-
-// ActivatedTask is like a Task, but exists after calling Task.MustActivate, and
-// contains an activated authentication token. This may be used to either add
-// new dependencies or to provide a finished result.
-//
-// The implementation of DepsServer also automatically populates all outgoing
-// RPCs with the activated Auth value.
-type ActivatedTask struct {
-	s dm.DepsServer
-	c context.Context
-
-	Auth *dm.Execution_Auth
-	Desc *dm.Quest_Desc
-	// State is read/writable.
-	State *dm.JsonResult
-}
-
-// WalkGraph calls the bound DepsServer's WalkGraph method with the activated
-// Auth field.
-func (t *ActivatedTask) WalkGraph(req *dm.WalkGraphReq) (*dm.GraphData, error) {
-	newReq := *req
-	newReq.Auth = t.Auth
-	return t.s.WalkGraph(t.c, &newReq)
-}
-
-// EnsureGraphData calls the bound DepsServer's EnsureGraphData method with the
-// activated Auth field in ForExecution.
-func (t *ActivatedTask) EnsureGraphData(req *dm.EnsureGraphDataReq) (*dm.EnsureGraphDataRsp, error) {
-	newReq := *req
-	newReq.ForExecution = t.Auth
-	return t.s.EnsureGraphData(t.c, &newReq)
-}
-
-// DepOn is a shorthand for EnsureGraphData which allows you to depend on
-// multiple existing quests by attempt id. The definitions for these quests must
-// already have been added to the deps server (probably with an EnsureGraphData
-// call).
-func (t *ActivatedTask) DepOn(to ...*dm.Attempt_ID) (bool, error) {
-	req := &dm.EnsureGraphDataReq{RawAttempts: dm.NewAttemptList(nil)}
-	req.RawAttempts.AddAIDs(to...)
-
-	rsp, err := t.EnsureGraphData(req)
-	return rsp.ShouldHalt, err
-}
-
-// MustDepOn is the same as DepOn but will panic if DepOn would have returned
-// a non-nil error.
-func (t *ActivatedTask) MustDepOn(to ...*dm.Attempt_ID) (halt bool) {
-	halt, err := t.DepOn(to...)
-	panicIf(err)
-	return
-}
-
-// Finish calls FinishAttempt with the provided JSON body and optional
-// expiration time.
-//
-// This will panic if you provide more than one expiration time (so don't do
-// that).
-func (t *ActivatedTask) Finish(resultJSON string, expire ...time.Time) {
-	req := &dm.FinishAttemptReq{
-		Auth: t.Auth,
-		Data: dm.NewJsonResult(resultJSON),
-	}
-	switch len(expire) {
-	case 0:
-	case 1:
-		req.Data.Expiration = timestamppb.New(expire[0])
-	default:
-		panic("may only specify 0 or 1 expire values")
-	}
-
-	_, err := t.s.FinishAttempt(t.c, req)
-	panicIf(err)
-}
-
-// WalkShouldReturn is a shorthand for the package-level WalkShouldReturn which
-// binds the activated auth to the WalkGraph request, but otherwise behaves
-// identically.
-//
-// Use this method like:
-//   req := &dm.WalkGraphReq{...}
-//   So(req, activated.WalkShouldReturn, &dm.GraphData{
-//     ...
-//   })
-func (t *ActivatedTask) WalkShouldReturn(request interface{}, expect ...interface{}) string {
-	r := *request.(*dm.WalkGraphReq)
-	r.Auth = t.Auth
-	return WalkShouldReturn(t.c, t.s)(&r, expect...)
-}
-
-// Distributor implements distributor.D, and provides a method (RunTask) to
-// allow a test to actually run a task which has been scheduled on this
-// Distributor, and correctly notify the deps server that the execution is
-// complete.
-type Distributor struct {
-	// RunError can be set to make Run return this error when it's invoked.
-	RunError error
-	// This can be set to turn the distributor into a polling-based distributor.
-	PollbackTime time.Duration
-
-	sync.Mutex
-	tasks map[distributor.Token]*DistributorData
-}
-
-// BoundDistributor binds the fake.Distributor to a Context and
-// a distributor.Config. It implements distributor.D.
-type BoundDistributor struct {
-	*Distributor
-	c   context.Context
-	cfg *distributor.Config
-}
-
-// MakeToken makes a distributor Token out of an Execution_ID. In this
-// implementation of a Distributor there's a 1:1 mapping between Execution_ID
-// and distributor task. This is not always the case for real distributor
-// implementations.
-func MakeToken(eid *dm.Execution_ID) distributor.Token {
-	return distributor.Token(fmt.Sprintf("fakeDistributor:%s|%d|%d", eid.Quest,
-		eid.Attempt, eid.Id))
-}
-
-// Run implements distributor.D
-func (d *BoundDistributor) Run(desc *dm.Quest_Desc, exAuth *dm.Execution_Auth, prev *dm.JsonResult) (tok distributor.Token, pollbackTime time.Duration, err error) {
-	if err = d.RunError; err != nil {
-		return
-	}
-	pollbackTime = d.PollbackTime
-
-	tok = MakeToken(exAuth.Id)
-
-	tsk := &DistributorData{
-		Auth:  exAuth,
-		Desc:  desc,
-		State: prev,
-	}
-	tsk.NotifyTopic, tsk.NotifyAuth, err = d.cfg.PrepareTopic(d.c, exAuth.Id)
-	panicIf(err)
-
-	d.Lock()
-	defer d.Unlock()
-	if d.tasks == nil {
-		d.tasks = map[distributor.Token]*DistributorData{}
-	}
-	d.tasks[tok] = tsk
-	return
-}
-
-// Cancel implements distributor.D
-func (d *BoundDistributor) Cancel(_ *dm.Quest_Desc, tok distributor.Token) (err error) {
-	d.Lock()
-	defer d.Unlock()
-	if tsk, ok := d.tasks[tok]; ok {
-		tsk.done = true
-		tsk.abnorm = &dm.AbnormalFinish{
-			Status: dm.AbnormalFinish_CANCELLED,
-			Reason: "cancelled via Cancel()"}
-	} else {
-		err = fmt.Errorf("MISSING task %q", tok)
-	}
-	return
-}
-
-// GetStatus implements distributor.D
-func (d *BoundDistributor) GetStatus(_ *dm.Quest_Desc, tok distributor.Token) (rslt *dm.Result, err error) {
-	d.Lock()
-	defer d.Unlock()
-	if tsk, ok := d.tasks[tok]; ok {
-		if tsk.done {
-			if tsk.abnorm != nil {
-				rslt = &dm.Result{AbnormalFinish: tsk.abnorm}
-			} else {
-				rslt = &dm.Result{Data: tsk.State}
-			}
-		}
-	} else {
-		rslt = &dm.Result{
-			AbnormalFinish: &dm.AbnormalFinish{
-				Status: dm.AbnormalFinish_MISSING,
-				Reason: fmt.Sprintf("unknown token: %s", tok)},
-		}
-	}
-	return
-}
-
-// FakeURLPrefix is the url that all fake InfoURLs are prefixed with.
-const FakeURLPrefix = "https://info.example.com/"
-
-// InfoURL builds a fake InfoURL for the given Execution_ID
-func InfoURL(e *dm.Execution_ID) string {
-	return FakeURLPrefix + string(MakeToken(e))
-}
-
-// InfoURL implements distributor.D
-func (d *BoundDistributor) InfoURL(tok distributor.Token) string {
-	return FakeURLPrefix + string(tok)
-}
-
-// HandleNotification implements distributor.D
-func (d *BoundDistributor) HandleNotification(q *dm.Quest_Desc, n *distributor.Notification) (rslt *dm.Result, err error) {
-	return d.GetStatus(q, distributor.Token(n.Attrs["token"]))
-}
-
-// HandleTaskQueueTask is not implemented, and shouldn't be needed for most
-// tests. It could be implemented if some new test required it, however.
-func (d *BoundDistributor) HandleTaskQueueTask(r *http.Request) ([]*distributor.Notification, error) {
-	panic("not implemented")
-}
-
-// Validate implements distributor.D (by returning a nil error for every
-// payload).
-func (d *BoundDistributor) Validate(payload string) error {
-	return nil
-}
-
-// RunTask allows you to run the task associated with the provided execution id.
-//
-// If the task corresponding to `eid` returns an error, or if the distributor
-// itself actually has an error, this method will return an error. Notably, if
-// `cb` returns an error, it will simply mark the corresponding task as FAILED,
-// but will return nil here.
-//
-// If the task exists and hasn't been run yet, cb will be called, and can do
-// anything that you may want to a test to do. Think of the callback as the
-// recipe engine; it has the opportunity to do anything it wants to, interact
-// with the deps server (or not), succeed (or not), etc.
-//
-// If the callback needs to maintain state between executions, Task.State is
-// read+write; when the callback exits, the final value of Task.State will be
-// passed back to the DM instance under test. A re-execution of the attempt will
-// start with the new value.
-func (d *Distributor) RunTask(c context.Context, eid *dm.Execution_ID, cb func(*Task) error) (err error) {
-	tok := MakeToken(eid)
-
-	d.Lock()
-	tsk := d.tasks[tok]
-	if tsk == nil {
-		err = fmt.Errorf("cannot RunTask(%q): doesn't exist", tok)
-	} else {
-		if tsk.done {
-			err = fmt.Errorf("cannot RunTask(%q): running twice", tok)
-		} else {
-			tsk.done = true
-		}
-	}
-	d.Unlock()
-
-	if err != nil {
-		return
-	}
-
-	abnorm := (*dm.AbnormalFinish)(nil)
-
-	usrTsk := &Task{
-		tsk.Auth,
-		tsk.Desc,
-		tsk.State,
-	}
-
-	defer func() {
-		d.Lock()
-		{
-			tsk.abnorm = abnorm
-			tsk.State = usrTsk.State
-
-			if r := recover(); r != nil {
-				tsk.abnorm = &dm.AbnormalFinish{
-					Status: dm.AbnormalFinish_CRASHED,
-					Reason: fmt.Sprintf("caught panic: %q", r),
-				}
-			}
-		}
-		d.Unlock()
-
-		err = tumble.RunMutation(c, &distributor.NotifyExecution{
-			CfgName: "fakeDistributor",
-			Notification: &distributor.Notification{
-				ID:    tsk.Auth.Id,
-				Attrs: map[string]string{"token": string(tok)}},
-		})
-	}()
-
-	err = cb(usrTsk)
-	if err != nil {
-		err = nil
-		abnorm = &dm.AbnormalFinish{
-			Status: dm.AbnormalFinish_FAILED,
-			Reason: fmt.Sprintf("cb error: %q", err),
-		}
-	}
-	return
-}
-
-func panicIf(err error) {
-	if err != nil {
-		panic(err)
-	}
-}
-
-var _ distributor.D = (*BoundDistributor)(nil)
-
-// QuestDesc generates a normalized generic QuestDesc of the form:
-//   Quest_Desc{
-//     DistributorConfigName: "fakeDistributor",
-//     Parameters:            `{"name":"$name"}`,
-//     DistributorParameters: "{}",
-//   }
-func QuestDesc(name string) *dm.Quest_Desc {
-	params, err := json.Marshal(struct {
-		Name string `json:"name"`
-	}{name})
-	panicIf(err)
-	desc := &dm.Quest_Desc{
-		DistributorConfigName: "fakeDistributor",
-		Parameters:            string(params),
-		DistributorParameters: "{}",
-	}
-	panicIf(desc.Normalize())
-	return desc
-}
-
-// WalkShouldReturn is a convey-style assertion factory to assert that a given
-// WalkGraph request object results in the provided GraphData.
-//
-// If keepTimestamps (a singular, optional boolean) is provided and true,
-// WalkShouldReturn will not remove timestamps from the compared GraphData. If
-// it is absent or false, GraphData.PurgeTimestamps will be called on the
-// returned GraphData before comparing it to the expected value.
-//
-// Use this function like:
-//   req := &dm.WalkGraphReq{...}
-//   So(req, WalkShouldReturn(c, s), &dm.GraphData{
-//     ...
-//   })
-func WalkShouldReturn(c context.Context, s dm.DepsServer, keepTimestamps ...bool) func(request interface{}, expect ...interface{}) string {
-	kt := len(keepTimestamps) > 0 && keepTimestamps[0]
-	if len(keepTimestamps) > 1 {
-		panic("may only specify 0 or 1 keepTimestamps values")
-	}
-
-	normalize := func(gd *dm.GraphData) *dm.GraphData {
-		data, err := proto.Marshal(gd)
-		panicIf(err)
-		ret := &dm.GraphData{}
-
-		panicIf(proto.Unmarshal(data, ret))
-
-		if !kt {
-			ret.PurgeTimestamps()
-		}
-		return ret
-	}
-
-	return func(request interface{}, expect ...interface{}) string {
-		r := request.(*dm.WalkGraphReq)
-		if len(expect) != 1 {
-			panic(fmt.Errorf("expected 1 arg on rhs, got %d", len(expect)))
-		}
-		e := expect[0].(*dm.GraphData)
-		ret, err := s.WalkGraph(c, r)
-		if nilExpect := assertions.ShouldErrLike(err, nil); nilExpect != "" {
-			return nilExpect
-		}
-		return assertions.ShouldResembleProto(normalize(ret), e)
-	}
-}
diff --git a/dm/appengine/distributor/handlers.go b/dm/appengine/distributor/handlers.go
deleted file mode 100644
index a7e56b4..0000000
--- a/dm/appengine/distributor/handlers.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package distributor
-
-import (
-	"go.chromium.org/luci/appengine/gaemiddleware"
-	"go.chromium.org/luci/server/router"
-)
-
-// InstallHandlers installs the taskqueue callback handler.
-//
-// The `base` middleware must have a registry installed with WithRegistry.
-func InstallHandlers(r *router.Router, base router.MiddlewareChain) {
-	r.POST(handlerPattern, base.Extend(gaemiddleware.RequireTaskQueue("")), TaskQueueHandler)
-	r.POST("/_ah/push-handlers/"+notifyTopicSuffix, base, PubsubReceiver)
-}
diff --git a/dm/appengine/distributor/jobsim/distributor.go b/dm/appengine/distributor/jobsim/distributor.go
deleted file mode 100644
index e0ad25b..0000000
--- a/dm/appengine/distributor/jobsim/distributor.go
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package jobsim
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"time"
-
-	"google.golang.org/protobuf/encoding/protojson"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/taskqueue"
-
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/retry"
-	"go.chromium.org/luci/dm/api/distributor/jobsim"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor"
-)
-
-type jobsimDist struct {
-	c   context.Context
-	cfg *distributor.Config
-}
-
-func (j *jobsimDist) jsConfig() *jobsim.Config {
-	return j.cfg.Content.(*jobsim.Config)
-}
-
-func (j *jobsimDist) parsePayload(payload string) (*jobsimExecution, error) {
-	ret := &jobsimExecution{}
-	err := protojson.Unmarshal([]byte(payload), &ret.Calculation)
-	return ret, err
-}
-
-func (j *jobsimDist) Run(desc *dm.Quest_Desc, exAuth *dm.Execution_Auth, prev *dm.JsonResult) (tok distributor.Token, _ time.Duration, err error) {
-	// TODO(riannucci): Fix luci-gae so we can truly escape the transaction when
-	// we build the jobsimDist instance. See luci/gae#23.
-	c := ds.WithoutTransaction(j.c)
-
-	logging.Fields{
-		"eid": exAuth.Id,
-	}.Infof(j.c, "jobsim: running new task")
-
-	jtsk, err := j.parsePayload(desc.Parameters)
-	if err != nil {
-		return
-	}
-	jtsk.ExAuth = *exAuth
-	jtsk.Status = jobsimRunnable
-	if prev != nil {
-		jtsk.StateOrReason = prev.Object
-	}
-	jtsk.CfgName = j.cfg.Name
-
-	key := []*ds.Key{
-		ds.MakeKey(c, ds.GetMetaDefault(ds.GetPLS(jtsk), "kind", ""), 0)}
-	if err = ds.AllocateIDs(c, key); err != nil {
-		return
-	}
-
-	// transactionally commit the job and a taskqueue task to execute it
-	jtsk.ID = fmt.Sprintf("%s|%d", j.jsConfig().Pool, key[0].IntID())
-	logging.Infof(j.c, "jobsim: entering transaction")
-	err = ds.RunInTransaction(c, func(c context.Context) error {
-		if err := ds.Get(c, jtsk); err == nil {
-			return nil
-		}
-		logging.Infof(j.c, "jobsim: got jtsk: %s", err)
-
-		if err := ds.Put(c, jtsk); err != nil {
-			return err
-		}
-		logging.Infof(j.c, "jobsim: put jtsk")
-
-		err := j.cfg.EnqueueTask(c, &taskqueue.Task{
-			Payload: []byte(jtsk.ID),
-		})
-		if err != nil {
-			logging.WithError(err).Errorf(j.c, "jobsim: got EnqueueTask error")
-			return err
-		}
-		logging.Infof(j.c, "jobsim: EnqueueTask'd")
-		return nil
-	}, nil)
-
-	tok = distributor.Token(jtsk.ID)
-	return
-}
-
-func (j *jobsimDist) Cancel(_ *dm.Quest_Desc, tok distributor.Token) error {
-	jtsk := &jobsimExecution{ID: string(tok)}
-
-	cancelBody := func(c context.Context) (needWrite bool, err error) {
-		if err = ds.Get(c, jtsk); err != nil {
-			return
-		}
-		if jtsk.Status != jobsimRunnable {
-			return
-		}
-		needWrite = true
-		return
-	}
-
-	if needWrite, err := cancelBody(j.c); err != nil || !needWrite {
-		return err
-	}
-
-	return ds.RunInTransaction(j.c, func(c context.Context) error {
-		if needWrite, err := cancelBody(c); err != nil || !needWrite {
-			return err
-		}
-		jtsk.Status = jobsimCancelled
-		return ds.Put(c, jtsk)
-	}, nil)
-}
-
-func (j *jobsimDist) GetStatus(_ *dm.Quest_Desc, tok distributor.Token) (*dm.Result, error) {
-	jtsk, err := loadTask(j.c, string(tok))
-	if err != nil {
-		return nil, err
-	}
-
-	return getAttemptResult(jtsk.Status, jtsk.StateOrReason), nil
-}
-
-func (j *jobsimDist) InfoURL(tok distributor.Token) string {
-	return fmt.Sprintf("jobsim://%s/ver/%s/tok/%s", j.cfg.Name, j.cfg.Version, tok)
-}
-
-func (j *jobsimDist) HandleNotification(_ *dm.Quest_Desc, note *distributor.Notification) (*dm.Result, error) {
-	n := &notification{}
-	err := json.Unmarshal(note.Data, n)
-	if err != nil {
-		return nil, err
-	}
-
-	return getAttemptResult(n.Status, n.StateOrReason), nil
-}
-
-func loadTask(c context.Context, rawTok string) (*jobsimExecution, error) {
-	logging.Fields{
-		"jobsimId": rawTok,
-	}.Infof(c, "jobsim: loading task")
-
-	jtsk := &jobsimExecution{ID: string(rawTok)}
-	if err := ds.Get(c, jtsk); err != nil {
-		logging.WithError(err).Errorf(c, "jobsim: failed to load task")
-		return nil, err
-	}
-
-	logging.Fields{
-		"eid": jtsk.ExAuth.Id,
-	}.Infof(c, "jobsim: execution context")
-
-	return jtsk, nil
-}
-
-func (j *jobsimDist) HandleTaskQueueTask(r *http.Request) (notes []*distributor.Notification, err error) {
-	// this function is what the lifetime of a remote-execution distributor (like
-	// swarming) would do when running a scheduled task.
-
-	// body is a distributor.Token
-	rawTok, err := ioutil.ReadAll(r.Body)
-	if err != nil {
-		return
-	}
-
-	jtsk, err := loadTask(j.c, string(rawTok))
-	if err != nil {
-		return
-	}
-
-	if jtsk.Status != jobsimRunnable {
-		logging.Infof(j.c, "jobsim: task is not scheduled")
-		return
-	}
-	jtsk.Status = jobsimRunning
-	if err := ds.Put(j.c, jtsk); err != nil {
-		logging.WithError(err).Warningf(j.c, "jobsim: failed to update task to Execution_Running")
-	}
-
-	state := &state{}
-	if err = state.fromPersistentState(jtsk.StateOrReason); err != nil {
-		logging.Fields{
-			logging.ErrorKey: err,
-			"state":          jtsk.StateOrReason,
-		}.Errorf(j.c, "jobsim: unable to inflate PersistentState")
-		return
-	}
-
-	// this is the part that the swarming client/recipe would do.
-	err = runJob(j.c, j.cfg.DMHost, state, &jtsk.Calculation, &jtsk.ExAuth, jtsk.CfgName)
-	if err != nil {
-		jtsk.Status = jobsimFailed
-		jtsk.StateOrReason = err.Error()
-	} else {
-		jtsk.Status = jobsimFinished
-		jtsk.StateOrReason = state.toPersistentState()
-	}
-
-	err = retry.Retry(j.c, retry.Default, func() error {
-		return ds.Put(j.c, jtsk)
-	}, func(err error, wait time.Duration) {
-		logging.Fields{
-			logging.ErrorKey: err,
-			"wait":           wait,
-		}.Warningf(j.c, "jobsim: failed to put task")
-	})
-	if err != nil {
-		logging.WithError(err).Errorf(j.c, "jobsim: FATAL: failed to put task")
-		return
-	}
-
-	notes = append(notes, &distributor.Notification{
-		ID:   jtsk.ExAuth.Id,
-		Data: (&notification{jtsk.Status, state.toPersistentState()}).toJSON(),
-	})
-	return
-}
-
-func (j *jobsimDist) Validate(payload string) error {
-	_, err := j.parsePayload(payload)
-	return err
-}
-
-// AddFactory adds this distributor implementation into the distributor
-// Registry.
-func AddFactory(m distributor.FactoryMap) {
-	m[(*jobsim.Config)(nil)] = func(c context.Context, cfg *distributor.Config) (distributor.D, error) {
-		return &jobsimDist{c, cfg}, nil
-	}
-}
diff --git a/dm/appengine/distributor/jobsim/model.go b/dm/appengine/distributor/jobsim/model.go
deleted file mode 100644
index 1bc1402..0000000
--- a/dm/appengine/distributor/jobsim/model.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package jobsim
-
-import (
-	"encoding/json"
-	"time"
-
-	"github.com/golang/protobuf/jsonpb"
-	"google.golang.org/protobuf/encoding/protojson"
-
-	"go.chromium.org/luci/dm/api/distributor/jobsim"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-type jobsimStatus string
-
-const (
-	jobsimRunnable  jobsimStatus = "runnable"
-	jobsimRunning   jobsimStatus = "running"
-	jobsimFailed    jobsimStatus = "failed"
-	jobsimCancelled jobsimStatus = "cancelled"
-	jobsimFinished  jobsimStatus = "finished"
-)
-
-type jobsimExecution struct {
-	_  string `gae:"$kind,jobsim.Task"`
-	ID string `gae:"$id"`
-
-	Status        jobsimStatus `gae:",noindex"`
-	StateOrReason string       `gae:",noindex"`
-
-	ExAuth dm.Execution_Auth `gae:",noindex"`
-
-	Calculation jobsim.Phrase `gae:",noindex"`
-	CfgName     string        `gae:",noindex"`
-}
-
-func getAttemptResult(status jobsimStatus, stateOrReason string) *dm.Result {
-	switch status {
-	case jobsimRunnable, jobsimRunning:
-		return nil
-
-	case jobsimFinished:
-		return &dm.Result{
-			Data: dm.NewJsonResult(stateOrReason)}
-	}
-
-	tr := &dm.Result{AbnormalFinish: &dm.AbnormalFinish{
-		Reason: stateOrReason}}
-	switch status {
-	case jobsimFailed:
-		tr.AbnormalFinish.Status = dm.AbnormalFinish_FAILED
-	case jobsimCancelled:
-		tr.AbnormalFinish.Status = dm.AbnormalFinish_CANCELLED
-	}
-	return tr
-}
-
-func executionResult(success bool, value int64, exp time.Time) *dm.JsonResult {
-	data, err := (&jsonpb.Marshaler{}).MarshalToString(&jobsim.Result{
-		Success: success, Value: value})
-	if err != nil {
-		panic(err)
-	}
-	return dm.NewJsonResult(data, exp)
-}
-
-func executionResultFromJSON(data *dm.JsonResult) (ret *jobsim.Result, err error) {
-	ret = &jobsim.Result{}
-	err = protojson.Unmarshal([]byte(data.Object), ret)
-	return
-}
-
-type notification struct {
-	Status        jobsimStatus
-	StateOrReason string
-}
-
-func (n *notification) toJSON() []byte {
-	ret, err := json.Marshal(n)
-	if err != nil {
-		panic(err)
-	}
-	return ret
-}
diff --git a/dm/appengine/distributor/jobsim/run.go b/dm/appengine/distributor/jobsim/run.go
deleted file mode 100644
index d6116f9..0000000
--- a/dm/appengine/distributor/jobsim/run.go
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package jobsim
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"math/rand"
-	"net/http"
-	"time"
-
-	"github.com/golang/protobuf/jsonpb"
-	"google.golang.org/grpc/codes"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/data/rand/cryptorand"
-	"go.chromium.org/luci/common/lhttp"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/dm/api/distributor/jobsim"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/grpc/grpcutil"
-	"go.chromium.org/luci/grpc/prpc"
-	authlib "go.chromium.org/luci/server/auth"
-)
-
-// state is the opaque state data that DM will pass between re-executions of the
-// same Attempt. For jobsim, which just does accumulating math calculations,
-// this state is very simple. For a recipe, it could be more complicated, and on
-// swarming, 'state' could be e.g. ISOLATED_OUTDIR's isolate hash.
-//
-// Generically, this COULD be used to cache e.g. all previous dependencies, but
-// it's generally better to cache the result of consuming those dependencies,
-// if possible (to avoid doing unnecessary work on subsequent executions).
-type state struct {
-	Stage int
-	Sum   int64
-}
-
-func (st *state) toPersistentState() string {
-	ret, err := json.Marshal(st)
-	if err != nil {
-		panic(err)
-	}
-	return string(ret)
-}
-
-func (st *state) fromPersistentState(s string) (err error) {
-	if s == "" {
-		return nil
-	}
-	return json.Unmarshal([]byte(s), st)
-}
-
-// runner holds the context for a single execution of the JobSim task. You could
-// think of this as the recipe engine. Everything that the runner does would
-// need to be done by any DM client during a single Execution in some form or
-// another.
-type runner struct {
-	c context.Context
-
-	// auth contains the current Execution_Auth for this Execution. It begins with
-	// Token == activation token (what DM submits to swarming), which is then
-	// transmuted by activateExecution into an execution token (basically, the
-	// Execution becomes active on it's first contact with DM, which prevents
-	// accidental retries/duplication of Execution work. Retries of failed
-	// Executions need to be handled by DM for this reason).
-	auth *dm.Execution_Auth
-
-	// dmc is just a DM pRPC client
-	dmc dm.DepsClient
-
-	// state is the mutable state for this Execution. It begins with the value of
-	// the previous Execution. When this execution finishes, the new value will be
-	// passed to the next Execution.
-	state *state
-}
-
-// getRandom returns a random byte sequence of `want` length, or an error if
-// that number of random bytes could not be generated.
-//
-// This uses cryptorand to generate cryptographically secure random numbers.
-func getRandom(c context.Context, want int) ([]byte, error) {
-	ret := make([]byte, want)
-	_, err := cryptorand.Read(c, ret)
-	if err != nil {
-		logging.WithError(err).Errorf(c, "could not generate random data")
-		return nil, err
-	}
-	return ret, nil
-}
-
-// activateExecution is essentially a direct map to ActivateExecution, except
-// that it transforms the runner's `auth` from a needs-activation authentication
-// to an activated one.
-//
-// This returns an OK bool, plus an error. If the bool is true, it means that
-// we're now authenticated. This will never return true with a non-nil error.
-//
-// The return value (false, nil) means the runner should quit peacefully
-// (no-error), and can occur if this execution payload is retried (e.g. by
-// taskqueue).
-func (r *runner) activateExecution() (ok bool, err error) {
-	newToken, err := getRandom(r.c, 128)
-	if err != nil {
-		return false, err
-	}
-
-	_, err = r.dmc.ActivateExecution(r.c, &dm.ActivateExecutionReq{
-		Auth:           r.auth,
-		ExecutionToken: newToken,
-	})
-	if err != nil {
-		logging.WithError(err).Errorf(r.c, "could not activate execution")
-		if grpcutil.Code(err) == codes.Unauthenticated {
-			// means we got retried, so invalidate ExecutionKey and quit peacefully.
-			return false, nil
-		}
-		return false, err
-	}
-	r.auth.Token = newToken
-	logging.Fields{"token": r.auth.Token}.Infof(r.c, "activated execution")
-	return true, nil
-}
-
-// doReturnStage implements the FinishAttempt portion of the DM Attempt
-// lifecycle. This sets the final result for the Attempt, and will prevent any
-// further executions of this Attempt. This is analogous to the recipe returning
-// a final result.
-func (r *runner) doReturnStage(stg *jobsim.ReturnStage) error {
-	retval := int64(0)
-	if stg != nil {
-		retval += stg.Retval
-	}
-	if r.state != nil {
-		retval += r.state.Sum
-	}
-
-	_, err := r.dmc.FinishAttempt(r.c, &dm.FinishAttemptReq{
-		Auth: r.auth,
-		Data: executionResult(true, retval, stg.GetExpiration().AsTime()),
-	})
-	if err != nil {
-		logging.WithError(err).Warningf(r.c, "got error on FinishAttempt")
-	}
-	return err
-}
-
-// doDeps will call EnsureGraphData to make sure the provided
-// quests+attempts+deps exist. DM will see if they're done or not, and let us
-// know if we should stop to be retried later.
-func (r *runner) doDeps(seed int64, stg *jobsim.DepsStage, cfgName string) (stop bool, err error) {
-	logging.Infof(r.c, "doing deps")
-
-	stg.ExpandShards()
-
-	req := &dm.EnsureGraphDataReq{}
-	req.ForExecution = r.auth
-	req.Include = &dm.EnsureGraphDataReq_Include{
-		Attempt: &dm.EnsureGraphDataReq_Include_Options{Result: true}}
-
-	var (
-		rnd = rand.New(rand.NewSource(seed))
-
-		maxAttemptNum  = map[string]uint32{}
-		currentAttempt = map[string]uint32{}
-	)
-
-	for i, dep := range stg.Deps {
-		dep.Seed(rnd, seed, int64(i))
-
-		desc := &dm.Quest_Desc{}
-		desc.DistributorConfigName = cfgName
-		desc.Parameters, err = (&jsonpb.Marshaler{}).MarshalToString(dep.Phrase)
-		if err != nil {
-			panic(err)
-		}
-
-		if err := desc.Normalize(); err != nil {
-			panic(err)
-		}
-
-		req.Quest = append(req.Quest, desc)
-
-		qid := desc.QuestID()
-		currentAttempt[qid] = 1
-		switch x := dep.AttemptStrategy.(type) {
-		case *jobsim.Dependency_Attempts:
-			req.QuestAttempt = append(req.QuestAttempt, &dm.AttemptList_Nums{Nums: x.Attempts.ToSlice()})
-		case *jobsim.Dependency_Retries:
-			maxAttemptNum[qid] = x.Retries + 1
-			req.QuestAttempt = append(req.QuestAttempt, &dm.AttemptList_Nums{Nums: []uint32{1}})
-		}
-	}
-
-	rsp, err := r.dmc.EnsureGraphData(r.c, req)
-	if err != nil {
-		logging.Fields{"err": err}.Infof(r.c, "error after first rpc")
-		return
-	}
-	if stop = rsp.ShouldHalt; stop {
-		logging.Infof(r.c, "halt after first rpc")
-		return
-	}
-
-	sum := int64(0)
-	for {
-		req.Quest = nil
-		req.QuestAttempt = nil
-		req.RawAttempts = dm.NewAttemptList(nil)
-
-		// TODO(iannucci): we could use the state api to remember that we did
-		// retries on the previous execution. The recipe engine should probably do
-		// this for recipes, but for this simple simulator, we'll make multiple
-		// RPCs.
-		for qid, q := range rsp.Result.Quests {
-			logging.Fields{"qid": qid}.Infof(r.c, "grabbing result")
-			var tr *jobsim.Result
-			if currentAttempt[qid] == 0 {
-				// rsp contains bonus data
-				continue
-			}
-			logging.Fields{"atmpt": q.Attempts[currentAttempt[qid]].Data}.Infof(r.c, "grabbing payload")
-			payload := q.Attempts[currentAttempt[qid]].Data.GetFinished().Data
-			tr, err = executionResultFromJSON(payload)
-			if err != nil {
-				return
-			}
-			logging.Fields{"qid": qid, "tr": tr}.Infof(r.c, "decoded TaskResult")
-			if tr.Success {
-				sum += tr.Value
-			} else {
-				current := currentAttempt[qid]
-				if maxAttempt := maxAttemptNum[qid]; maxAttempt > current {
-					if current > maxAttempt {
-						logging.Fields{
-							"qid": qid, "current": current, "max": maxAttempt,
-						}.Infof(r.c, "too many retries")
-						return r.doFailure(seed, 1.1) // guarantee failure
-					}
-					logging.Fields{
-						"qid": qid, "current": current, "max": maxAttempt,
-					}.Infof(r.c, "retrying")
-					current++
-					currentAttempt[qid] = current
-					req.RawAttempts.To[qid].Nums = []uint32{current}
-				} else {
-					logging.Fields{
-						"qid": qid,
-					}.Infof(r.c, "no retries allowed")
-					return r.doFailure(seed, 1.1) // guarantee failure
-				}
-			}
-		}
-		if req.Quest != nil {
-			rsp, err = r.dmc.EnsureGraphData(r.c, req)
-			if err != nil {
-				logging.Fields{"err": err}.Infof(r.c, "err after Nth rpc")
-				return
-			}
-			if stop = rsp.ShouldHalt; stop {
-				logging.Infof(r.c, "halt after Nth rpc")
-				return
-			}
-		} else {
-			r.state.Sum += sum
-			logging.Fields{"sum": sum}.Infof(r.c, "added and advancing")
-			return
-		}
-	}
-}
-
-func (r *runner) doStall(stg *jobsim.StallStage) {
-	dur := stg.Delay.AsDuration()
-	logging.Fields{"duration": dur}.Infof(r.c, "stalling")
-	clock.Sleep(r.c, dur)
-}
-
-// doFailure implements a jobsim task having some flakiness (e.g. it will
-// non-deterministically select to fail at this stage). If it fails, this will
-// cause the overall application-level Attempt Result to indicate failure to any
-// other Attempts which depend on this one.
-//
-// This is analogous to a recipe running a flaky test and then setting its
-// result to be failure. As far as DM is concerned, the recipe ran to completion
-// (e.g. FINISHED). Other recipes may decide to take some action at this stage
-// (e.g. issue new Attempts of this same Quest).
-func (r *runner) doFailure(seed int64, chance float32) (stop bool, err error) {
-	failed := chance >= 1.0
-	if !failed {
-		logging.Fields{"chance": chance}.Infof(r.c, "failing with probability")
-		rndVal := rand.New(rand.NewSource(seed)).Float32()
-		failed = rndVal <= chance
-		logging.Fields{"rndVal": rndVal}.Infof(r.c, "failed")
-	} else {
-		logging.Infof(r.c, "failed (guaranteed)")
-	}
-
-	if !failed {
-		logging.Infof(r.c, "passed")
-		return
-	}
-
-	stop = true
-	_, err = r.dmc.FinishAttempt(r.c, &dm.FinishAttemptReq{
-		Auth: r.auth,
-		Data: executionResult(false, 0, time.Time{}),
-	})
-	if err != nil {
-		logging.WithError(err).Warningf(r.c, "got error on FinishAttempt")
-	}
-	return
-}
-
-// runJob is analogous to a single Execution of a recipe. It will:
-//   * Activate itself with DM.
-//   * Inspect its previous State to determine where it left off on the previous
-//     execution.
-//   * Execute stages (incrementing the Stage counter in the state, and/or
-//     accumulating into Sum) until it hits a stop condition:
-//     * depending on incomplete Attempts
-//     * arriving at a final result
-//
-// If it hits some underlying error it will return that error, and expect to be
-// retried by DM.
-func runJob(c context.Context, host string, state *state, job *jobsim.Phrase, auth *dm.Execution_Auth, cfgName string) error {
-	tr, err := authlib.GetRPCTransport(c, authlib.NoAuth)
-	if err != nil {
-		return err
-	}
-	pcli := &prpc.Client{
-		C:       &http.Client{Transport: tr},
-		Host:    host,
-		Options: prpc.DefaultOptions(),
-	}
-	pcli.Options.Insecure = lhttp.IsLocalHost(host)
-	dmc := dm.NewDepsPRPCClient(pcli)
-	r := runner{c, auth, dmc, state}
-
-	ok, err := r.activateExecution()
-	if !ok || err != nil {
-		return err
-	}
-
-	stop := false
-	for ; r.state.Stage < len(job.Stages); r.state.Stage++ {
-		switch stg := job.Stages[r.state.Stage].StageType.(type) {
-		case *jobsim.Stage_Deps:
-			stop, err = r.doDeps(job.Seed, stg.Deps, cfgName)
-		case *jobsim.Stage_Stall:
-			r.doStall(stg.Stall)
-		case *jobsim.Stage_Failure:
-			stop, err = r.doFailure(job.Seed, stg.Failure.Chance)
-		default:
-			err = fmt.Errorf("don't know how to handle StageType: %T", stg)
-		}
-		if stop || err != nil {
-			return err
-		}
-	}
-	return r.doReturnStage(job.ReturnStage)
-}
diff --git a/dm/appengine/distributor/notify_execution.go b/dm/appengine/distributor/notify_execution.go
deleted file mode 100644
index e118127..0000000
--- a/dm/appengine/distributor/notify_execution.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package distributor
-
-import (
-	"context"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// NotifyExecution is used to finish an execution. Specifically it allows the
-// appropriate distributor to HandleNotification, and then when that concludes,
-// invokes DM's FinishExecution (see mutate.FinishExecution).
-type NotifyExecution struct {
-	CfgName      string
-	Notification *Notification
-}
-
-// Root implements tumble.Mutation.
-func (f *NotifyExecution) Root(c context.Context) *ds.Key {
-	return model.ExecutionKeyFromID(c, f.Notification.ID)
-}
-
-// RollForward implements tumble.Mutation.
-func (f *NotifyExecution) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	reg := GetRegistry(c)
-	dist, _, err := reg.MakeDistributor(c, f.CfgName)
-	if err != nil {
-		logging.Fields{
-			logging.ErrorKey: err,
-			"cfg":            f.CfgName,
-		}.Errorf(c, "Failed to make distributor")
-		return
-	}
-
-	q := &model.Quest{ID: f.Notification.ID.Quest}
-	if err := ds.Get(ds.WithoutTransaction(c), q); err != nil {
-		return nil, errors.Annotate(err, "getting Quest").Err()
-	}
-	rslt, err := dist.HandleNotification(&q.Desc, f.Notification)
-	if err != nil {
-		// TODO(riannucci): check for transient/non-transient
-		logging.Fields{
-			logging.ErrorKey: err,
-			"cfg":            f.CfgName,
-		}.Errorf(c, "Failed to handle notification")
-		return
-	}
-	if rslt != nil {
-		return reg.FinishExecution(c, f.Notification.ID, rslt)
-	}
-	return
-}
-
-func init() {
-	tumble.Register((*NotifyExecution)(nil))
-}
diff --git a/dm/appengine/distributor/pubsub.go b/dm/appengine/distributor/pubsub.go
deleted file mode 100644
index 3f6b28b..0000000
--- a/dm/appengine/distributor/pubsub.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package distributor
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"net/http"
-	"strconv"
-	"time"
-
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/server/router"
-	"go.chromium.org/luci/server/tokens"
-	"go.chromium.org/luci/tumble"
-)
-
-const notifyTopicSuffix = "dm-distributor-notify"
-
-// PubsubReceiver is the HTTP handler that processes incoming pubsub events
-// delivered to topics prepared with TaskDescription.PrepareTopic, and routes
-// them to the appropriate distributor implementation's HandleNotification
-// method.
-//
-// It requires that a Registry be installed in c via WithRegistry.
-func PubsubReceiver(ctx *router.Context) {
-	c, rw, r := ctx.Context, ctx.Writer, ctx.Request
-	defer r.Body.Close()
-
-	type PubsubMessage struct {
-		Attributes map[string]string `json:"attributes"`
-		Data       []byte            `json:"data"`
-		MessageID  string            `json:"message_id"`
-	}
-	type PubsubPushMessage struct {
-		Message      PubsubMessage `json:"message"`
-		Subscription string        `json:"subscription"`
-	}
-	psm := &PubsubPushMessage{}
-
-	if err := json.NewDecoder(r.Body).Decode(psm); err != nil {
-		logging.WithError(err).Errorf(c, "Failed to parse pubsub message")
-		http.Error(rw, "Failed to parse pubsub message", http.StatusInternalServerError)
-		return
-	}
-
-	eid, cfgName, err := decodeAuthToken(c, psm.Message.Attributes["auth_token"])
-	if err != nil {
-		logging.WithError(err).Errorf(c, "bad auth_token")
-		// Acknowledge this message, since it'll never be valid.
-		rw.WriteHeader(http.StatusNoContent)
-		return
-	}
-
-	// remove "auth_token" from Attributes to avoid having it pass to the
-	// distributor.
-	delete(psm.Message.Attributes, "auth_token")
-
-	err = tumble.RunMutation(c, &NotifyExecution{
-		cfgName, &Notification{eid, psm.Message.Data, psm.Message.Attributes},
-	})
-	if err != nil {
-		// TODO(riannucci): distinguish between transient/non-transient failures.
-		logging.WithError(err).Errorf(c, "failed to NotifyExecution")
-		rw.WriteHeader(http.StatusInternalServerError)
-		return
-	}
-
-	rw.WriteHeader(http.StatusNoContent)
-}
-
-// pubsubAuthToken describes how to generate HMAC protected tokens used to
-// authenticate PubSub messages.
-var pubsubAuthToken = tokens.TokenKind{
-	Algo:       tokens.TokenAlgoHmacSHA256,
-	Expiration: 48 * time.Hour,
-	SecretKey:  "pubsub_auth_token",
-	Version:    1,
-}
-
-func encodeAuthToken(c context.Context, eid *dm.Execution_ID, cfgName string) (string, error) {
-	return pubsubAuthToken.Generate(c, nil, map[string]string{
-		"quest":     eid.Quest,
-		"attempt":   strconv.FormatUint(uint64(eid.Attempt), 10),
-		"execution": strconv.FormatUint(uint64(eid.Id), 10),
-		"cfgName":   cfgName,
-	}, 0)
-}
-
-func decodeAuthToken(c context.Context, authToken string) (eid *dm.Execution_ID, cfgName string, err error) {
-	items, err := pubsubAuthToken.Validate(c, authToken, nil)
-	if err != nil {
-		return
-	}
-	quest, qok := items["quest"]
-	attempt, aok := items["attempt"]
-	execution, eok := items["execution"]
-	if !qok || !aok || !eok {
-		err = fmt.Errorf("missing keys: %v", items)
-		return
-	}
-	attemptNum, err := strconv.ParseUint(attempt, 10, 32)
-	if err != nil {
-		return
-	}
-	executionNum, err := strconv.ParseUint(execution, 10, 32)
-	if err != nil {
-		return
-	}
-	eid = dm.NewExecutionID(quest, uint32(attemptNum), uint32(executionNum))
-
-	cfgName, ok := items["cfgName"]
-	if !ok {
-		err = fmt.Errorf("missing config name")
-	}
-
-	return
-}
diff --git a/dm/appengine/distributor/registry.go b/dm/appengine/distributor/registry.go
deleted file mode 100644
index 548f563..0000000
--- a/dm/appengine/distributor/registry.go
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package distributor
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"reflect"
-
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/config"
-	"go.chromium.org/luci/config/cfgclient"
-	"go.chromium.org/luci/dm/api/distributor"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/gae/service/info"
-	"go.chromium.org/luci/tumble"
-
-	"google.golang.org/protobuf/proto"
-)
-
-var regKey = "holds a DM Distributor Registry"
-
-// WithRegistry adds the registry to the Context.
-func WithRegistry(c context.Context, r Registry) context.Context {
-	if r == nil {
-		panic(errors.New("you may not use WithRegistry on a nil Registry"))
-	}
-	return context.WithValue(c, &regKey, r)
-}
-
-// GetRegistry gets the registry from the Context. This will return nil if the
-// Context does not contain a Registry.
-func GetRegistry(c context.Context) Registry {
-	ret, _ := c.Value(&regKey).(Registry)
-	return ret
-}
-
-// FinishExecutionFn is required to eliminate a circular dependency
-// between mutate <-> distributor. Essentially this just makes a new
-// mutate.FinishExecution.
-//
-// See mutate.FinishExecutionFn for the only actual implementation of this.
-type FinishExecutionFn func(c context.Context, eid *dm.Execution_ID, rslt *dm.Result) ([]tumble.Mutation, error)
-
-// Registry holds a collection of all of the available distributor types.
-type Registry interface {
-	FinishExecution(c context.Context, eid *dm.Execution_ID, rslt *dm.Result) ([]tumble.Mutation, error)
-
-	// MakeDistributor builds a distributor instance that's configured with the
-	// provided config.
-	//
-	// The configuration for this distributor are obtained from luci-config at the
-	// time an Execution is started.
-	MakeDistributor(c context.Context, cfgName string) (d D, ver string, err error)
-}
-
-// FactoryMap maps nil proto.Message instances (e.g. (*MyMessage)(nil)) to the
-// factory which knows how to turn a Message of that type into a distributor.
-type FactoryMap map[proto.Message]Factory
-
-// NewRegistry builds a new implementation of Registry configured to load
-// configuration data from luci-config.
-//
-// The mapping should hold nil-ptrs of various config protos -> respective
-// Factory. When loading from luci-config, when we see a given message type,
-// we'll construct the distributor instance using the provided Factory.
-func NewRegistry(mapping FactoryMap, fFn FinishExecutionFn) Registry {
-	ret := &registry{fFn, make(map[reflect.Type]Factory, len(mapping))}
-	add := func(p proto.Message, factory Factory) {
-		if factory == nil {
-			panic("factory is nil")
-		}
-		if p == nil {
-			panic("proto.Message is nil")
-		}
-
-		typ := reflect.TypeOf(p)
-
-		if _, ok := ret.data[typ]; ok {
-			panic(fmt.Errorf("trying to register %q twice", typ))
-		}
-		ret.data[typ] = factory
-	}
-	for p, f := range mapping {
-		add(p, f)
-	}
-	return ret
-}
-
-type registry struct {
-	finishExecutionImpl FinishExecutionFn
-	data                map[reflect.Type]Factory
-}
-
-var _ Registry = (*registry)(nil)
-
-func (r *registry) FinishExecution(c context.Context, eid *dm.Execution_ID, rslt *dm.Result) ([]tumble.Mutation, error) {
-	return r.finishExecutionImpl(c, eid, rslt)
-}
-
-func (r *registry) MakeDistributor(c context.Context, cfgName string) (d D, ver string, err error) {
-	cfg, err := loadConfig(c, cfgName)
-	if err != nil {
-		logging.Fields{"error": err, "cfg": cfgName}.Errorf(c, "Failed to load config")
-		return
-	}
-
-	ver = cfg.Version
-
-	typ := reflect.TypeOf(cfg.Content)
-
-	fn, ok := r.data[typ]
-	if !ok {
-		return nil, "", fmt.Errorf("unknown distributor type %T", cfg.Content)
-	}
-
-	d, err = fn(c, cfg)
-	return
-}
-
-// loadConfig loads the named distributor configuration from luci-config,
-// possibly using the in-memory or memcache version.
-func loadConfig(c context.Context, cfgName string) (ret *Config, err error) {
-	var (
-		distCfg distributor.Config
-		meta    config.Meta
-	)
-	if err = cfgclient.Get(c, "services/${appid}", "distributors.cfg", cfgclient.ProtoText(&distCfg), &meta); err != nil {
-		return
-	}
-
-	cfgVersion := meta.Revision
-	cfg, ok := distCfg.DistributorConfigs[cfgName]
-	if !ok {
-		err = fmt.Errorf("unknown distributor configuration: %q", cfgName)
-		return
-	}
-	if alias := cfg.GetAlias(); alias != nil {
-		cfg, ok = distCfg.DistributorConfigs[alias.OtherConfig]
-		if !ok {
-			err = fmt.Errorf("unknown distributor configuration: %q (via alias %q)", cfgName, alias.OtherConfig)
-			return
-		}
-		if cfg.GetAlias() != nil {
-			err = fmt.Errorf("too many levels of indirection for alias %q (points to alias %q)", cfgName, alias.OtherConfig)
-			return
-		}
-	}
-
-	dt := cfg.DistributorType
-	if dt == nil {
-		err = fmt.Errorf("blank or unrecognized distributor_type")
-		return
-	}
-	dVal := reflect.ValueOf(dt)
-
-	// All non-nil DistributorType's have a single field which is the actual oneof
-	// value.
-	implConfig := dVal.Elem().Field(0).Interface().(proto.Message)
-
-	ret = &Config{
-		info.DefaultVersionHostname(c),
-		cfgName,
-		cfgVersion,
-		implConfig,
-	}
-	return
-}
diff --git a/dm/appengine/distributor/swarming/v1/distributor.go b/dm/appengine/distributor/swarming/v1/distributor.go
deleted file mode 100644
index cb6fe8a..0000000
--- a/dm/appengine/distributor/swarming/v1/distributor.go
+++ /dev/null
@@ -1,379 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package swarming
-
-import (
-	"bytes"
-	"context"
-	"encoding/base64"
-	"encoding/json"
-	"fmt"
-	"net/http"
-	"time"
-
-	"google.golang.org/api/googleapi"
-	"google.golang.org/protobuf/encoding/protojson"
-	"google.golang.org/protobuf/types/known/durationpb"
-	"google.golang.org/protobuf/types/known/timestamppb"
-
-	"github.com/golang/protobuf/jsonpb"
-
-	swarm "go.chromium.org/luci/common/api/swarming/swarming/v1"
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/retry"
-	sv1 "go.chromium.org/luci/dm/api/distributor/swarming/v1"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor"
-	"go.chromium.org/luci/gae/service/info"
-	"go.chromium.org/luci/server/auth"
-)
-
-type swarmingDist struct {
-	context.Context
-
-	cfg *distributor.Config
-
-	sCfg *sv1.Config
-}
-
-var _ distributor.D = (*swarmingDist)(nil)
-
-var swarmBotLookup = map[string]dm.AbnormalFinish_Status{
-	"BOT_DIED":  dm.AbnormalFinish_CRASHED,
-	"CANCELED":  dm.AbnormalFinish_CANCELLED,
-	"EXPIRED":   dm.AbnormalFinish_EXPIRED,
-	"TIMED_OUT": dm.AbnormalFinish_TIMED_OUT,
-}
-
-func cipdPackageFromSwarm(pkg *swarm.SwarmingRpcsCipdPackage) *sv1.CipdPackage {
-	return &sv1.CipdPackage{Name: pkg.PackageName, Version: pkg.Version}
-}
-
-func cipdSpecFromSwarm(pkgs *swarm.SwarmingRpcsCipdPins) *sv1.CipdSpec {
-	ret := &sv1.CipdSpec{
-		Client: cipdPackageFromSwarm(pkgs.ClientPackage),
-		ByPath: map[string]*sv1.CipdSpec_CipdPackages{},
-	}
-	for _, pkg := range pkgs.Packages {
-		pkgs, ok := ret.ByPath[pkg.Path]
-		if !ok {
-			pkgs = &sv1.CipdSpec_CipdPackages{}
-			ret.ByPath[pkg.Path] = pkgs
-		}
-		pkgs.Pkg = append(pkgs.Pkg, cipdPackageFromSwarm(pkg))
-	}
-	return ret
-}
-
-func toSwarmMap(m map[string]string) []*swarm.SwarmingRpcsStringPair {
-	ret := make([]*swarm.SwarmingRpcsStringPair, 0, len(m))
-	for key, value := range m {
-		ret = append(ret, &swarm.SwarmingRpcsStringPair{
-			Key: key, Value: value})
-	}
-	return ret
-}
-
-func toIntSeconds(p *durationpb.Duration) int64 {
-	return int64(p.AsDuration().Seconds())
-}
-
-func httpClients(c context.Context) (anonC, authC *http.Client) {
-	rt, err := auth.GetRPCTransport(c, auth.AsSelf)
-	if err != nil {
-		// if we can't set up a transport, we're seriously hosed
-		panic(err)
-	}
-	anonTransport, err := auth.GetRPCTransport(c, auth.NoAuth)
-	if err != nil {
-		panic(err)
-	}
-	anonC = &http.Client{Transport: anonTransport}
-	authC = &http.Client{Transport: rt}
-	return
-}
-
-func newSwarmClient(c context.Context, cfg *sv1.Config) *swarm.Service {
-	_, authC := httpClients(c)
-	svc, err := swarm.New(authC)
-	if err != nil {
-		// can only happen with nil client
-		panic(err)
-	}
-	svc.BasePath = cfg.Swarming.Url + "/_ah/api/swarming/v1/"
-	return svc
-}
-
-func parseParams(desc *dm.Quest_Desc) (ret *sv1.Parameters, err error) {
-	ret = &sv1.Parameters{}
-	if err = protojson.Unmarshal([]byte(desc.DistributorParameters), ret); err != nil {
-		err = errors.Annotate(err, "unmarshalling DistributorParameters").
-			InternalReason("These paramaeters were already validated?").
-			Err()
-		return
-	}
-	if err = ret.Normalize(); err != nil {
-		err = errors.Annotate(err, "normalizing DistributorParameters").
-			InternalReason("These paramaeters were already normalized successfully once?").
-			Err()
-		return
-	}
-	return
-}
-
-func (d *swarmingDist) Run(desc *dm.Quest_Desc, auth *dm.Execution_Auth, prev *dm.JsonResult) (tok distributor.Token, _ time.Duration, err error) {
-	id := auth.Id
-
-	params, err := parseParams(desc)
-	if err != nil {
-		return
-	}
-
-	prevParsed := (*sv1.Result)(nil)
-	if prev != nil {
-		prevParsed = &sv1.Result{}
-		if err = protojson.Unmarshal([]byte(prev.Object), prevParsed); err != nil {
-			err = errors.Annotate(err, "parsing previous result").Err()
-			return
-		}
-	}
-
-	secretBytesRaw := &bytes.Buffer{}
-	marshaller := &jsonpb.Marshaler{OrigName: true}
-	if err = marshaller.Marshal(secretBytesRaw, auth); err != nil {
-		return
-	}
-	secretBytes := base64.StdEncoding.EncodeToString(secretBytesRaw.Bytes())
-
-	cipdInput := (*swarm.SwarmingRpcsCipdInput)(nil)
-	if prevParsed != nil {
-		cipdInput = prevParsed.CipdPins.ToCipdInput()
-	} else {
-		cipdInput = params.Job.Inputs.Cipd.ToCipdInput()
-	}
-
-	topic, token, err := d.cfg.PrepareTopic(d, auth.Id)
-	if err != nil {
-		err = errors.Annotate(err, "preparing topic").Err()
-		return
-	}
-
-	prefix := params.Meta.NamePrefix
-	if len(prefix) > 0 {
-		prefix += " / "
-	}
-
-	dims := make(map[string]string, len(params.Scheduling.Dimensions))
-	for k, v := range params.Scheduling.Dimensions {
-		dims[k] = v
-	}
-	if prevParsed != nil {
-		for k, v := range prevParsed.SnapshotDimensions {
-			dims[k] = v
-		}
-	}
-
-	tags := []string{
-		"requestor:DM",
-		"requestor:" + info.TrimmedAppID(d),
-		"requestor:swarming_v1",
-		fmt.Sprintf("quest:%s", id.Quest),
-		fmt.Sprintf("attempt:%s|%d", id.Quest, id.Attempt),
-		fmt.Sprintf("execution:%s|%d|%d", id.Quest, id.Attempt, id.Id),
-	}
-
-	rslt := (*swarm.SwarmingRpcsTaskRequestMetadata)(nil)
-	err = retry.Retry(d, retry.Default, func() (err error) {
-		rpcCtx, cancel := context.WithTimeout(d, 10*time.Second)
-		defer cancel()
-		rslt, err = newSwarmClient(rpcCtx, d.sCfg).Tasks.New(&swarm.SwarmingRpcsNewTaskRequest{
-			ExpirationSecs: toIntSeconds(desc.Meta.Timeouts.Start),
-			Name:           fmt.Sprintf("%s%s|%d|%d", prefix, id.Quest, id.Attempt, id.Id),
-
-			Priority: int64(params.Scheduling.Priority),
-
-			Properties: &swarm.SwarmingRpcsTaskProperties{
-				CipdInput:            cipdInput,
-				Dimensions:           toSwarmMap(dims),
-				Env:                  toSwarmMap(params.Job.Env),
-				ExecutionTimeoutSecs: toIntSeconds(desc.Meta.Timeouts.Run),
-				GracePeriodSecs:      toIntSeconds(desc.Meta.Timeouts.Stop),
-				IoTimeoutSecs:        toIntSeconds(params.Scheduling.IoTimeout),
-				SecretBytes:          secretBytes,
-			},
-
-			PubsubTopic:     topic.String(),
-			PubsubAuthToken: token,
-
-			Tags: tags,
-		}).Context(rpcCtx).Do()
-		return
-	}, retry.LogCallback(d, "swarm.Tasks.New"))
-	if err != nil {
-		err = errors.Annotate(err, "calling swarm.Tasks.New").Err()
-		return
-	}
-
-	tok = distributor.Token(rslt.TaskId)
-	return
-}
-
-func (d *swarmingDist) Cancel(q *dm.Quest_Desc, tok distributor.Token) error {
-	return retry.Retry(d, retry.Default, func() (err error) {
-		ctx, cancel := context.WithTimeout(d, 10*time.Second)
-		defer cancel()
-		cr := &swarm.SwarmingRpcsTaskCancelRequest{KillRunning: true}
-		_, err = newSwarmClient(ctx, d.sCfg).Task.Cancel(string(tok), cr).Context(ctx).Do()
-		return
-	}, retry.LogCallback(d, "swarm.Task.Cancel"))
-}
-
-func snapshotDimensions(p *sv1.Parameters, dims []*swarm.SwarmingRpcsStringListPair) map[string]string {
-	if len(p.Scheduling.SnapshotDimensions) == 0 {
-		return nil
-	}
-	allDims := map[string]string{}
-	for _, dim := range dims {
-		allDims[dim.Key] = dim.Value[len(dim.Value)-1]
-	}
-
-	ret := make(map[string]string, len(p.Scheduling.SnapshotDimensions))
-	for _, k := range p.Scheduling.SnapshotDimensions {
-		if v, ok := allDims[k]; ok {
-			ret[k] = v
-		}
-	}
-	return ret
-}
-
-func (d *swarmingDist) GetStatus(q *dm.Quest_Desc, tok distributor.Token) (*dm.Result, error) {
-	rslt := (*swarm.SwarmingRpcsTaskResult)(nil)
-
-	err := retry.Retry(d, retry.Default, func() (err error) {
-		ctx, cancel := context.WithTimeout(d, 10*time.Second)
-		defer cancel()
-		rslt, err = newSwarmClient(ctx, d.sCfg).Task.Result(string(tok)).Context(ctx).Do()
-		return
-	}, retry.LogCallback(d, fmt.Sprintf("swarm.Task.Result(%s)", tok)))
-	if err != nil {
-		if gerr := err.(*googleapi.Error); gerr != nil {
-			if gerr.Code == http.StatusNotFound {
-				return &dm.Result{
-					AbnormalFinish: &dm.AbnormalFinish{
-						Status: dm.AbnormalFinish_MISSING,
-						Reason: "swarming: notFound",
-					},
-				}, nil
-			}
-		}
-
-		return nil, err
-	}
-	ret := &dm.Result{}
-
-	switch rslt.State {
-	case "PENDING", "RUNNING":
-		return nil, nil
-
-	case "COMPLETED":
-		if rslt.InternalFailure {
-			ret.AbnormalFinish = &dm.AbnormalFinish{
-				Status: dm.AbnormalFinish_CRASHED,
-				Reason: fmt.Sprintf("swarming: COMPLETED/InternalFailure(%d)", rslt.ExitCode),
-			}
-			break
-		}
-
-		retData := &sv1.Result{
-			ExitCode: rslt.ExitCode,
-		}
-		if rslt.CipdPins != nil {
-			retData.CipdPins = cipdSpecFromSwarm(rslt.CipdPins)
-		}
-		params, err := parseParams(q)
-		if err != nil {
-			return nil, err
-		}
-		retData.SnapshotDimensions = snapshotDimensions(params, rslt.BotDimensions)
-
-		data, err := (&jsonpb.Marshaler{OrigName: true}).MarshalToString(retData)
-		if err != nil {
-			panic(err)
-		}
-
-		ret.Data = &dm.JsonResult{
-			Object: data,
-			Size:   uint32(len(data)),
-			Expiration: timestamppb.New(
-				clock.Now(d).Add(d.sCfg.Isolate.Expiration.AsDuration())),
-		}
-
-	default:
-		if bad, ok := swarmBotLookup[rslt.State]; ok {
-			ret.AbnormalFinish = &dm.AbnormalFinish{
-				Status: bad,
-				Reason: fmt.Sprintf("swarming: %s", rslt.State),
-			}
-		} else {
-			ret.AbnormalFinish = &dm.AbnormalFinish{
-				Status: dm.AbnormalFinish_RESULT_MALFORMED,
-				Reason: fmt.Sprintf("swarming: unknown state %s", rslt.State),
-			}
-		}
-	}
-
-	return ret, nil
-}
-
-func (d *swarmingDist) InfoURL(tok distributor.Token) string {
-	return fmt.Sprintf("%s/user/task/%s", d.sCfg.Swarming.Url, tok)
-}
-
-func (d *swarmingDist) HandleNotification(q *dm.Quest_Desc, notification *distributor.Notification) (*dm.Result, error) {
-	type Data struct {
-		TaskID distributor.Token `json:"task_id"`
-	}
-	dat := &Data{}
-	if err := json.Unmarshal(notification.Data, dat); err != nil {
-		logging.Fields{"payload": notification.Data}.Errorf(
-			d, "Could not unmarshal swarming payload! relying on timeout.")
-		return nil, nil
-	}
-	return d.GetStatus(q, dat.TaskID)
-}
-
-func (*swarmingDist) HandleTaskQueueTask(r *http.Request) ([]*distributor.Notification, error) {
-	return nil, nil
-}
-
-func (*swarmingDist) Validate(payload string) error {
-	msg := &sv1.Parameters{}
-	if err := protojson.Unmarshal([]byte(payload), msg); err != nil {
-		return errors.Annotate(err, "unmarshal").InternalReason("payload(%v)", payload).Err()
-	}
-	return errors.Annotate(msg.Normalize(), "normalize").InternalReason("payload(%v)", payload).Err()
-}
-
-func factory(c context.Context, cfg *distributor.Config) (distributor.D, error) {
-	return &swarmingDist{c, cfg, cfg.Content.(*sv1.Config)}, nil
-}
-
-// AddFactory adds this distributor implementation into the distributor
-// Registry.
-func AddFactory(m distributor.FactoryMap) {
-	m[(*sv1.Config)(nil)] = factory
-}
diff --git a/dm/appengine/distributor/test_registry.go b/dm/appengine/distributor/test_registry.go
deleted file mode 100644
index 5cfe2c0..0000000
--- a/dm/appengine/distributor/test_registry.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package distributor
-
-import (
-	"context"
-	"fmt"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/tumble"
-)
-
-type TestFactoryFn func(context.Context, *Config) D
-
-type TestFactoryMap map[string]TestFactoryFn
-
-type testRegistry struct {
-	finishExecutionImpl FinishExecutionFn
-	data                TestFactoryMap
-}
-
-var _ Registry = (*testRegistry)(nil)
-
-// NewTestingRegistry returns a new testing registry.
-//
-// The mocks dictionary maps from cfgName to a mock implementation of the
-// distributor.
-func NewTestingRegistry(mocks TestFactoryMap, fFn FinishExecutionFn) Registry {
-	return &testRegistry{fFn, mocks}
-}
-
-func (t *testRegistry) FinishExecution(c context.Context, eid *dm.Execution_ID, rslt *dm.Result) ([]tumble.Mutation, error) {
-	return t.finishExecutionImpl(c, eid, rslt)
-}
-
-func (t *testRegistry) MakeDistributor(c context.Context, cfgName string) (D, string, error) {
-	ret, ok := t.data[cfgName]
-	if !ok {
-		return nil, "", fmt.Errorf("unknown distributor configuration: %q", cfgName)
-	}
-	return ret(c, &Config{
-		DMHost:  "test-dm-host.example.com",
-		Version: "test-version",
-		Name:    cfgName,
-	}), "testing", nil
-}
diff --git a/dm/appengine/distributor/tq_handler.go b/dm/appengine/distributor/tq_handler.go
deleted file mode 100644
index 4a724a8..0000000
--- a/dm/appengine/distributor/tq_handler.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package distributor
-
-import (
-	"net/http"
-	"net/url"
-	"strings"
-
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/server/router"
-	"go.chromium.org/luci/tumble"
-)
-
-const handlerPattern = "/tq/distributor/:cfgName"
-
-func handlerPath(cfgName string) string {
-	return strings.Replace(handlerPattern, ":cfgName", url.QueryEscape(cfgName), 1)
-}
-
-// TaskQueueHandler is the http handler that routes taskqueue tasks made with
-// Config.EnqueueTask to a distributor's HandleTaskQueueTask method.
-//
-// This requires that ctx.Context already have a Registry installed via the
-// WithRegistry method.
-func TaskQueueHandler(ctx *router.Context) {
-	c, rw, r, p := ctx.Context, ctx.Writer, ctx.Request, ctx.Params
-	defer r.Body.Close()
-
-	cfgName := p.ByName("cfgName")
-	dist, _, err := GetRegistry(c).MakeDistributor(c, cfgName)
-	if err != nil {
-		logging.Fields{"error": err, "cfg": cfgName}.Errorf(c, "Failed to make distributor")
-		http.Error(rw, "bad distributor", http.StatusBadRequest)
-		return
-	}
-	notifications, err := dist.HandleTaskQueueTask(r)
-	if err != nil {
-		logging.Fields{"error": err, "cfg": cfgName}.Errorf(c, "Failed to handle taskqueue task")
-		http.Error(rw, "failure to execute handler", http.StatusInternalServerError)
-		return
-	}
-	if len(notifications) > 0 {
-		muts := make([]tumble.Mutation, 0, len(notifications))
-		for _, notify := range notifications {
-			if notify != nil {
-				muts = append(muts, &NotifyExecution{cfgName, notify})
-			}
-		}
-		err = tumble.AddToJournal(c, muts...)
-		if err != nil {
-			logging.Fields{"error": err, "cfg": cfgName}.Errorf(c, "Failed to handle notifications")
-			http.Error(rw, "failure to handle notifications", http.StatusInternalServerError)
-			return
-		}
-	}
-	rw.WriteHeader(http.StatusOK)
-}
diff --git a/dm/appengine/doc.go b/dm/appengine/doc.go
deleted file mode 100644
index a579459..0000000
--- a/dm/appengine/doc.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package appengine provides the appengine service implementation for DM.
-//
-// This contains the following subpackages:
-//   model - These objects are the datastore model objects for DM.
-//   mutate - Tumble mutations for DM, a.k.a. DM's state machine. Each mutation
-//     represents a single node in DM's state machine.
-//   deps - The dependency management pRPC service.
-//   frontend - The deployable appengine app. For Technical Reasons (tm), almost
-//     zero code lives here, it just calls through to code in deps.
-//   distributor - Definition of the Distributor interface, and implementations
-//     (such as swarming_v1).
-//
-// For more information on DM itself, check out https://go.chromium.org/luci/wiki/Design-Documents
-package appengine
diff --git a/dm/appengine/frontend/.gcloudignore b/dm/appengine/frontend/.gcloudignore
deleted file mode 100644
index cd43ed5..0000000
--- a/dm/appengine/frontend/.gcloudignore
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file specifies files that are *not* uploaded to Google Cloud Platform
-# using gcloud. It follows the same syntax as .gitignore, with the addition of
-# "#!include" directives (which insert the entries of the given .gitignore-style
-# file at that point).
-#
-# For more information, run:
-#   $ gcloud topic gcloudignore
-
-.gcloudignore
-.gitignore
diff --git a/dm/appengine/frontend/app.yaml b/dm/appengine/frontend/app.yaml
deleted file mode 100644
index 0833869..0000000
--- a/dm/appengine/frontend/app.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-service: default
-runtime: go111
-
-handlers:
-- url: /_ah/push-handlers/.*
-  script: auto
-  secure: always
-  login: admin
-- url: /.*
-  script: auto
-  secure: always
diff --git a/dm/appengine/frontend/cron.yaml b/dm/appengine/frontend/cron.yaml
deleted file mode 100644
index e5851e3..0000000
--- a/dm/appengine/frontend/cron.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-cron:
-- description: tumble.Cron invocation
-  url: /internal/tumble/fire_all_tasks
-  schedule: every 1 minutes
diff --git a/dm/appengine/frontend/doc.go b/dm/appengine/frontend/doc.go
deleted file mode 100644
index f72ca0b..0000000
--- a/dm/appengine/frontend/doc.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Binary frontend is DM's Google AppEngine application stub.
-//
-// Setup
-//
-// * Create a pubsub topic "projects/$APPID/topics/dm-distributor-notify"
-// * Create a pubsub Push subscription:
-//     Topic: "projects/$APPID/topics/dm-distributor-notify"
-//     Name: "projects/$APPID/subscriptions/dm-distributor-notify"
-//     Push: "https://$APPID.$APPDOMAIN/_ah/push-handlers/dm-distributor-notify"
-package main
diff --git a/dm/appengine/frontend/index.yaml b/dm/appengine/frontend/index.yaml
deleted file mode 100644
index 66a9bc9..0000000
--- a/dm/appengine/frontend/index.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2016 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-
-indexes:
-
-# This index supports the tumble installation.
-- kind: tumble.Mutation
-  properties:
-  - name: ExpandedShard
-  - name: TargetRoot
-
-# This index supports the tumble delayed mutations.
-- kind: tumble.Mutation
-  properties:
-  - name: TargetRoot
-  - name: ProcessAfter
-
-# AUTOGENERATED
diff --git a/dm/appengine/frontend/main.go b/dm/appengine/frontend/main.go
deleted file mode 100644
index c633d39..0000000
--- a/dm/appengine/frontend/main.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"net/http"
-
-	"google.golang.org/appengine"
-
-	"go.chromium.org/luci/appengine/gaemiddleware/standard"
-	"go.chromium.org/luci/dm/appengine/deps"
-	"go.chromium.org/luci/dm/appengine/distributor"
-	"go.chromium.org/luci/dm/appengine/distributor/jobsim"
-	"go.chromium.org/luci/dm/appengine/distributor/swarming/v1"
-	"go.chromium.org/luci/dm/appengine/mutate"
-	"go.chromium.org/luci/grpc/discovery"
-	"go.chromium.org/luci/grpc/prpc"
-	"go.chromium.org/luci/server/router"
-	"go.chromium.org/luci/tumble"
-)
-
-func main() {
-	tmb := tumble.Service{}
-
-	distributors := distributor.FactoryMap{}
-	jobsim.AddFactory(distributors)
-	swarming.AddFactory(distributors)
-
-	reg := distributor.NewRegistry(distributors, mutate.FinishExecutionFn)
-
-	basemw := standard.Base().Extend(func(c *router.Context, next router.Handler) {
-		c.Context = distributor.WithRegistry(c.Context, reg)
-		next(c)
-	})
-
-	r := router.New()
-
-	svr := prpc.Server{}
-	deps.RegisterDepsServer(&svr)
-	discovery.Enable(&svr)
-
-	distributor.InstallHandlers(r, basemw)
-	svr.InstallHandlers(r, basemw)
-	tmb.InstallHandlers(r, basemw)
-	standard.InstallHandlers(r)
-
-	http.Handle("/", r)
-	appengine.Main()
-}
diff --git a/dm/appengine/frontend/queue.yaml b/dm/appengine/frontend/queue.yaml
deleted file mode 100644
index 6596303..0000000
--- a/dm/appengine/frontend/queue.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-queue:
-- name: tumble
-  rate: 32/s
-  bucket_size: 32
-  retry_parameters:
-    task_age_limit: 2m
-    min_backoff_seconds: 2
-    max_backoff_seconds: 6
-    max_doublings: 7  # tops out at 2**(6 - 1) * 2 == 128 sec
diff --git a/dm/appengine/integration_tests/.gitignore b/dm/appengine/integration_tests/.gitignore
deleted file mode 100644
index 57c4804..0000000
--- a/dm/appengine/integration_tests/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# Integration tests prepare consistent config directories in .devcfg_versions
-# and symlink them to ../devcfg (where appengine/gaeconfig component reads them
-# from when it runs on dev server).
-.devcfg_versions
diff --git a/dm/appengine/integration_tests/01_test_single_jobsim.sh b/dm/appengine/integration_tests/01_test_single_jobsim.sh
deleted file mode 100755
index f1abcb0..0000000
--- a/dm/appengine/integration_tests/01_test_single_jobsim.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2016 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-
-. ./integration_test.sh
-
-write_config services/luci-dm/distributors.cfg <<EOF
-distributor_configs: {
-  key: "jobsim"
-  value: { jobsim: {} }
-}
-EOF
-
-quest_id=$(add_attempts jobsim '{"return_stage": {"retval": 178}}' 1)
-log $quest_id
-
-walk_attempt "$quest_id" 1
diff --git a/dm/appengine/integration_tests/02_diamond_jobsim.sh b/dm/appengine/integration_tests/02_diamond_jobsim.sh
deleted file mode 100755
index df2dca6..0000000
--- a/dm/appengine/integration_tests/02_diamond_jobsim.sh
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2016 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-
-. ./integration_test.sh
-
-write_config services/luci-dm/distributors.cfg <<EOF
-distributor_configs: {
-  key: "jobsim"
-  value: { jobsim: {} }
-}
-EOF
-
-read -r -d '' job_text <<EOJ
-{
-  "name": "hello",
-  "stages": [
-    {
-      "deps": {"deps": [{
-        "shards": 6,
-        "attempts": {"items": [{"single": 1}]},
-        "mix_seed": true,
-        "phrase": {
-          "name": "compile",
-          "stages": [
-            {
-              "deps": {"deps": [{
-                "shards": 6,
-                "attempts": {"items": [{"single": 1}]},
-                "phrase": {
-                  "name": "thingy",
-                  "stages": [
-                    {
-                      "deps": {"deps": [{
-                        "attempts": {"items": [{"single": 1}]},
-                        "phrase": {
-                          "name": "nerp",
-                          "stages": [
-                            {
-                              "deps": {"deps": [{
-                                "attempts": {"items": [{"single": 1}]},
-                                "phrase": {
-                                  "seed": 1,
-                                  "name": "isolate_source",
-                                  "return_stage": {"retval": 1}
-                                }
-                              }]}
-                            }
-                          ],
-                          "return_stage": {"retval": 1}
-                        }
-                      }]}
-                    }
-                  ],
-                  "return_stage": {"retval": 1}
-                }
-              }]}
-            }
-          ],
-          "return_stage": {"retval": 1}
-        }
-      }]}
-    }
-  ]
-}
-EOJ
-
-quest_id=$(add_attempts jobsim "$job_text" 1)
-log $quest_id
-
-walk_attempt "$quest_id" 1
diff --git a/dm/appengine/integration_tests/integration_test.sh b/dm/appengine/integration_tests/integration_test.sh
deleted file mode 100755
index 5dd7dbd..0000000
--- a/dm/appengine/integration_tests/integration_test.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2016 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-
-cd "${0%/*}"
-
-: ${HOST:=:8080}
-: ${VERBOSE:=1}
-CFGVERS=1
-
-DEVCFG_SYMLINK=$(dirname $PWD)/devcfg
-DEVCFG_VERSIONS_DIR="$PWD/.devcfg_versions"
-
-echo Using host: $HOST
-
-_new_cfg_vers() {
-  local oldVers=$CFGVERS
-  CFGVERS=$(( $CFGVERS + 1 ))
-  cp -a $DEVCFG_VERSIONS_DIR/$oldVers $DEVCFG_VERSIONS_DIR/$CFGVERS
-}
-
-_link_current_cfg() {
-  rm -f $DEVCFG_SYMLINK
-  ln -s $DEVCFG_VERSIONS_DIR/$CFGVERS $DEVCFG_SYMLINK
-}
-
-if [[ $1 == "remote" ]];
-then
-  echo "Non-local execution not currently supported"
-  exit 1
-else
-  echo "Doing local test"
-  rm -rf $DEVCFG_VERSIONS_DIR
-  rm -f $DEVCFG_SYMLINK
-  mkdir -p $DEVCFG_VERSIONS_DIR/$CFGVERS
-  _link_current_cfg
-fi
-
-log() {
-  echo $@ > /dev/stderr
-}
-
-write_config() {
-  local outFile=$1
-  _new_cfg_vers
-  log "Writing config v$CFGVERS to: $outFile"
-  mkdir -p $DEVCFG_VERSIONS_DIR/$CFGVERS/`dirname $outFile`
-  cat > $DEVCFG_VERSIONS_DIR/$CFGVERS/$outFile
-  _link_current_cfg
-}
-
-call() {
-  local method=$1
-  shift
-  if [[ $VERBOSE == 1 ]]; then
-    log "RPC[$HOST]" "$method($@)"
-  fi
-  rpc call $HOST dm.Deps.$method "$@"
-}
-
-add_attempts() {
-  local cfgName=$1
-  local payload=$2
-  shift 2
-  log "Adding quest: $@"
-  local args=(
-    -quest.json_payload "$payload"
-    -quest.distributor_config_name "$cfgName"
-  )
-  id=$(dmtool hash -json_payload "$payload" -distributor_config_name "$cfgName")
-  for attempt in $@; do
-    args+=("-attempts.to.$id.nums" $attempt)
-  done
-
-  call EnsureGraphData "${args[@]}" > /dev/stderr
-  echo $id
-}
-
-walk_attempt() {
-  local questID=$1
-  local attemptID=$2
-
-  call WalkGraph -query.attempt_list.to.$questID.nums $attemptID \
-    -limit.max_depth 100 -include.all
-}
diff --git a/dm/appengine/model/attempt.go b/dm/appengine/model/attempt.go
deleted file mode 100644
index a45a294..0000000
--- a/dm/appengine/model/attempt.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"fmt"
-	"time"
-
-	"google.golang.org/protobuf/types/known/timestamppb"
-
-	"go.chromium.org/luci/common/clock"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	bf "go.chromium.org/luci/tumble/bitfield"
-)
-
-// AttemptRetryState indicates the current state of the Attempt's retry
-// counters.
-type AttemptRetryState struct {
-	Failed   uint32
-	Expired  uint32
-	TimedOut uint32
-	Crashed  uint32
-}
-
-// Reset resets all of the AttemptRetryState counters.
-func (a *AttemptRetryState) Reset() {
-	*a = AttemptRetryState{}
-}
-
-// Attempt is the datastore model for a DM Attempt. It has no parent key, but
-// it may have the following children entities:
-//   * FwdDep
-//   * AttemptResult
-//
-// Additionally, every Attempt has an associated BackDepGroup whose ID equals
-// the ID of this Attempt.
-type Attempt struct {
-	ID dm.Attempt_ID `gae:"$id"`
-
-	Created  time.Time
-	Modified time.Time
-
-	State      dm.Attempt_State
-	RetryState AttemptRetryState
-
-	// IsAbnormal is true iff State==ABNORMAL_FINISHED, used for walk_graph.
-	IsAbnormal bool
-
-	// A lazily-updated boolean to reflect that this Attempt is expired for
-	// queries.
-	IsExpired bool
-
-	// Contains either data (State==FINISHED) or abnormal_finish (State==ABNORMAL_FINISHED)
-	//
-	// Does not contain the `data.object` field (which is in the AttemptResult,1 object)
-	Result dm.Result `gae:",noindex"`
-
-	// TODO(iannucci): Use CurExecution as a 'deps block version'
-	// then we can have an 'ANY' directive which executes the attempt as soon
-	// as any of the dependencies are ready. If it adds more deps in ANY mode,
-	// the bitmaps get /extended/, and new deps bit indices are added to the
-	// existing max.
-	// If it adds more deps in ALL mode, it just converts from ANY -> ALL mode
-	// and follows the current behavior.
-
-	// CurExecution is the maximum Execution ID for this Attempt so far. Execution
-	// IDs are contiguous from [1, CurExecution]. If the State is not currently
-	// Executing, then CurExecution represents the execution that JUST finished
-	// (or 0 if no Executions have been made yet).
-	CurExecution uint32
-
-	// LastSuccessfulExecution is the execution ID of the last successful
-	// execution, or 0 if no such execution occured yet.
-	LastSuccessfulExecution uint32
-
-	// DepMap is valid only while Attempt is in a State of EXECUTING or WAITING.
-	//
-	// The size of this field is inspected to deteremine what the next state after
-	// EXECUTING is. If the size == 0, it means the Attempt should move to the
-	// FINISHED state. Otherwise it means that the Attempt should move to the
-	// WAITING state.
-	//
-	// A bit field value of 0 means that the dep is currently waiting, and a bit
-	// value of 1 means that the coresponding dep is satisfined. The Attempt can
-	// be unblocked from WAITING back to SCHEDULING when all bits are set to 1.
-	DepMap bf.BitField `gae:",noindex" json:"-"`
-}
-
-// MakeAttempt is a convenience function to create a new Attempt model in
-// the NeedsExecution state.
-func MakeAttempt(c context.Context, aid *dm.Attempt_ID) *Attempt {
-	now := clock.Now(c).UTC()
-	return &Attempt{
-		ID:       *aid,
-		Created:  now,
-		Modified: now,
-	}
-}
-
-// ModifyState changes the current state of this Attempt and updates its
-// Modified timestamp.
-func (a *Attempt) ModifyState(c context.Context, newState dm.Attempt_State) error {
-	if a.State == newState {
-		return nil
-	}
-	if err := a.State.Evolve(newState); err != nil {
-		return err
-	}
-	now := clock.Now(c).UTC()
-	if now.After(a.Modified) {
-		a.Modified = now
-	} else {
-		// Microsecond is the smallest granularity that datastore can store
-		// timestamps, so use that to disambiguate: the goal here is that any
-		// modification always increments the modified time, and never decrements
-		// it.
-		a.Modified = a.Modified.Add(time.Microsecond)
-	}
-	return nil
-}
-
-// ToProto returns a dm proto version of this Attempt.
-func (a *Attempt) ToProto(withData bool) *dm.Attempt {
-	ret := dm.Attempt{Id: &a.ID}
-	if withData {
-		ret.Data = a.DataProto()
-	}
-	return &ret
-}
-
-// DataProto returns an Attempt.Data message for this Attempt.
-func (a *Attempt) DataProto() (ret *dm.Attempt_Data) {
-	switch a.State {
-	case dm.Attempt_SCHEDULING:
-		ret = dm.NewAttemptScheduling().Data
-	case dm.Attempt_EXECUTING:
-		ret = dm.NewAttemptExecuting(a.CurExecution).Data
-	case dm.Attempt_WAITING:
-		ret = dm.NewAttemptWaiting(a.DepMap.Size() - a.DepMap.CountSet()).Data
-	case dm.Attempt_FINISHED:
-		ret = dm.NewAttemptFinished(a.Result.Data).Data
-	case dm.Attempt_ABNORMAL_FINISHED:
-		ret = dm.NewAttemptAbnormalFinish(a.Result.AbnormalFinish).Data
-	default:
-		panic(fmt.Errorf("unknown Attempt_State: %s", a.State))
-	}
-	ret.Created = timestamppb.New(a.Created)
-	ret.Modified = timestamppb.New(a.Modified)
-	ret.NumExecutions = a.CurExecution
-	return ret
-}
diff --git a/dm/appengine/model/attempt_result.go b/dm/appengine/model/attempt_result.go
deleted file mode 100644
index 25c24bb..0000000
--- a/dm/appengine/model/attempt_result.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/gae/service/datastore"
-)
-
-// AttemptResult holds the raw, compressed json blob returned from the
-// execution.
-type AttemptResult struct {
-	_id     int64          `gae:"$id,1"`
-	Attempt *datastore.Key `gae:"$parent"`
-
-	// The sizes and expirations are denormalized across Attempt and
-	// AttemptResult.
-	Data dm.JsonResult `gae:",noindex"`
-}
diff --git a/dm/appengine/model/attempt_test.go b/dm/appengine/model/attempt_test.go
deleted file mode 100644
index 7df32d4..0000000
--- a/dm/appengine/model/attempt_test.go
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"math"
-	"testing"
-	"time"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"google.golang.org/protobuf/types/known/timestamppb"
-
-	"go.chromium.org/luci/common/clock/testclock"
-	. "go.chromium.org/luci/common/testing/assertions"
-	"go.chromium.org/luci/tumble/bitfield"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-func TestAttempt(t *testing.T) {
-	t.Parallel()
-
-	Convey("Attempt", t, func() {
-		c := context.Background()
-		c, clk := testclock.UseTime(c, testclock.TestTimeUTC)
-
-		Convey("ModifyState", func() {
-			a := MakeAttempt(c, dm.NewAttemptID("quest", 5))
-			So(a.State, ShouldEqual, dm.Attempt_SCHEDULING)
-			So(a.ModifyState(c, dm.Attempt_FINISHED), ShouldErrLike, "invalid state transition")
-			So(a.Modified, ShouldResemble, testclock.TestTimeUTC)
-
-			clk.Add(time.Second)
-
-			So(a.ModifyState(c, dm.Attempt_EXECUTING), ShouldBeNil)
-			So(a.State, ShouldEqual, dm.Attempt_EXECUTING)
-			So(a.Modified, ShouldResemble, clk.Now())
-
-			So(a.ModifyState(c, dm.Attempt_WAITING), ShouldBeNil)
-			So(a.ModifyState(c, dm.Attempt_WAITING), ShouldBeNil)
-			So(a.ModifyState(c, dm.Attempt_SCHEDULING), ShouldBeNil)
-			So(a.ModifyState(c, dm.Attempt_EXECUTING), ShouldBeNil)
-			So(a.ModifyState(c, dm.Attempt_FINISHED), ShouldBeNil)
-
-			So(a.ModifyState(c, dm.Attempt_SCHEDULING), ShouldErrLike, "invalid")
-			So(a.State, ShouldEqual, dm.Attempt_FINISHED)
-		})
-
-		Convey("ToProto", func() {
-			Convey("NeedsExecution", func() {
-				a := MakeAttempt(c, dm.NewAttemptID("quest", 10))
-
-				atmpt := dm.NewAttemptScheduling()
-				atmpt.Id = dm.NewAttemptID("quest", 10)
-				atmpt.Data.Created = timestamppb.New(testclock.TestTimeUTC)
-				atmpt.Data.Modified = timestamppb.New(testclock.TestTimeUTC)
-
-				So(a.ToProto(true), ShouldResemble, atmpt)
-			})
-
-			Convey("Executing", func() {
-				a := MakeAttempt(c, dm.NewAttemptID("quest", 10))
-				clk.Add(10 * time.Second)
-				a.CurExecution = 1
-				So(a.ModifyState(c, dm.Attempt_EXECUTING), ShouldBeNil)
-
-				So(a.ToProto(true), ShouldResemble, &dm.Attempt{
-					Id: &dm.Attempt_ID{Quest: "quest", Id: 10},
-					Data: &dm.Attempt_Data{
-						Created:       timestamppb.New(testclock.TestTimeUTC),
-						Modified:      timestamppb.New(clk.Now()),
-						NumExecutions: 1,
-						AttemptType: &dm.Attempt_Data_Executing_{Executing: &dm.Attempt_Data_Executing{
-							CurExecutionId: 1}}},
-				})
-			})
-
-			Convey("Waiting", func() {
-				a := MakeAttempt(c, dm.NewAttemptID("quest", 10))
-				clk.Add(10 * time.Second)
-				a.CurExecution = 1
-				So(a.ModifyState(c, dm.Attempt_EXECUTING), ShouldBeNil)
-				clk.Add(10 * time.Second)
-				So(a.ModifyState(c, dm.Attempt_WAITING), ShouldBeNil)
-				a.DepMap = bitfield.Make(4)
-				a.DepMap.Set(2)
-
-				atmpt := dm.NewAttemptWaiting(3)
-				atmpt.Id = dm.NewAttemptID("quest", 10)
-				atmpt.Data.Created = timestamppb.New(testclock.TestTimeUTC)
-				atmpt.Data.Modified = timestamppb.New(clk.Now())
-				atmpt.Data.NumExecutions = 1
-
-				So(a.ToProto(true), ShouldResemble, atmpt)
-			})
-
-			Convey("Finished", func() {
-				a := MakeAttempt(c, dm.NewAttemptID("quest", 10))
-				a.State = dm.Attempt_FINISHED
-				a.CurExecution = math.MaxUint32
-				a.DepMap = bitfield.Make(20)
-				a.Result.Data = dm.NewJsonResult("", testclock.TestTimeUTC.Add(10*time.Second))
-
-				a.DepMap.Set(1)
-				a.DepMap.Set(5)
-				a.DepMap.Set(7)
-
-				So(a.ToProto(true), ShouldResemble, &dm.Attempt{
-					Id: &dm.Attempt_ID{Quest: "quest", Id: 10},
-					Data: &dm.Attempt_Data{
-						Created:       timestamppb.New(testclock.TestTimeUTC),
-						Modified:      timestamppb.New(testclock.TestTimeUTC),
-						NumExecutions: math.MaxUint32,
-						AttemptType: &dm.Attempt_Data_Finished_{Finished: &dm.Attempt_Data_Finished{
-							Data: &dm.JsonResult{
-								Expiration: timestamppb.New(testclock.TestTimeUTC.Add(10 * time.Second))}}},
-					},
-				})
-			})
-		})
-	})
-}
diff --git a/dm/appengine/model/backdep.go b/dm/appengine/model/backdep.go
deleted file mode 100644
index 8135b3f..0000000
--- a/dm/appengine/model/backdep.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"go.chromium.org/luci/gae/service/datastore"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-)
-
-// BackDepGroup describes a group of reverse dependencies ('depended-by')
-// between Attempts. Its ID is the same as the id of the Attempt that's being
-// depended-on by other attempts, and it serves as the parent entity for the
-// BackDep model. So:
-//
-//   Attempt(OTHER_QUEST|2)
-//     FwdDep(QUEST|1)
-//
-//   Attempt(QUEST|1)
-//
-//   BackDepGroup(QUEST|1)
-//     BackDep(OTHER_QUEST|2)
-//
-// Represents the OTHER_QUEST|2 depending on QUEST|1.
-type BackDepGroup struct {
-	// Dependee is the "<AttemptID>" that the deps in this group point
-	// back FROM.
-	Dependee dm.Attempt_ID `gae:"$id"`
-
-	// This is a denormalized version of Attempt.State, used to allow
-	// transactional additions to the BackDepGroup to stay within this Entity
-	// Group when adding new back deps.
-	AttemptFinished bool
-}
-
-// BackDep represents a single backwards dependency. Its ID is the same as the
-// Attempt that's depending on this one. See BackDepGroup for more context.
-type BackDep struct {
-	// The attempt id of the attempt that's depending on this dependee.
-	Depender dm.Attempt_ID `gae:"$id"`
-
-	// The BackdepGroup for the attempt that is being depended on.
-	DependeeGroup *datastore.Key `gae:"$parent"`
-
-	// Propagated is true if the BackDepGroup has AttemptFinished, and this
-	// BackDep has been processed by the mutate.RecordCompletion tumble
-	// mutation. So if with two attempts A and B, A depends on B, the
-	// BackDep{DependeeGroup: B, Depender: A} has Propagated as true when B is
-	// finished, and a tumble Mutation has been launched to inform A of that fact.
-	Propagated bool
-}
-
-// Edge produces a fwdedge object which points from the depending attempt to
-// the depended-on attempt.
-func (b *BackDep) Edge() *FwdEdge {
-	ret := &FwdEdge{From: &b.Depender, To: &dm.Attempt_ID{}}
-	if err := ret.To.SetDMEncoded(b.DependeeGroup.StringID()); err != nil {
-		panic(err)
-	}
-	return ret
-}
diff --git a/dm/appengine/model/doc.go b/dm/appengine/model/doc.go
deleted file mode 100644
index 23a20ec..0000000
--- a/dm/appengine/model/doc.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package model contains all of DM's datastore models.
-package model
diff --git a/dm/appengine/model/edge.go b/dm/appengine/model/edge.go
deleted file mode 100644
index bb47f73..0000000
--- a/dm/appengine/model/edge.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	ds "go.chromium.org/luci/gae/service/datastore"
-)
-
-// FwdEdge represents a forward-dependency from one attempt to another. The
-// From attempt will block until the To attempt completes.
-type FwdEdge struct {
-	From *dm.Attempt_ID
-	To   *dm.Attempt_ID
-}
-
-// Fwd returns the Attempt (From) and FwdDep (To) models that this FwdEdge
-// represents.
-func (e *FwdEdge) Fwd(c context.Context) (*Attempt, *FwdDep) {
-	atmpt := &Attempt{ID: *e.From}
-	return atmpt, &FwdDep{
-		Depender: ds.KeyForObj(c, atmpt),
-		Dependee: *e.To,
-	}
-}
-
-// Back returns the BackDepGroup (To) and the BackDep (From) models that
-// represent the reverse dependency for this FwdEdge.
-func (e *FwdEdge) Back(c context.Context) (*BackDepGroup, *BackDep) {
-	bdg := &BackDepGroup{Dependee: *e.To}
-	return bdg, &BackDep{
-		DependeeGroup: ds.KeyForObj(c, bdg),
-		Depender:      *e.From,
-	}
-}
diff --git a/dm/appengine/model/edge_test.go b/dm/appengine/model/edge_test.go
deleted file mode 100644
index 0034791..0000000
--- a/dm/appengine/model/edge_test.go
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-)
-
-func TestBackdepEdge(t *testing.T) {
-	t.Parallel()
-
-	Convey("BackDep.Edge", t, func() {
-		bd := &BackDep{
-			*dm.NewAttemptID("depender", 5),
-			ds.MkKeyContext("aid", "ns").MakeKey("BackDepGroup", "quest|fffffffe"),
-			true,
-		}
-		So(bd.Edge(), ShouldResemble, &FwdEdge{
-			dm.NewAttemptID("depender", 5),
-			dm.NewAttemptID("quest", 1),
-		})
-	})
-}
-
-func TestFwdDepEdge(t *testing.T) {
-	t.Parallel()
-
-	Convey("FwdDep.Edge", t, func() {
-		bd := &FwdDep{
-			Dependee: *dm.NewAttemptID("quest", 1),
-			Depender: ds.MkKeyContext("aid", "ns").MakeKey("Attempt", "depender|fffffffa"),
-		}
-		So(bd.Edge(), ShouldResemble, &FwdEdge{
-			dm.NewAttemptID("depender", 5),
-			dm.NewAttemptID("quest", 1),
-		})
-	})
-}
-
-func TestFwdEdge(t *testing.T) {
-	t.Parallel()
-
-	Convey("FwdEdge", t, func() {
-		c := memory.Use(context.Background())
-		e := &FwdEdge{
-			dm.NewAttemptID("from", 1),
-			dm.NewAttemptID("to", 1),
-		}
-
-		Convey("Fwd", func() {
-			atmpt, fwddep := e.Fwd(c)
-			So(atmpt.ID.Quest, ShouldEqual, "from")
-			So(atmpt.ID.Id, ShouldEqual, 1)
-			So(fwddep.Dependee.Quest, ShouldEqual, "to")
-			So(fwddep.Dependee.Id, ShouldEqual, 1)
-			So(fwddep.Depender.String(), ShouldEqual, `dev~app::/Attempt,"from|fffffffe"`)
-		})
-
-		Convey("Back", func() {
-			bdg, bdep := e.Back(c)
-			So(bdg.Dependee.Quest, ShouldEqual, "to")
-			So(bdg.Dependee.Id, ShouldEqual, 1)
-			So(bdep.Depender.Quest, ShouldEqual, "from")
-			So(bdep.Depender.Id, ShouldEqual, 1)
-			So(bdep.DependeeGroup.String(), ShouldEqual, `dev~app::/BackDepGroup,"to|fffffffe"`)
-		})
-
-	})
-}
-
-func TestFwdDepsFromList(t *testing.T) {
-	t.Parallel()
-
-	Convey("FwdDepsFromList", t, func() {
-		c := memory.Use(context.Background())
-		list := &dm.AttemptList{To: map[string]*dm.AttemptList_Nums{
-			"a": {Nums: []uint32{1}},
-			"b": {Nums: []uint32{1, 2}},
-			"c": {Nums: []uint32{1}},
-		}}
-		base := dm.NewAttemptID("quest", 1)
-
-		kctx := ds.GetKeyContext(c)
-
-		root := kctx.MakeKey("Attempt", "quest|fffffffe")
-
-		So(FwdDepsFromList(c, base, list), ShouldResemble, []*FwdDep{
-			{Depender: root, Dependee: *dm.NewAttemptID("a", 1), BitIndex: 0},
-			{Depender: root, Dependee: *dm.NewAttemptID("b", 1), BitIndex: 1},
-			{Depender: root, Dependee: *dm.NewAttemptID("b", 2), BitIndex: 2},
-			{Depender: root, Dependee: *dm.NewAttemptID("c", 1), BitIndex: 3},
-		})
-		So(FwdDepKeysFromList(c, base, list), ShouldResemble, []*ds.Key{
-			kctx.MakeKey("Attempt", "quest|fffffffe", "FwdDep", "a|fffffffe"),
-			kctx.MakeKey("Attempt", "quest|fffffffe", "FwdDep", "b|fffffffe"),
-			kctx.MakeKey("Attempt", "quest|fffffffe", "FwdDep", "b|fffffffd"),
-			kctx.MakeKey("Attempt", "quest|fffffffe", "FwdDep", "c|fffffffe"),
-		})
-	})
-
-}
diff --git a/dm/appengine/model/execution.go b/dm/appengine/model/execution.go
deleted file mode 100644
index abc38a3..0000000
--- a/dm/appengine/model/execution.go
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"crypto/subtle"
-	"encoding/hex"
-	"errors"
-	"fmt"
-	"math"
-	"time"
-
-	"google.golang.org/grpc/codes"
-	"google.golang.org/protobuf/types/known/timestamppb"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/data/rand/cryptorand"
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/grpc/grpcutil"
-)
-
-const ek = logging.ErrorKey
-
-type invertedHexUint32 uint32
-
-const invertedHexUint32RenderFmt = "%08x"
-
-var _ ds.PropertyConverter = (*invertedHexUint32)(nil)
-
-func (i *invertedHexUint32) ToProperty() (ret ds.Property, err error) {
-	err = ret.SetValue(fmt.Sprintf(
-		invertedHexUint32RenderFmt, (*i)^math.MaxUint32), ds.NoIndex)
-	return
-}
-
-func (i *invertedHexUint32) FromProperty(p ds.Property) (err error) {
-	sVal, err := p.Project(ds.PTString)
-	if err != nil {
-		return
-	}
-
-	tmp := uint32(0)
-	if _, err = fmt.Sscanf(sVal.(string), invertedHexUint32RenderFmt, &tmp); err != nil {
-		return
-	}
-	*i = invertedHexUint32(tmp ^ math.MaxUint32)
-	return
-}
-
-// Execution represents either an ongoing execution on the Quest's specified
-// distributor, or is a placeholder for an already-completed Execution.
-type Execution struct {
-	ID      invertedHexUint32 `gae:"$id"`
-	Attempt *ds.Key           `gae:"$parent"`
-
-	Created  time.Time
-	Modified time.Time
-
-	// DistributorConfigName is redundant with the Quest definition, but this
-	// helps avoid extra unnecessary datastore round-trips to load the Quest.
-	DistributorConfigName    string
-	DistributorConfigVersion string
-	DistributorToken         string
-
-	State dm.Execution_State
-
-	// IsAbnormal is true iff State==ABNORMAL_FINISHED. Used for walk_graph.
-	IsAbnormal bool
-
-	// A lazily-updated boolean to reflect that this Execution is expired for
-	// queries.
-	IsExpired bool
-
-	// Contains either data (State==FINISHED) or abnormal_finish (State==ABNORMAL_FINISHED)
-	Result dm.Result `gae:",noindex"`
-
-	// These are DM's internal mechanism for performing timeout actions on
-	// Executions.
-	//
-	// The TimeTo* variables are copied from the quest description.
-	//
-	// The Timeout is only active when the Execution is in a non-terminal state.
-	TimeToStart time.Duration `gae:",noindex"` // timeouts.start
-	TimeToRun   time.Duration `gae:",noindex"` // timeouts.run
-	TimeToStop  time.Duration `gae:",noindex"` // pollTimeout || timeouts.stop
-
-	// Token is a randomized nonce that's used to verify that RPCs verify from the
-	// expected client (the client that's currently running the Execution). The
-	// Token has 2 modes.
-	//
-	// When the Execution is handed to the distributor, the Token is randomly
-	// generated by DM and passed to the distributor. The State of the Execution
-	// starts as SCHEDULED. This token may be used by the client to "activate" the
-	// Execution with the ActivateExecution rpc. At that point, the client
-	// provides a new random token, the Execution State moves from SCHEDULED to
-	// RUNNING, and Token assumes the new value. As long as the Execution State is
-	// RUNNING, the client may continue to use that new Token value to
-	// authenticate other rpc's like AddDeps and FinishAttempt.
-	//
-	// As soon as the Execution is in the STOPPING, ABNORMAL_FINISHED or FINISHED
-	// state, this will be nil'd out.
-	Token []byte `gae:",noindex"`
-}
-
-// MakeExecution makes a new Execution in the SCHEDULING state, with a new
-// random Token.
-func MakeExecution(c context.Context, e *dm.Execution_ID, cfgName, cfgVers string) *Execution {
-	now := clock.Now(c).UTC()
-	ret := &Execution{
-		ID:      invertedHexUint32(e.Id),
-		Attempt: AttemptKeyFromID(c, e.AttemptID()),
-
-		Created:  now,
-		Modified: now,
-
-		DistributorConfigName:    cfgName,
-		DistributorConfigVersion: cfgVers,
-
-		Token: MakeRandomToken(c, dm.MinimumActivationTokenLength),
-	}
-	return ret
-}
-
-// ModifyState changes the current state of this Execution and updates its
-// Modified timestamp.
-func (e *Execution) ModifyState(c context.Context, newState dm.Execution_State) error {
-	if e.State == newState {
-		return nil
-	}
-	if err := e.State.Evolve(newState); err != nil {
-		return err
-	}
-	now := clock.Now(c).UTC()
-	if now.After(e.Modified) {
-		e.Modified = now
-	} else {
-		// Microsecond is the smallest granularity that datastore can store
-		// timestamps, so use that to disambiguate: the goal here is that any
-		// modification always increments the modified time, and never decrements
-		// it.
-		e.Modified = e.Modified.Add(time.Microsecond)
-	}
-	return nil
-}
-
-// MakeRandomToken creates a cryptographically random byte slice of the
-// specified length. It panics if the specified length cannot be read in full.
-func MakeRandomToken(c context.Context, l uint32) []byte {
-	rtok := make([]byte, l)
-	if _, err := cryptorand.Read(c, rtok); err != nil {
-		panic(err)
-	}
-	return rtok
-}
-
-// Revoke will clear the Token and Put this Execution to the datastore. This
-// action requires the Execution to be in the RUNNING state, and causes it to
-// enter the STOPPING state.
-func (e *Execution) Revoke(c context.Context) error {
-	e.Token = nil
-	if err := e.ModifyState(c, dm.Execution_STOPPING); err != nil {
-		return err
-	}
-	return ds.Put(c, e)
-}
-
-func loadExecution(c context.Context, eid *dm.Execution_ID) (a *Attempt, e *Execution, err error) {
-	a = &Attempt{ID: *eid.AttemptID()}
-	e = &Execution{ID: invertedHexUint32(eid.Id), Attempt: ds.KeyForObj(c, a)}
-	err = ds.Get(c, a, e)
-
-	if err != nil {
-		err = grpcutil.Errf(codes.Internal,
-			"couldn't get attempt %v or its execution %d: %s", a.ID, e.ID, err)
-		return
-	}
-
-	if a.CurExecution != uint32(e.ID) {
-		err = fmt.Errorf("verifying incorrect execution %d, expected %d", a.CurExecution, e.ID)
-		return
-	}
-	return
-}
-
-func verifyExecutionAndCheckExTok(c context.Context, auth *dm.Execution_Auth) (a *Attempt, e *Execution, err error) {
-	a, e, err = loadExecution(c, auth.Id)
-	if err != nil {
-		return
-	}
-
-	if a.State != dm.Attempt_EXECUTING {
-		err = errors.New("Attempt is not executing")
-		return
-	}
-
-	if e.State != dm.Execution_RUNNING {
-		err = errors.New("Execution is not running")
-		return
-	}
-
-	if subtle.ConstantTimeCompare(e.Token, auth.Token) != 1 {
-		err = fmt.Errorf("incorrect Token: %x", hex.EncodeToString(auth.Token))
-	}
-	return
-}
-
-func makeError(err error, msg string) error {
-	code := grpcutil.Code(err)
-	if code == codes.Unknown {
-		code = codes.PermissionDenied
-	}
-	return grpcutil.Errf(code, msg)
-}
-
-// AuthenticateExecution verifies that the Attempt is executing, and that evkey
-// matches the execution key of the current Execution for this Attempt.
-//
-// As a bonus, it will return the loaded Attempt and Execution.
-func AuthenticateExecution(c context.Context, auth *dm.Execution_Auth) (a *Attempt, e *Execution, err error) {
-	a, e, err = verifyExecutionAndCheckExTok(c, auth)
-	if err != nil {
-		logging.Fields{ek: err, "eid": auth.Id}.Errorf(c, "failed to verify execution")
-		err = makeError(err, "requires execution Auth")
-	}
-	return a, e, err
-}
-
-// InvalidateExecution verifies that the execution key is valid, and then
-// revokes the execution key.
-//
-// As a bonus, it will return the loaded Attempt and Execution.
-func InvalidateExecution(c context.Context, auth *dm.Execution_Auth) (a *Attempt, e *Execution, err error) {
-	if a, e, err = verifyExecutionAndCheckExTok(c, auth); err != nil {
-		logging.Fields{ek: err, "eid": auth.Id}.Errorf(c, "failed to verify execution")
-		err = makeError(err, "requires execution Auth")
-		return
-	}
-
-	err = e.Revoke(c)
-	if err != nil {
-		logging.Fields{ek: err, "eid": auth.Id}.Errorf(c, "failed to revoke execution")
-		err = makeError(err, "unable to invalidate Auth")
-	}
-	return
-}
-
-func verifyExecutionAndActivate(c context.Context, auth *dm.Execution_Auth, actTok []byte) (a *Attempt, e *Execution, err error) {
-	a, e, err = loadExecution(c, auth.Id)
-	if err != nil {
-		return
-	}
-
-	if a.State != dm.Attempt_EXECUTING {
-		err = errors.New("Attempt is in wrong state")
-		return
-	}
-
-	switch e.State {
-	case dm.Execution_SCHEDULING:
-		if subtle.ConstantTimeCompare(e.Token, auth.Token) != 1 {
-			err = errors.New("incorrect ActivationToken")
-			return
-		}
-
-		e.State.MustEvolve(dm.Execution_RUNNING)
-		e.Token = actTok
-		err = ds.Put(c, e)
-		logging.Infof(c, "activated execution %s: was SCHEDULING now RUNNING", auth.Id)
-
-	case dm.Execution_RUNNING:
-		if subtle.ConstantTimeCompare(e.Token, actTok) != 1 {
-			err = errors.New("incorrect Token")
-		}
-		// either the Token matched, in which case this is simply a retry
-		// by the same client, so there's no error, or it's wrong which means it's
-		// a retry by a different client.
-
-		logging.Infof(c, "already activated execution %s", auth.Id)
-
-	default:
-		err = fmt.Errorf("Execution is in wrong state")
-	}
-	return
-}
-
-// ActivateExecution validates that the execution is unactivated and that
-// the activation token matches and then sets the token to the new
-// value.
-//
-// It's OK to retry this. Subsequent invocations with the same Token
-// will recognize this case and not return an error.
-func ActivateExecution(c context.Context, auth *dm.Execution_Auth, actToken []byte) (a *Attempt, e *Execution, err error) {
-	a, e, err = verifyExecutionAndActivate(c, auth, actToken)
-	if err != nil {
-		logging.Fields{ek: err, "eid": auth.Id}.Errorf(c, "failed to activate execution")
-		err = makeError(err, "failed to activate execution Auth")
-	}
-	return a, e, err
-}
-
-// GetEID gets an Execution_ID for this Execution. It panics if the Execution
-// is in an invalid state.
-func (e *Execution) GetEID() *dm.Execution_ID {
-	aid := &dm.Attempt_ID{}
-	if e.ID == 0 {
-		panic("cannot create valid Execution_ID with 0-value ID field")
-	}
-	if err := aid.SetDMEncoded(e.Attempt.StringID()); err != nil {
-		panic(err)
-	}
-	return dm.NewExecutionID(aid.Quest, aid.Id, uint32(e.ID))
-}
-
-// ToProto returns a dm proto version of this Execution.
-func (e *Execution) ToProto(includeID bool) *dm.Execution {
-	ret := &dm.Execution{Data: e.DataProto()}
-	if includeID {
-		ret.Id = e.GetEID()
-	}
-	return ret
-}
-
-// DataProto returns an Execution.Data message for this Execution.
-//
-// This omits the DistributorInfo.Url portion, which must be filled in elsewhere for
-// package cyclical import reasons.
-func (e *Execution) DataProto() (ret *dm.Execution_Data) {
-	switch e.State {
-	case dm.Execution_SCHEDULING:
-		ret = dm.NewExecutionScheduling().Data
-	case dm.Execution_RUNNING:
-		ret = dm.NewExecutionRunning().Data
-	case dm.Execution_STOPPING:
-		ret = dm.NewExecutionStopping().Data
-	case dm.Execution_FINISHED:
-		ret = dm.NewExecutionFinished(e.Result.Data).Data
-	case dm.Execution_ABNORMAL_FINISHED:
-		ret = dm.NewExecutionAbnormalFinish(e.Result.AbnormalFinish).Data
-	default:
-		panic(fmt.Errorf("unknown Execution_State: %s", e.State))
-	}
-	ret.Created = timestamppb.New(e.Created)
-	ret.Modified = timestamppb.New(e.Modified)
-	ret.DistributorInfo = &dm.Execution_Data_DistributorInfo{
-		ConfigName:    e.DistributorConfigName,
-		ConfigVersion: e.DistributorConfigVersion,
-		Token:         e.DistributorToken,
-	}
-	return ret
-}
diff --git a/dm/appengine/model/execution_test.go b/dm/appengine/model/execution_test.go
deleted file mode 100644
index 43abba5..0000000
--- a/dm/appengine/model/execution_test.go
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"google.golang.org/protobuf/types/known/timestamppb"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/gae/filter/featureBreaker"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	"go.chromium.org/luci/common/clock/testclock"
-	"go.chromium.org/luci/common/logging/memlogger"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestExecutions(t *testing.T) {
-	t.Parallel()
-
-	Convey("Execution", t, func() {
-		c := memory.Use(context.Background())
-		c = memlogger.Use(c)
-
-		a := &Attempt{ID: *dm.NewAttemptID("q", 1)}
-		ak := ds.KeyForObj(c, a)
-
-		Convey("Revoke", func() {
-			e1 := &Execution{ID: 1, Attempt: ak, Token: []byte("good tok"), State: dm.Execution_RUNNING}
-			So(ds.Put(c, e1), ShouldBeNil)
-
-			So(ds.KeyForObj(c, e1).String(), ShouldEqual,
-				`dev~app::/Attempt,"q|fffffffe"/Execution,"fffffffe"`)
-
-			e2 := *e1
-			So(e2.Revoke(c), ShouldBeNil)
-
-			So(e1.Token, ShouldResemble, []byte("good tok"))
-			So(ds.Get(c, e1), ShouldBeNil)
-			So(e1.Token, ShouldBeNil)
-		})
-
-		Convey("Verify", func() {
-			e1 := &Execution{ID: 1, Attempt: ak, Token: []byte("good tok")}
-			So(ds.Put(c, e1), ShouldBeNil)
-
-			auth := &dm.Execution_Auth{
-				Id:    dm.NewExecutionID("q", a.ID.Id, uint32(e1.ID)),
-				Token: []byte("bad tok"),
-			}
-
-			_, _, err := AuthenticateExecution(c, auth)
-			So(err, ShouldBeRPCInternal, "execution Auth")
-
-			So(ds.Put(c, a), ShouldBeNil)
-			_, _, err = AuthenticateExecution(c, auth)
-			So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-
-			a.CurExecution = 1
-			So(ds.Put(c, a), ShouldBeNil)
-			_, _, err = AuthenticateExecution(c, auth)
-			So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-
-			a.State = dm.Attempt_EXECUTING
-			So(ds.Put(c, a), ShouldBeNil)
-			_, _, err = AuthenticateExecution(c, auth)
-			So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-
-			e1.State = dm.Execution_RUNNING
-			So(ds.Put(c, e1), ShouldBeNil)
-			_, _, err = AuthenticateExecution(c, auth)
-			So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-
-			auth.Token = []byte("good tok")
-			atmpt, exe, err := AuthenticateExecution(c, auth)
-			So(err, ShouldBeNil)
-
-			So(atmpt, ShouldResemble, a)
-			So(exe, ShouldResemble, e1)
-		})
-
-		Convey("Activate", func() {
-			e1 := &Execution{
-				ID:      1,
-				Attempt: ak,
-				Token:   []byte("good tok"),
-			}
-			a.CurExecution = 1
-			So(ds.Put(c, a, e1), ShouldBeNil)
-
-			auth := &dm.Execution_Auth{
-				Id:    dm.NewExecutionID("q", a.ID.Id, uint32(e1.ID)),
-				Token: []byte("wrong tok"),
-			}
-
-			Convey("wrong execution id", func() {
-				auth.Id.Id++
-				_, _, err := ActivateExecution(c, auth, []byte("wrong tok"))
-				So(err, ShouldBeRPCInternal, "execution Auth")
-			})
-
-			Convey("attempt bad state", func() {
-				_, _, err := ActivateExecution(c, auth, []byte("wrong tok"))
-				So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-			})
-
-			Convey("attempt executing", func() {
-				a.State = dm.Attempt_EXECUTING
-				So(ds.Put(c, a), ShouldBeNil)
-
-				Convey("wrong execution state", func() {
-					e1.State = dm.Execution_STOPPING
-					So(ds.Put(c, e1), ShouldBeNil)
-					_, _, err := ActivateExecution(c, auth, []byte("wrong token"))
-					So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-				})
-
-				Convey("wrong token", func() {
-					_, _, err := ActivateExecution(c, auth, []byte("wrong tok"))
-					So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-				})
-
-				Convey("correct token", func() {
-					auth.Token = []byte("good tok")
-					newA, e, err := ActivateExecution(c, auth, []byte("new token"))
-					So(err, ShouldBeNil)
-					So(newA, ShouldResemble, a)
-					So(e.State, ShouldEqual, dm.Execution_RUNNING)
-
-					Convey("retry with different token fails", func() {
-						_, _, err = ActivateExecution(c, auth, []byte("other token"))
-						So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-					})
-
-					Convey("retry with same token OK", func() {
-						auth.Token = []byte("new token")
-						_, _, err = ActivateExecution(c, auth, []byte("new token"))
-						So(err, ShouldBeNil)
-					})
-				})
-			})
-
-		})
-
-		Convey("Invalidate", func() {
-			e1 := &Execution{
-				ID:      1,
-				Attempt: ak,
-				Token:   []byte("good tok"),
-				State:   dm.Execution_RUNNING,
-			}
-			So(ds.Put(c, e1), ShouldBeNil)
-
-			a.CurExecution = 1
-			a.State = dm.Attempt_EXECUTING
-			So(ds.Put(c, a), ShouldBeNil)
-
-			auth := &dm.Execution_Auth{
-				Id:    dm.NewExecutionID("q", a.ID.Id, uint32(e1.ID)),
-				Token: []byte("bad token"),
-			}
-
-			_, _, err := InvalidateExecution(c, auth)
-			So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-
-			auth.Token = []byte("good tok")
-			_, _, err = InvalidateExecution(c, auth)
-			So(err, ShouldBeNil)
-
-			So(ds.Get(c, e1), ShouldBeNil)
-			So(e1.Token, ShouldBeNil)
-
-			_, _, err = InvalidateExecution(c, auth)
-			So(err, ShouldBeRPCPermissionDenied, "requires execution Auth")
-		})
-
-		Convey("failed invalidation", func() {
-			e1 := &Execution{
-				ID:      1,
-				Attempt: ak,
-				Token:   []byte("good tok"),
-				State:   dm.Execution_RUNNING,
-			}
-			So(ds.Put(c, e1), ShouldBeNil)
-			a.CurExecution = 1
-			a.State = dm.Attempt_EXECUTING
-			So(ds.Put(c, a), ShouldBeNil)
-
-			auth := &dm.Execution_Auth{
-				Id:    dm.NewExecutionID("q", a.ID.Id, uint32(e1.ID)),
-				Token: []byte("good tok"),
-			}
-
-			c, fb := featureBreaker.FilterRDS(c, nil)
-			fb.BreakFeatures(nil, "PutMulti")
-
-			_, _, err := InvalidateExecution(c, auth)
-			So(err, ShouldBeRPCPermissionDenied, "unable to invalidate Auth")
-
-			fb.UnbreakFeatures("PutMulti")
-
-			_, _, err = InvalidateExecution(c, auth)
-			So(err, ShouldBeNil)
-
-			So(ds.Get(c, e1), ShouldBeNil)
-			So(e1.Token, ShouldBeNil)
-		})
-	})
-
-}
-
-func TestExecutionToProto(t *testing.T) {
-	t.Parallel()
-
-	Convey("Test Execution.ToProto", t, func() {
-		c := memory.Use(context.Background())
-		c = memlogger.Use(c)
-
-		e := &Execution{
-			ID:      1,
-			Attempt: ds.MakeKey(c, "Attempt", "qst|fffffffe"),
-
-			Created:          testclock.TestTimeUTC,
-			Modified:         testclock.TestTimeUTC,
-			DistributorToken: "id",
-
-			Token: []byte("secret"),
-		}
-
-		Convey("no id", func() {
-			exp := dm.NewExecutionScheduling()
-			exp.Data.Created = timestamppb.New(testclock.TestTimeUTC)
-			exp.Data.Modified = timestamppb.New(testclock.TestTimeUTC)
-			exp.Data.DistributorInfo = &dm.Execution_Data_DistributorInfo{Token: "id"}
-
-			So(e.ToProto(false), ShouldResemble, exp)
-		})
-
-		Convey("with id", func() {
-			exp := dm.NewExecutionScheduling()
-			exp.Id = dm.NewExecutionID("qst", 1, 1)
-			exp.Data.Created = timestamppb.New(testclock.TestTimeUTC)
-			exp.Data.Modified = timestamppb.New(testclock.TestTimeUTC)
-			exp.Data.DistributorInfo = &dm.Execution_Data_DistributorInfo{Token: "id"}
-
-			So(e.ToProto(true), ShouldResemble, exp)
-		})
-	})
-}
diff --git a/dm/appengine/model/fwddep.go b/dm/appengine/model/fwddep.go
deleted file mode 100644
index 1feafc7..0000000
--- a/dm/appengine/model/fwddep.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"sort"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	ds "go.chromium.org/luci/gae/service/datastore"
-)
-
-// FwdDep describes a 'depends-on' relation between two Attempts. It has a
-// reciprocal BackDep as well, which notes the depended-on-by relationship. So:
-//
-//   Attempt(OTHER_QUEST|2)
-//     FwdDep(QUEST|1)
-//
-//   Attempt(QUEST|1)
-//
-//   BackDepGroup(QUEST|1)
-//     BackDep(OTHER_QUEST|2)
-//
-// Represents the OTHER_QUEST|2 depending on QUEST|1.
-type FwdDep struct {
-	// Attempt that this points from.
-	Depender *ds.Key `gae:"$parent"`
-
-	// A FwdDep's ID is the Attempt ID that it points to.
-	Dependee dm.Attempt_ID `gae:"$id"`
-
-	// This will be used to set a bit in the Attempt (WaitingDepBitmap) when the
-	// Dep completes.
-	BitIndex uint32
-
-	// ForExecution indicates which Execution added this dependency. This is used
-	// for validation of AckFwdDep mutations to ensure that they're operating
-	// on an Attempt in the correct state, but can also be used for historical
-	// analysis/display.
-	ForExecution uint32
-}
-
-// Edge produces a edge object which points 'forwards' from the depending
-// attempt to the depended-on attempt.
-func (f *FwdDep) Edge() *FwdEdge {
-	ret := &FwdEdge{To: &f.Dependee, From: &dm.Attempt_ID{}}
-	if err := ret.From.SetDMEncoded(f.Depender.StringID()); err != nil {
-		panic(err)
-	}
-	return ret
-}
-
-// FwdDepsFromList creates a slice of *FwdDep given an originating base
-// Attempt_ID, and a list of dependency Attempts.
-func FwdDepsFromList(c context.Context, base *dm.Attempt_ID, list *dm.AttemptList) []*FwdDep {
-	from := ds.KeyForObj(c, &Attempt{ID: *base})
-	keys := make(sort.StringSlice, 0, len(list.To))
-	amt := 0
-	for qst, nums := range list.To {
-		keys = append(keys, qst)
-		amt += len(nums.Nums)
-	}
-	keys.Sort()
-	idx := uint32(0)
-	ret := make([]*FwdDep, 0, amt)
-	for _, key := range keys {
-		for _, num := range list.To[key].Nums {
-			dep := &FwdDep{Depender: from}
-			dep.Dependee.Quest = key
-			dep.Dependee.Id = num
-			dep.BitIndex = idx
-			idx++
-			ret = append(ret, dep)
-		}
-	}
-	return ret
-}
-
-// FwdDepKeysFromList makes a list of datastore.Key's that correspond to all
-// of the FwdDeps expressed by the <base, list> pair.
-func FwdDepKeysFromList(c context.Context, base *dm.Attempt_ID, list *dm.AttemptList) []*ds.Key {
-	keys := make(sort.StringSlice, 0, len(list.To))
-	amt := 0
-	for qst, nums := range list.To {
-		keys = append(keys, qst)
-		amt += len(nums.Nums)
-	}
-	keys.Sort()
-	ret := make([]*ds.Key, 0, amt)
-	for _, key := range keys {
-		for _, num := range list.To[key].Nums {
-			ret = append(ret, ds.MakeKey(c,
-				"Attempt", base.DMEncoded(),
-				"FwdDep", dm.NewAttemptID(key, num).DMEncoded()))
-		}
-	}
-	return ret
-}
diff --git a/dm/appengine/model/keys.go b/dm/appengine/model/keys.go
deleted file mode 100644
index a1d322b..0000000
--- a/dm/appengine/model/keys.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"fmt"
-	"math"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	ds "go.chromium.org/luci/gae/service/datastore"
-)
-
-// QuestKeyFromID makes a datastore.Key given the QuestID.
-func QuestKeyFromID(c context.Context, qid string) *ds.Key {
-	return ds.MakeKey(c, "Quest", qid)
-}
-
-// QuestFromID produces an empty Quest model from the QuestID.
-func QuestFromID(qid string) *Quest {
-	return &Quest{ID: qid}
-}
-
-// QuestIDFromKey makes a QuestID from the given datastore.Key. It panics if the
-// Key does not point to a Quest.
-func QuestIDFromKey(k *ds.Key) string {
-	if k.Kind() != "Quest" || k.Parent() != nil {
-		panic(fmt.Errorf("invalid Quest key: %s", k))
-	}
-	return k.StringID()
-}
-
-// AttemptKeyFromID makes a datastore.Key given the AttemptID.
-func AttemptKeyFromID(c context.Context, aid *dm.Attempt_ID) *ds.Key {
-	return ds.MakeKey(c, "Attempt", aid.DMEncoded())
-}
-
-// AttemptFromID produces an empty Attempt model from the AttemptID.
-func AttemptFromID(aid *dm.Attempt_ID) *Attempt {
-	ret := &Attempt{}
-	ret.ID = *aid
-	return ret
-}
-
-// AttemptIDFromKey makes a AttemptID from the given datastore.Key. It panics if the
-// Key does not point to a Attempt.
-func AttemptIDFromKey(k *ds.Key) *dm.Attempt_ID {
-	if k.Kind() != "Attempt" || k.Parent() != nil {
-		panic(fmt.Errorf("invalid Attempt key: %s", k))
-	}
-	ret := &dm.Attempt_ID{}
-	if err := ret.SetDMEncoded(k.StringID()); err != nil {
-		panic(fmt.Errorf("invalid Attempt key: %s: %s", k, err))
-	}
-	return ret
-}
-
-// ExecutionKeyFromID makes a datastore.Key given the ExecutionID.
-func ExecutionKeyFromID(c context.Context, eid *dm.Execution_ID) *ds.Key {
-	return ds.MakeKey(c, "Attempt", eid.AttemptID().DMEncoded(), "Execution", eid.Id)
-}
-
-// ExecutionFromID produces an empty Execution model from the ExecutionID.
-func ExecutionFromID(c context.Context, eid *dm.Execution_ID) *Execution {
-	ret := &Execution{}
-	ret.ID = invertedHexUint32(eid.Id)
-	ret.Attempt = AttemptKeyFromID(c, eid.AttemptID())
-	return ret
-}
-
-// ExecutionIDFromKey makes a ExecutionID from the given datastore.Key. It panics if the
-// Key does not point to a Execution.
-func ExecutionIDFromKey(k *ds.Key) *dm.Execution_ID {
-	if k.Kind() != "Execution" || k.Parent() == nil {
-		panic(fmt.Errorf("invalid Execution key: %s", k))
-	}
-	id := k.IntID()
-	if id <= 0 || id > math.MaxUint32 {
-		panic(fmt.Errorf("invalid Execution key: %s", k))
-	}
-	atmpt := AttemptIDFromKey(k.Parent())
-	return &dm.Execution_ID{Quest: atmpt.Quest, Attempt: atmpt.Id, Id: uint32(id)}
-}
diff --git a/dm/appengine/model/quest.go b/dm/appengine/model/quest.go
deleted file mode 100644
index 2b24f81..0000000
--- a/dm/appengine/model/quest.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"time"
-
-	"google.golang.org/protobuf/proto"
-	"google.golang.org/protobuf/types/known/timestamppb"
-
-	"go.chromium.org/luci/common/clock"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-// NewQuest builds a new Quest object with a correct ID given the current
-// contents of the Quest_Desc. It returns an error if the Desc is invalid.
-//
-// Desc must already be Normalize()'d
-func NewQuest(c context.Context, desc *dm.Quest_Desc) *Quest {
-	return &Quest{ID: desc.QuestID(), Desc: *desc, Created: clock.Now(c).UTC()}
-}
-
-// Quest is the model for a job-to-run. Its questPayload should fully
-// describe the job to be done.
-type Quest struct {
-	// ID is the base64 sha256 of questPayload
-	ID string `gae:"$id"`
-
-	Desc    dm.Quest_Desc `gae:",noindex"`
-	BuiltBy TemplateInfo  `gae:",noindex"`
-
-	Created time.Time `gae:",noindex"`
-}
-
-// Equals is true if q and a and equal.
-func (q *Quest) Equals(a *Quest) bool {
-	return q == a || (q.ID == a.ID &&
-		proto.Equal(&q.Desc, &a.Desc) &&
-		q.BuiltBy.Equals(a.BuiltBy) &&
-		q.Created.Equal(a.Created))
-}
-
-// QueryAttemptsForQuest returns all Attempt objects that exist for this Quest.
-func QueryAttemptsForQuest(c context.Context, qid string) *ds.Query {
-	from := ds.MakeKey(c, "Attempt", qid+"|")
-	to := ds.MakeKey(c, "Attempt", qid+"~")
-	return ds.NewQuery("Attempt").Gt("__key__", from).Lt("__key__", to)
-}
-
-// ToProto converts this Quest into its display equivalent.
-func (q *Quest) ToProto() *dm.Quest {
-	return &dm.Quest{
-		Id:   dm.NewQuestID(q.ID),
-		Data: q.DataProto(),
-	}
-}
-
-// DataProto gets the Quest.Data proto message for this Quest.
-func (q *Quest) DataProto() *dm.Quest_Data {
-	spec := make([]*dm.Quest_TemplateSpec, len(q.BuiltBy))
-	for i := range q.BuiltBy {
-		spec[i] = &q.BuiltBy[i]
-	}
-
-	return &dm.Quest_Data{
-		Created: timestamppb.New(q.Created),
-		Desc:    &q.Desc,
-		BuiltBy: spec,
-	}
-}
diff --git a/dm/appengine/model/quest_test.go b/dm/appengine/model/quest_test.go
deleted file mode 100644
index 40ab3f7..0000000
--- a/dm/appengine/model/quest_test.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"context"
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"google.golang.org/protobuf/types/known/timestamppb"
-
-	"go.chromium.org/luci/common/clock/testclock"
-	. "go.chromium.org/luci/common/testing/assertions"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-func TestQuest(t *testing.T) {
-	t.Parallel()
-
-	Convey("Quest", t, func() {
-		c := memory.Use(context.Background())
-		c, _ = testclock.UseTime(c, testclock.TestTimeUTC)
-
-		Convey("QuestDescriptor", func() {
-			Convey("good", func() {
-				Convey("normal (normalized)", func() {
-					qd := dm.NewQuestDesc("swarming", `{  "key"  :  ["value"]}`, "{  }", nil)
-					So(qd.Normalize(), ShouldBeNil)
-					So(NewQuest(c, qd), ShouldResemble, &Quest{
-						"1258phYs8GW6qM5AQopQ_L3A5cZhO7iaYQZyFkNusVw",
-						*qd,
-						nil,
-						testclock.TestTimeUTC,
-					})
-				})
-
-				Convey("extra data", func() {
-					qd := dm.NewQuestDesc("swarming", `{"key":["value"]} foof`, "{  }", nil)
-					So(qd.Normalize(), ShouldErrLike, "extra junk")
-				})
-
-				Convey("data ordering", func() {
-					qd := dm.NewQuestDesc("swarming", `{"key":["value"], "abc": true}`, "{  }", nil)
-					So(qd.Normalize(), ShouldBeNil)
-					So(NewQuest(c, qd), ShouldResemble, &Quest{
-						"IMTBeXfkZgGntgNfWMuLa_YQA62o9dzxi0EoLCYXbsE",
-						*qd,
-						nil,
-						testclock.TestTimeUTC,
-					})
-				})
-
-			})
-
-			Convey("bad", func() {
-				Convey("payload too large", func() {
-					payload := make([]byte, 512*1000)
-					qd := dm.NewQuestDesc("swarming", string(payload), "{}", nil)
-					So(qd.Normalize(), ShouldErrLike, "too large: 512002 > 262144")
-				})
-
-				Convey("json with null byte", func() {
-					qd := dm.NewQuestDesc("swarming", "{\"key\": \"\x00\"}", "{}", nil)
-					So(qd.Normalize(), ShouldErrLike, "invalid character")
-				})
-
-				Convey("not a dictionary", func() {
-					qd := dm.NewQuestDesc("swarming", "[]", "{}", nil)
-					So(qd.Normalize(), ShouldErrLike, "cannot unmarshal array")
-				})
-			})
-		})
-
-		Convey("ToProto", func() {
-			qd := dm.NewQuestDesc("swarming", `{"key": ["value"]}`, "{}", nil)
-			So(qd.Normalize(), ShouldBeNil)
-			q := NewQuest(c, qd)
-			p := q.ToProto()
-			So(p, ShouldResemble, &dm.Quest{
-				Id: dm.NewQuestID("1258phYs8GW6qM5AQopQ_L3A5cZhO7iaYQZyFkNusVw"),
-				Data: &dm.Quest_Data{
-					Created: timestamppb.New(testclock.TestTimeUTC),
-					Desc:    &q.Desc,
-					BuiltBy: []*dm.Quest_TemplateSpec{},
-				},
-			})
-			So(p.Data.Desc.Parameters, ShouldResemble, `{"key":["value"]}`)
-		})
-
-		Convey("QueryAttemptsForQuest", func() {
-			qd := dm.NewQuestDesc("swarming", `{"key": ["value"]}`, "{}", nil)
-			So(qd.Normalize(), ShouldBeNil)
-			q := NewQuest(c, qd)
-			So(ds.Put(c, q), ShouldBeNil)
-			ds.GetTestable(c).CatchupIndexes()
-
-			as := []*Attempt(nil)
-			So(ds.GetAll(c, QueryAttemptsForQuest(c, q.ID), &as), ShouldBeNil)
-			So(as, ShouldBeNil)
-
-			a := &Attempt{ID: *dm.NewAttemptID(q.ID, 1)}
-			So(ds.Put(c, a), ShouldBeNil)
-			a.ID.Id = 2
-			So(ds.Put(c, a), ShouldBeNil)
-			a.ID.Quest = "eMpqiyje5ItTX8IistN7IlAMVxyCsJcez4DAHKvhm7X" // one less
-			a.ID.Id = 1
-			So(ds.Put(c, a), ShouldBeNil)
-			a.ID.Quest = "eMpqiyje5ItTX8IistN7IlAMVxyCsJcez4DAHKvhm7Z" // one more
-			So(ds.Put(c, a), ShouldBeNil)
-
-			as = nil
-			So(ds.GetAll(c, QueryAttemptsForQuest(c, q.ID), &as), ShouldBeNil)
-			So(as, ShouldBeNil)
-
-			ds.GetTestable(c).CatchupIndexes()
-			as = nil
-			So(ds.GetAll(c, QueryAttemptsForQuest(c, q.ID), &as), ShouldBeNil)
-			So(as, ShouldResembleProto, []*Attempt{
-				{ID: *dm.NewAttemptID("1258phYs8GW6qM5AQopQ_L3A5cZhO7iaYQZyFkNusVw", 2)},
-				{ID: *dm.NewAttemptID("1258phYs8GW6qM5AQopQ_L3A5cZhO7iaYQZyFkNusVw", 1)},
-			})
-
-		})
-	})
-}
diff --git a/dm/appengine/model/template_info.go b/dm/appengine/model/template_info.go
deleted file mode 100644
index 8e419d6..0000000
--- a/dm/appengine/model/template_info.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"sort"
-
-	"github.com/xtgo/set"
-	"go.chromium.org/luci/common/data/sortby"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-// TemplateInfo is an ordered list of dm.Quest_TemplateSpec's
-type TemplateInfo []dm.Quest_TemplateSpec
-
-func (ti TemplateInfo) Len() int      { return len(ti) }
-func (ti TemplateInfo) Swap(i, j int) { ti[i], ti[j] = ti[j], ti[i] }
-func (ti TemplateInfo) Less(i, j int) bool {
-	return sortby.Chain{
-		func(i, j int) bool { return ti[i].Project < ti[j].Project },
-		func(i, j int) bool { return ti[i].Ref < ti[j].Ref },
-		func(i, j int) bool { return ti[i].Version < ti[j].Version },
-		func(i, j int) bool { return ti[i].Name < ti[j].Name },
-	}.Use(i, j)
-}
-
-// Equals returns true iff this TemplateInfo is exactly same as `other`.
-func (ti TemplateInfo) Equals(other TemplateInfo) bool {
-	if len(other) != len(ti) {
-		return false
-	}
-	for i, me := range ti {
-		if !me.Equals(&other[i]) {
-			return false
-		}
-	}
-	return true
-}
-
-// EqualsData returns true iff this TemplateInfo has the same content as the
-// proto-style TemplateInfo. This assumes that `other` is sorted.
-func (ti TemplateInfo) EqualsData(other []*dm.Quest_TemplateSpec) bool {
-	if len(other) != len(ti) {
-		return false
-	}
-	for i, me := range ti {
-		if !me.Equals(other[i]) {
-			return false
-		}
-	}
-	return true
-}
-
-// Add adds ts to the TemplateInfo uniq'ly.
-func (ti *TemplateInfo) Add(ts ...dm.Quest_TemplateSpec) {
-	*ti = append(*ti, ts...)
-	sort.Sort(*ti)
-	*ti = (*ti)[:set.Uniq(*ti)]
-}
diff --git a/dm/appengine/model/template_info_test.go b/dm/appengine/model/template_info_test.go
deleted file mode 100644
index 5e7388f..0000000
--- a/dm/appengine/model/template_info_test.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package model
-
-import (
-	"sort"
-	"testing"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestTemplateInfo(t *testing.T) {
-	t.Parallel()
-
-	Convey("Test TemplateInfo", t, func() {
-		ti := TemplateInfo{}
-
-		Convey("empty", func() {
-			So(ti.EqualsData(nil), ShouldBeTrue)
-			sort.Sort(ti)
-
-			Convey("can add", func() {
-				ti.Add(*dm.NewTemplateSpec("proj", "ref", "vers", "name"))
-				So(ti[0], ShouldResemble, *dm.NewTemplateSpec("proj", "ref", "vers", "name"))
-			})
-		})
-
-		Convey("can uniq", func() {
-			ti.Add(
-				*dm.NewTemplateSpec("a", "b", "c", "d"),
-				*dm.NewTemplateSpec("a", "b", "c", "d"),
-				*dm.NewTemplateSpec("a", "b", "c", "d"),
-				*dm.NewTemplateSpec("a", "b", "c", "d"),
-			)
-			So(len(ti), ShouldEqual, 1)
-		})
-
-		Convey("can sort", func() {
-			ti.Add(
-				*dm.NewTemplateSpec("z", "b", "c", "d"),
-				*dm.NewTemplateSpec("a", "b", "z", "d"),
-				*dm.NewTemplateSpec("a", "z", "c", "d"),
-				*dm.NewTemplateSpec("a", "b", "c", "z"),
-			)
-			So(ti, ShouldResemble, TemplateInfo{
-				*dm.NewTemplateSpec("a", "b", "c", "z"),
-				*dm.NewTemplateSpec("a", "b", "z", "d"),
-				*dm.NewTemplateSpec("a", "z", "c", "d"),
-				*dm.NewTemplateSpec("z", "b", "c", "d"),
-			})
-		})
-
-		Convey("equivalence", func() {
-			other := []*dm.Quest_TemplateSpec{
-				dm.NewTemplateSpec("a", "b", "c", "z"),
-				dm.NewTemplateSpec("a", "b", "z", "d"),
-				dm.NewTemplateSpec("a", "z", "c", "d"),
-				dm.NewTemplateSpec("z", "b", "c", "d"),
-			}
-
-			So(ti.EqualsData(other), ShouldBeFalse)
-
-			ti.Add(
-				*dm.NewTemplateSpec("z", "b", "c", "d"),
-				*dm.NewTemplateSpec("a", "b", "z", "d"),
-				*dm.NewTemplateSpec("a", "z", "c", "d"),
-				*dm.NewTemplateSpec("a", "b", "c", "z"),
-			)
-			So(ti.EqualsData(other), ShouldBeTrue)
-
-			ti[3].Project = "Z"
-			So(ti.EqualsData(other), ShouldBeFalse)
-		})
-	})
-}
diff --git a/dm/appengine/mutate/ack_fwd_dep.go b/dm/appengine/mutate/ack_fwd_dep.go
deleted file mode 100644
index 0f61885..0000000
--- a/dm/appengine/mutate/ack_fwd_dep.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// AckFwdDep records the fact that a dependency was completed.
-type AckFwdDep struct {
-	Dep *model.FwdEdge
-}
-
-// Root implements tumble.Mutation.
-func (f *AckFwdDep) Root(c context.Context) *ds.Key {
-	return model.AttemptKeyFromID(c, f.Dep.From)
-}
-
-// RollForward implements tumble.Mutation.
-func (f *AckFwdDep) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	atmpt, fdep := f.Dep.Fwd(c)
-	err = ds.Get(c, atmpt, fdep)
-	if err != nil {
-		return
-	}
-
-	if (atmpt.State != dm.Attempt_EXECUTING && atmpt.State != dm.Attempt_WAITING) || atmpt.CurExecution != fdep.ForExecution {
-		logging.Errorf(c, "EARLY EXIT: %s: %s v %s", atmpt.State, atmpt.CurExecution, fdep.ForExecution)
-		return
-	}
-
-	idx := uint32(fdep.BitIndex)
-
-	if !atmpt.DepMap.IsSet(idx) {
-		atmpt.DepMap.Set(idx)
-
-		if atmpt.DepMap.All(true) && atmpt.State == dm.Attempt_WAITING {
-			if err = atmpt.ModifyState(c, dm.Attempt_SCHEDULING); err != nil {
-				return
-			}
-			atmpt.DepMap.Reset()
-			muts = append(muts, &ScheduleExecution{For: f.Dep.From})
-		}
-
-		err = ds.Put(c, atmpt)
-	}
-
-	return
-}
-
-func init() {
-	tumble.Register((*AckFwdDep)(nil))
-}
diff --git a/dm/appengine/mutate/ack_fwd_dep_test.go b/dm/appengine/mutate/ack_fwd_dep_test.go
deleted file mode 100644
index e3a6353..0000000
--- a/dm/appengine/mutate/ack_fwd_dep_test.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"testing"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-	"go.chromium.org/luci/tumble/bitfield"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestAckFwdDep(t *testing.T) {
-	t.Parallel()
-
-	Convey("AckFwdDep", t, func() {
-		c := memory.Use(context.Background())
-
-		afd := &AckFwdDep{
-			Dep: &model.FwdEdge{
-				From: dm.NewAttemptID("quest", 1),
-				To:   dm.NewAttemptID("to", 1),
-			},
-		}
-
-		Convey("Root", func() {
-			So(afd.Root(c), ShouldResemble, ds.MakeKey(c, "Attempt", "quest|fffffffe"))
-		})
-
-		Convey("RollForward", func() {
-			a, fwd := afd.Dep.Fwd(c)
-
-			Convey("AddingDeps", func() {
-				Convey("good", func() {
-					a.State = dm.Attempt_WAITING
-					a.DepMap = bitfield.Make(2)
-					So(ds.Put(c, a, fwd), ShouldBeNil)
-
-					Convey("not-last", func() {
-						muts, err := afd.RollForward(c)
-						So(err, ShouldBeNil)
-						So(muts, ShouldBeNil)
-
-						So(ds.Get(c, a, fwd), ShouldBeNil)
-						So(a.State, ShouldEqual, dm.Attempt_WAITING)
-						So(a.DepMap.CountSet(), ShouldEqual, 1)
-					})
-
-					Convey("last-finished", func() {
-						a.DepMap.Set(1)
-						So(ds.Put(c, a), ShouldBeNil)
-
-						muts, err := afd.RollForward(c)
-						So(err, ShouldBeNil)
-						So(muts, ShouldResemble, []tumble.Mutation{
-							&ScheduleExecution{&a.ID}})
-
-						So(ds.Get(c, a, fwd), ShouldBeNil)
-						So(a.State, ShouldEqual, dm.Attempt_SCHEDULING)
-						So(a.DepMap.CountSet(), ShouldEqual, 0) // was reset
-					})
-				})
-
-				Convey("bad", func() {
-					a.State = dm.Attempt_WAITING
-					a.DepMap = bitfield.Make(2)
-					a.CurExecution = 1
-					So(ds.Put(c, a, fwd), ShouldBeNil)
-
-					Convey("CurExecution mismatch -> NOP", func() {
-						muts, err := afd.RollForward(c)
-						So(err, ShouldBeNil)
-						So(muts, ShouldBeNil)
-
-						So(ds.Get(c, a, fwd), ShouldBeNil)
-						So(a.State, ShouldEqual, dm.Attempt_WAITING)
-						So(a.DepMap.CountSet(), ShouldEqual, 0)
-					})
-
-					Convey("Missing data", func() {
-						So(ds.Delete(c, ds.KeyForObj(c, a)), ShouldBeNil)
-
-						_, err := afd.RollForward(c)
-						So(err, ShouldErrLike, ds.ErrNoSuchEntity)
-					})
-				})
-
-			})
-		})
-	})
-}
diff --git a/dm/appengine/mutate/activate_execution.go b/dm/appengine/mutate/activate_execution.go
deleted file mode 100644
index 164cc0d..0000000
--- a/dm/appengine/mutate/activate_execution.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// ActivateExecution executes an execution, moving it from the
-// SCHEDULING->RUNNING state, and resetting the execution timeout (if any).
-type ActivateExecution struct {
-	Auth   *dm.Execution_Auth
-	NewTok []byte
-}
-
-// Root implements tumble.Mutation.
-func (a *ActivateExecution) Root(c context.Context) *datastore.Key {
-	return model.AttemptKeyFromID(c, a.Auth.Id.AttemptID())
-}
-
-// RollForward implements tumble.Mutation
-func (a *ActivateExecution) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	_, e, err := model.ActivateExecution(c, a.Auth, a.NewTok)
-	if err == nil {
-		err = ResetExecutionTimeout(c, e)
-	}
-	return
-}
-
-func init() {
-	tumble.Register((*ActivateExecution)(nil))
-}
diff --git a/dm/appengine/mutate/add_backdep.go b/dm/appengine/mutate/add_backdep.go
deleted file mode 100644
index 1d8a5af..0000000
--- a/dm/appengine/mutate/add_backdep.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// AddBackDep adds a BackDep (and possibly a BackDepGroup). If NeedsAck
-// is true, this mutation will chain to an AckFwdDep. It should only be false
-// if this AddBackDep is spawned from an AddFinishedDeps, where the originating
-// Attempt already knows that this dependency is Finished.
-type AddBackDep struct {
-	Dep      *model.FwdEdge
-	NeedsAck bool // make AckFwdDep iff true
-}
-
-// Root implements tumble.Mutation.
-func (a *AddBackDep) Root(c context.Context) *ds.Key {
-	bdg, _ := a.Dep.Back(c)
-	return ds.KeyForObj(c, bdg)
-}
-
-// RollForward implements tumble.Mutation.
-func (a *AddBackDep) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	bdg, bd := a.Dep.Back(c)
-	err = ds.Get(c, bdg)
-	if err == ds.ErrNoSuchEntity {
-		err = ds.Put(c, bdg)
-	}
-	if err != nil {
-		return
-	}
-
-	bd.Propagated = bdg.AttemptFinished
-
-	err = ds.Put(c, bd)
-
-	if a.NeedsAck && bdg.AttemptFinished {
-		muts = append(muts, &AckFwdDep{a.Dep})
-	}
-	return
-}
-
-func init() {
-	tumble.Register((*AddBackDep)(nil))
-}
diff --git a/dm/appengine/mutate/add_backdep_test.go b/dm/appengine/mutate/add_backdep_test.go
deleted file mode 100644
index 1928823..0000000
--- a/dm/appengine/mutate/add_backdep_test.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"testing"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/filter/featureBreaker"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestAddBackDep(t *testing.T) {
-	t.Parallel()
-
-	Convey("AddBackDep", t, func() {
-		c := memory.Use(context.Background())
-
-		abd := &AddBackDep{
-			Dep: &model.FwdEdge{
-				From: dm.NewAttemptID("quest", 1),
-				To:   dm.NewAttemptID("to", 1),
-			},
-		}
-
-		Convey("Root", func() {
-			So(abd.Root(c).String(), ShouldEqual, `dev~app::/BackDepGroup,"to|fffffffe"`)
-		})
-
-		Convey("RollForward", func() {
-			bdg, bd := abd.Dep.Back(c)
-			So(bd.Propagated, ShouldBeFalse)
-
-			Convey("attempt finished", func() {
-				bdg.AttemptFinished = true
-				So(ds.Put(c, bdg), ShouldBeNil)
-
-				Convey("no need completion", func() {
-					muts, err := abd.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeNil)
-
-					So(ds.Get(c, bdg, bd), ShouldBeNil)
-					So(bd.Edge(), ShouldResemble, abd.Dep)
-					So(bd.Propagated, ShouldBeTrue)
-				})
-
-				Convey("need completion", func() {
-					abd.NeedsAck = true
-					muts, err := abd.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldResemble, []tumble.Mutation{&AckFwdDep{abd.Dep}})
-
-					So(ds.Get(c, bdg, bd), ShouldBeNil)
-					So(bd.Edge(), ShouldResemble, abd.Dep)
-					So(bd.Propagated, ShouldBeTrue)
-				})
-			})
-
-			Convey("attempt not finished, need completion", func() {
-				ex, err := ds.Exists(c, ds.KeyForObj(c, bdg))
-				So(err, ShouldBeNil)
-				So(ex.Any(), ShouldBeFalse)
-
-				abd.NeedsAck = true
-				muts, err := abd.RollForward(c)
-				So(err, ShouldBeNil)
-				So(muts, ShouldBeNil)
-
-				// Note that bdg was created as a side effect.
-				So(ds.Get(c, bdg, bd), ShouldBeNil)
-				So(bd.Edge(), ShouldResemble, abd.Dep)
-				So(bd.Propagated, ShouldBeFalse)
-				So(bdg.AttemptFinished, ShouldBeFalse)
-			})
-
-			Convey("failure", func() {
-				c, fb := featureBreaker.FilterRDS(c, nil)
-				fb.BreakFeatures(nil, "PutMulti")
-
-				_, err := abd.RollForward(c)
-				So(err, ShouldErrLike, `feature "PutMulti" is broken`)
-			})
-		})
-	})
-}
diff --git a/dm/appengine/mutate/add_deps.go b/dm/appengine/mutate/add_deps.go
deleted file mode 100644
index ca6ae49..0000000
--- a/dm/appengine/mutate/add_deps.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/grpc/grpcutil"
-	"go.chromium.org/luci/tumble"
-	"go.chromium.org/luci/tumble/bitfield"
-
-	"google.golang.org/grpc/codes"
-)
-
-// AddDeps transactionally stops the current execution and adds one or more
-// dependencies.
-type AddDeps struct {
-	Auth   *dm.Execution_Auth
-	Quests []*model.Quest
-
-	// Attempts is attempts we think are missing from the global graph.
-	Attempts *dm.AttemptList
-
-	// Deps are fwddeps we think are missing from the auth'd attempt.
-	Deps *dm.AttemptList
-}
-
-// Root implements tumble.Mutation
-func (a *AddDeps) Root(c context.Context) *ds.Key {
-	return model.AttemptKeyFromID(c, a.Auth.Id.AttemptID())
-}
-
-// RollForward implements tumble.Mutation
-//
-// This mutation is called directly.
-func (a *AddDeps) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	// Invalidate the execution key so that they can't make more API calls.
-	atmpt, ex, err := model.InvalidateExecution(c, a.Auth)
-	if err != nil {
-		return
-	}
-
-	if err = ResetExecutionTimeout(c, ex); err != nil {
-		logging.WithError(err).Errorf(c, "could not reset timeout")
-		return
-	}
-
-	fwdDeps, err := filterExisting(c, model.FwdDepsFromList(c, a.Auth.Id.AttemptID(), a.Deps))
-	err = errors.Annotate(err, "while filtering deps").Tag(grpcutil.Tag.With(codes.Internal)).Err()
-	if err != nil || len(fwdDeps) == 0 {
-		return
-	}
-
-	logging.Fields{"aid": atmpt.ID, "count": len(fwdDeps)}.Infof(c, "added deps")
-	atmpt.DepMap = bitfield.Make(uint32(len(fwdDeps)))
-
-	for i, fdp := range fwdDeps {
-		fdp.BitIndex = uint32(i)
-		fdp.ForExecution = atmpt.CurExecution
-	}
-
-	if err = ds.Put(c, fwdDeps, atmpt, ex); err != nil {
-		err = errors.Annotate(err, "putting stuff").Tag(grpcutil.Tag.With(codes.Internal)).Err()
-		return
-	}
-
-	mergeQuestMap := map[string]*MergeQuest(nil)
-	if len(a.Quests) > 0 {
-		mergeQuestMap = make(map[string]*MergeQuest, len(a.Quests))
-		for _, q := range a.Quests {
-			mergeQuestMap[q.ID] = &MergeQuest{Quest: q}
-		}
-	}
-
-	muts = make([]tumble.Mutation, 0, len(fwdDeps)+len(a.Attempts.GetTo())+len(a.Quests))
-	for _, dep := range fwdDeps {
-		toAppend := &muts
-		if mq := mergeQuestMap[dep.Dependee.Quest]; mq != nil {
-			toAppend = &mq.AndThen
-		}
-
-		if nums, ok := a.Attempts.GetTo()[dep.Dependee.Quest]; ok {
-			for _, n := range nums.Nums {
-				if n == dep.Dependee.Id {
-					*toAppend = append(*toAppend, &EnsureAttempt{ID: &dep.Dependee})
-					break
-				}
-			}
-		}
-		*toAppend = append(*toAppend, &AddBackDep{
-			Dep:      dep.Edge(),
-			NeedsAck: true,
-		})
-	}
-
-	// TODO(iannucci): This could run into datastore transaction limits. We could
-	// allieviate this by only emitting a single mutation which does tail-calls to
-	// decrease its own, unprocessed size by emitting new MergeQuest mutations.
-	for _, mut := range mergeQuestMap {
-		muts = append(muts, mut)
-	}
-
-	return
-}
-
-func init() {
-	tumble.Register((*AddDeps)(nil))
-}
diff --git a/dm/appengine/mutate/add_deps_test.go b/dm/appengine/mutate/add_deps_test.go
deleted file mode 100644
index 94b97d4..0000000
--- a/dm/appengine/mutate/add_deps_test.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"testing"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestAddDeps(t *testing.T) {
-	t.Parallel()
-
-	Convey("AddDeps", t, func() {
-		c := memory.Use(context.Background())
-
-		aid := dm.NewAttemptID("quest", 1)
-		a := model.MakeAttempt(c, aid)
-		a.CurExecution = 1
-		a.State = dm.Attempt_EXECUTING
-		ex := &model.Execution{
-			ID: 1, Attempt: ds.KeyForObj(c, a), Token: []byte("sup"),
-			State: dm.Execution_RUNNING}
-
-		ad := &AddDeps{
-			Auth: &dm.Execution_Auth{
-				Id:    dm.NewExecutionID("quest", 1, 1),
-				Token: []byte("sup"),
-			},
-			Deps: dm.NewAttemptList(map[string][]uint32{
-				"to":    {1, 2, 3},
-				"top":   {1},
-				"tp":    {1},
-				"zebra": {17},
-			}),
-		}
-		fds := model.FwdDepsFromList(c, aid, ad.Deps)
-
-		Convey("Root", func() {
-			So(ad.Root(c).String(), ShouldEqual, `dev~app::/Attempt,"quest|fffffffe"`)
-		})
-
-		Convey("RollForward", func() {
-
-			Convey("Bad", func() {
-				Convey("Bad ExecutionKey", func() {
-					So(ds.Put(c, a, ex), ShouldBeNil)
-
-					ad.Auth.Token = []byte("nerp")
-					muts, err := ad.RollForward(c)
-					So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-					So(muts, ShouldBeEmpty)
-				})
-			})
-
-			Convey("Good", func() {
-				So(ds.Put(c, a, ex), ShouldBeNil)
-
-				Convey("All added already", func() {
-					So(ds.Put(c, fds), ShouldBeNil)
-
-					muts, err := ad.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeEmpty)
-				})
-
-				Convey("None added already", func() {
-					muts, err := ad.RollForward(c)
-					So(err, ShouldBeNil)
-					So(len(muts), ShouldEqual, len(fds))
-
-					So(muts[0], ShouldResemble, &AddBackDep{
-						Dep: fds[0].Edge(), NeedsAck: true})
-
-					So(ds.Get(c, a, fds), ShouldBeNil)
-					So(a.DepMap.Size(), ShouldEqual, len(fds))
-					So(a.State, ShouldEqual, dm.Attempt_EXECUTING)
-					So(fds[0].ForExecution, ShouldEqual, 1)
-
-					muts, err = (&FinishExecution{
-						ad.Auth.Id, &dm.Result{Data: dm.NewJsonResult(`{"hi": true}`)},
-					}).RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeNil)
-
-					So(ds.Get(c, a), ShouldBeNil)
-					So(a.State, ShouldEqual, dm.Attempt_WAITING)
-				})
-
-				Convey("adding new Attempts at the same time", func() {
-					ad.Attempts = dm.NewAttemptList(map[string][]uint32{
-						"to": {2, 3},
-						"tp": {1},
-					})
-
-					muts, err := ad.RollForward(c)
-					So(err, ShouldBeNil)
-					So(len(muts), ShouldEqual, len(fds)+3)
-
-					So(muts[0], ShouldResemble, &EnsureAttempt{dm.NewAttemptID("to", 3)})
-					So(muts[1], ShouldResemble, &AddBackDep{
-						Dep: fds[0].Edge(), NeedsAck: true})
-
-					So(ds.Get(c, a, fds), ShouldBeNil)
-					So(a.DepMap.Size(), ShouldEqual, len(fds))
-					So(a.State, ShouldEqual, dm.Attempt_EXECUTING)
-					So(fds[0].ForExecution, ShouldEqual, 1)
-
-					muts, err = (&FinishExecution{
-						ad.Auth.Id, &dm.Result{Data: dm.NewJsonResult(`{"hi":true}`)},
-					}).RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeNil)
-
-					So(ds.Get(c, a), ShouldBeNil)
-					So(a.State, ShouldEqual, dm.Attempt_WAITING)
-				})
-			})
-		})
-	})
-}
diff --git a/dm/appengine/mutate/add_finished_deps.go b/dm/appengine/mutate/add_finished_deps.go
deleted file mode 100644
index 8c6d951..0000000
--- a/dm/appengine/mutate/add_finished_deps.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// AddFinishedDeps adds a bunch of dependencies which are known in advance to
-// already be in the Finished state.
-type AddFinishedDeps struct {
-	Auth *dm.Execution_Auth
-
-	// MergeQuests lists quests which need their BuiltBy lists merged. The Quests
-	// here must be a subset of the quests mentioned in FinishedAttempts.
-	MergeQuests []*model.Quest
-
-	// FinishedAttempts are a list of attempts that we already know are in the
-	// Finished state.
-	FinishedAttempts *dm.AttemptList
-}
-
-// Root implements tumble.Mutation
-func (f *AddFinishedDeps) Root(c context.Context) *ds.Key {
-	return model.AttemptKeyFromID(c, f.Auth.Id.AttemptID())
-}
-
-// RollForward implements tumble.Mutation
-func (f *AddFinishedDeps) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	atmpt, _, err := model.AuthenticateExecution(c, f.Auth)
-	if err != nil {
-		return
-	}
-
-	fwdDeps, err := filterExisting(c, model.FwdDepsFromList(c, f.Auth.Id.AttemptID(), f.FinishedAttempts))
-	if err != nil || len(fwdDeps) == 0 {
-		return
-	}
-
-	muts = make([]tumble.Mutation, 0, len(fwdDeps)+len(f.MergeQuests))
-	for _, d := range fwdDeps {
-		d.ForExecution = atmpt.CurExecution
-		muts = append(muts, &AddBackDep{Dep: d.Edge()})
-	}
-	for _, q := range f.MergeQuests {
-		muts = append(muts, &MergeQuest{Quest: q})
-	}
-
-	return muts, ds.Put(c, fwdDeps)
-}
-
-func init() {
-	tumble.Register((*AddFinishedDeps)(nil))
-}
diff --git a/dm/appengine/mutate/add_finished_deps_test.go b/dm/appengine/mutate/add_finished_deps_test.go
deleted file mode 100644
index 0c5cc39..0000000
--- a/dm/appengine/mutate/add_finished_deps_test.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"testing"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestAddFinishedDeps(t *testing.T) {
-	t.Parallel()
-
-	Convey("AddFinishedDeps", t, func() {
-		c := memory.Use(context.Background())
-		f := &AddFinishedDeps{
-			&dm.Execution_Auth{
-				Id:    dm.NewExecutionID("quest", 1, 7),
-				Token: []byte("sup"),
-			},
-			[]*model.Quest{
-				{
-					ID: "to",
-					BuiltBy: model.TemplateInfo{
-						*dm.NewTemplateSpec("a", "b", "c", "d"),
-					},
-				},
-			},
-			dm.NewAttemptList(map[string][]uint32{
-				"to": {1, 2, 3},
-			}),
-		}
-
-		base := f.Auth.Id.AttemptID()
-		fs := model.FwdDepsFromList(c, base, f.FinishedAttempts)
-
-		fs[1].ForExecution = 1
-		So(ds.Put(c, fs[1]), ShouldBeNil)
-
-		a := &model.Attempt{ID: *base, State: dm.Attempt_EXECUTING, CurExecution: 7}
-		ak := ds.KeyForObj(c, a)
-		e := &model.Execution{
-			ID: 7, Attempt: ak, State: dm.Execution_RUNNING, Token: []byte("sup")}
-		So(ds.Put(c, a, e), ShouldBeNil)
-
-		Convey("Root", func() {
-			So(f.Root(c).String(), ShouldEqual, `dev~app::/Attempt,"quest|fffffffe"`)
-		})
-
-		Convey("RollForward", func() {
-			err := ds.Get(c, fs)
-			So(err, ShouldResemble, errors.MultiError{
-				ds.ErrNoSuchEntity,
-				nil,
-				ds.ErrNoSuchEntity,
-			})
-
-			muts, err := f.RollForward(c)
-			So(err, ShouldBeNil)
-			So(muts, ShouldResemble, []tumble.Mutation{
-				&AddBackDep{Dep: fs[0].Edge()},
-				&AddBackDep{Dep: fs[2].Edge()},
-				&MergeQuest{f.MergeQuests[0], nil},
-			})
-
-			So(ds.Get(c, fs), ShouldBeNil)
-			So(fs[0].ForExecution, ShouldEqual, 7)
-			So(fs[1].ForExecution, ShouldEqual, 1)
-			So(fs[2].ForExecution, ShouldEqual, 7)
-
-			muts, err = f.RollForward(c)
-			So(err, ShouldBeNil)
-			So(muts, ShouldBeEmpty)
-		})
-
-		Convey("RollForward (bad)", func() {
-			So(ds.Delete(c, ak), ShouldBeNil)
-			_, err := f.RollForward(c)
-			So(err, ShouldBeRPCInternal, "execution Auth")
-		})
-	})
-}
diff --git a/dm/appengine/mutate/doc.go b/dm/appengine/mutate/doc.go
deleted file mode 100644
index c50a53d..0000000
--- a/dm/appengine/mutate/doc.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package mutate includes the main logic of DM's state machine. The package
-// is a series of "go.chromium.org/luci/tumble".Mutation implementations.
-// Each mutation operates on a single entity group in DM's datastore model,
-// advancing the state machine for the dependency graph by one edge.
-package mutate
diff --git a/dm/appengine/mutate/ensure_attempt.go b/dm/appengine/mutate/ensure_attempt.go
deleted file mode 100644
index dc4d3c1..0000000
--- a/dm/appengine/mutate/ensure_attempt.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// EnsureAttempt ensures that the given Attempt exists. If it doesn't, it's
-// created in a NeedsExecution state.
-type EnsureAttempt struct {
-	ID *dm.Attempt_ID
-}
-
-// Root implements tumble.Mutation.
-func (e *EnsureAttempt) Root(c context.Context) *ds.Key {
-	return model.AttemptKeyFromID(c, e.ID)
-}
-
-// RollForward implements tumble.Mutation.
-func (e *EnsureAttempt) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	a := model.MakeAttempt(c, e.ID)
-	if err = ds.Get(c, a); err != ds.ErrNoSuchEntity {
-		return
-	}
-
-	if err = ds.Put(c, a); err != nil {
-		logging.WithError(err).Errorf(logging.SetField(c, "id", e.ID), "in put")
-	}
-	muts = append(muts, &ScheduleExecution{e.ID})
-	return
-}
-
-func init() {
-	tumble.Register((*EnsureAttempt)(nil))
-}
diff --git a/dm/appengine/mutate/ensure_attempt_test.go b/dm/appengine/mutate/ensure_attempt_test.go
deleted file mode 100644
index 09e05b2..0000000
--- a/dm/appengine/mutate/ensure_attempt_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"testing"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/filter/featureBreaker"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestEnsureAttempt(t *testing.T) {
-	t.Parallel()
-
-	Convey("EnsureAttempt", t, func() {
-		c := memory.Use(context.Background())
-		ea := &EnsureAttempt{dm.NewAttemptID("quest", 1)}
-
-		Convey("Root", func() {
-			So(ea.Root(c).String(), ShouldEqual, `dev~app::/Attempt,"quest|fffffffe"`)
-		})
-
-		Convey("RollForward", func() {
-			a := &model.Attempt{ID: *ea.ID}
-
-			Convey("Good", func() {
-				So(ds.Get(c, a), ShouldEqual, ds.ErrNoSuchEntity)
-
-				muts, err := ea.RollForward(c)
-				So(err, ShouldBeNil)
-				So(muts, ShouldHaveLength, 1)
-
-				So(ds.Get(c, a), ShouldEqual, nil)
-				So(a.State, ShouldEqual, dm.Attempt_SCHEDULING)
-
-				Convey("replaying the mutation after the state has evolved is a noop", func() {
-					So(a.ModifyState(c, dm.Attempt_EXECUTING), ShouldBeNil)
-					So(ds.Put(c, a), ShouldBeNil)
-
-					muts, err = ea.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeEmpty)
-
-					So(ds.Get(c, a), ShouldEqual, nil)
-					So(a.State, ShouldEqual, dm.Attempt_EXECUTING)
-				})
-			})
-
-			Convey("Bad", func() {
-				c, fb := featureBreaker.FilterRDS(c, nil)
-				fb.BreakFeatures(nil, "GetMulti")
-
-				muts, err := ea.RollForward(c)
-				So(err, ShouldErrLike, `feature "GetMulti" is broken`)
-				So(muts, ShouldBeEmpty)
-
-				fb.UnbreakFeatures("GetMulti")
-
-				So(ds.Get(c, a), ShouldEqual, ds.ErrNoSuchEntity)
-			})
-		})
-	})
-}
diff --git a/dm/appengine/mutate/ensure_quest_attempts.go b/dm/appengine/mutate/ensure_quest_attempts.go
deleted file mode 100644
index 397c307..0000000
--- a/dm/appengine/mutate/ensure_quest_attempts.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// MaxEnsureAttempts limits the maximum number of EnsureAttempt entities that
-// the EnsureQuestAttempts mutation will emit. If there are more AttemptIDs
-// than this maximum, then EnsureQuestAttempts will do tail-recursion to process
-// the remainder.
-const MaxEnsureAttempts = 10
-
-// EnsureQuestAttempts ensures that the given Attempt exists. If it doesn't, it's
-// created in a NeedsExecution state.
-type EnsureQuestAttempts struct {
-	Quest *model.Quest
-	AIDs  []uint32
-
-	// DoNotMergeQuest causes this mutation to not attempt to merge the BuiltBy of
-	// Quest.
-	DoNotMergeQuest bool
-}
-
-// Root implements tumble.Mutation.
-func (e *EnsureQuestAttempts) Root(c context.Context) *datastore.Key {
-	return model.QuestKeyFromID(c, e.Quest.ID)
-}
-
-// RollForward implements tumble.Mutation.
-func (e *EnsureQuestAttempts) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	if !e.DoNotMergeQuest {
-		if _, err = (&MergeQuest{Quest: e.Quest}).RollForward(c); err != nil {
-			return
-		}
-	}
-
-	if len(e.AIDs) > 0 {
-		lim := len(e.AIDs)
-		if lim > MaxEnsureAttempts {
-			lim = MaxEnsureAttempts + 1
-		}
-		muts = make([]tumble.Mutation, 0, lim)
-		for i, aid := range e.AIDs {
-			if i > MaxEnsureAttempts {
-				muts = append(muts, &EnsureQuestAttempts{e.Quest, e.AIDs[i:], true})
-				break
-			}
-			muts = append(muts, &EnsureAttempt{dm.NewAttemptID(e.Quest.ID, aid)})
-		}
-	}
-
-	return
-}
-
-func init() {
-	tumble.Register((*EnsureQuestAttempts)(nil))
-}
diff --git a/dm/appengine/mutate/ensure_quest_attempts_test.go b/dm/appengine/mutate/ensure_quest_attempts_test.go
deleted file mode 100644
index d8551e5..0000000
--- a/dm/appengine/mutate/ensure_quest_attempts_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"testing"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-
-	//. "go.chromium.org/luci/common/testing/assertions"
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestEnsureQuestAttempts(t *testing.T) {
-	t.Parallel()
-
-	Convey("EnsureQuestAttempts", t, func() {
-		ttest := &tumble.Testing{}
-		c := ttest.Context()
-
-		desc := dm.NewQuestDesc("distributor", `{"data":"yes"}`, "{}", nil)
-		So(desc.Normalize(), ShouldBeNil)
-		qst := model.NewQuest(c, desc)
-
-		eqa := EnsureQuestAttempts{qst, []uint32{1, 2, 3, 4}, false}
-
-		Convey("root", func() {
-			So(eqa.Root(c), ShouldResemble, ds.MakeKey(c, "Quest", qst.ID))
-		})
-
-		Convey("quest dne", func() {
-			muts, err := eqa.RollForward(c)
-			So(err, ShouldBeNil)
-			So(muts, ShouldResemble, []tumble.Mutation{
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 1)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 2)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 3)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 4)},
-			})
-		})
-
-		Convey("tail recursion", func() {
-			eqa.AIDs = append(eqa.AIDs, []uint32{5, 6, 7, 8, 9, 10, 11, 12}...)
-			muts, err := eqa.RollForward(c)
-			So(err, ShouldBeNil)
-			So(muts, ShouldResemble, []tumble.Mutation{
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 1)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 2)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 3)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 4)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 5)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 6)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 7)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 8)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 9)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 10)},
-				&EnsureAttempt{dm.NewAttemptID(qst.ID, 11)},
-				&EnsureQuestAttempts{qst, []uint32{12}, true},
-			})
-		})
-	})
-}
diff --git a/dm/appengine/mutate/filter_existing.go b/dm/appengine/mutate/filter_existing.go
deleted file mode 100644
index dd196fc..0000000
--- a/dm/appengine/mutate/filter_existing.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-)
-
-// filterExisting removes the FwdDep objects which already exist.
-//
-// returns gRPC code error.
-func filterExisting(c context.Context, fwdDeps []*model.FwdDep) ([]*model.FwdDep, error) {
-	ret := make([]*model.FwdDep, 0, len(fwdDeps))
-
-	err := ds.Get(c, fwdDeps)
-	if err == nil {
-		return nil, nil
-	}
-
-	merr, ok := err.(errors.MultiError)
-	if !ok {
-		return nil, err
-	}
-
-	for i, err := range merr {
-		if err == nil {
-			continue
-		}
-		ret = append(ret, fwdDeps[i])
-	}
-
-	return ret, nil
-}
diff --git a/dm/appengine/mutate/finish_attempt.go b/dm/appengine/mutate/finish_attempt.go
deleted file mode 100644
index 76921a2..0000000
--- a/dm/appengine/mutate/finish_attempt.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"google.golang.org/grpc/codes"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/grpc/grpcutil"
-	"go.chromium.org/luci/tumble"
-)
-
-// FinishAttempt does a couple things:
-//   Invalidates the current Execution
-//   Moves the state to Finished
-//   Creates a new AttemptResult
-//   Starts RecordCompletion state machine.
-type FinishAttempt struct {
-	dm.FinishAttemptReq
-}
-
-// Root implements tumble.Mutation
-func (f *FinishAttempt) Root(c context.Context) *ds.Key {
-	return model.AttemptKeyFromID(c, f.Auth.Id.AttemptID())
-}
-
-// RollForward implements tumble.Mutation
-//
-// This mutation is called directly from FinishAttempt.
-func (f *FinishAttempt) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	atmpt, ex, err := model.InvalidateExecution(c, f.Auth)
-	if err != nil {
-		logging.WithError(err).Errorf(c, "could not invalidate execution")
-		return
-	}
-
-	if err = ResetExecutionTimeout(c, ex); err != nil {
-		logging.WithError(err).Errorf(c, "could not reset timeout")
-		return
-	}
-
-	ar := &model.AttemptResult{
-		Attempt: model.AttemptKeyFromID(c, &atmpt.ID),
-		Data:    *f.Data,
-	}
-
-	rslt := *f.Data
-	atmpt.Result.Data = &rslt
-	atmpt.Result.Data.Object = ""
-
-	err = errors.Annotate(ds.Put(c, atmpt, ar), "during Put").Tag(grpcutil.Tag.With(codes.Internal)).Err()
-	return
-}
-
-func init() {
-	tumble.Register((*FinishAttempt)(nil))
-}
diff --git a/dm/appengine/mutate/finish_attempt_test.go b/dm/appengine/mutate/finish_attempt_test.go
deleted file mode 100644
index 0534a45..0000000
--- a/dm/appengine/mutate/finish_attempt_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"testing"
-
-	"go.chromium.org/luci/common/clock/testclock"
-	"go.chromium.org/luci/common/logging/memlogger"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestFinishAttempt(t *testing.T) {
-	t.Parallel()
-
-	Convey("FinishAttempt", t, func() {
-		c := memory.Use(context.Background())
-		fa := &FinishAttempt{
-			dm.FinishAttemptReq{
-				Auth: &dm.Execution_Auth{
-					Id:    dm.NewExecutionID("quest", 1, 1),
-					Token: []byte("exekey"),
-				},
-				Data: dm.NewJsonResult(`{"result": true}`, testclock.TestTimeUTC),
-			},
-		}
-
-		So(fa.Normalize(), ShouldBeNil)
-
-		Convey("Root", func() {
-			So(fa.Root(c).String(), ShouldEqual, `dev~app::/Attempt,"quest|fffffffe"`)
-		})
-
-		Convey("RollForward", func() {
-			a := &model.Attempt{
-				ID:           *fa.Auth.Id.AttemptID(),
-				State:        dm.Attempt_EXECUTING,
-				CurExecution: 1,
-			}
-			ak := ds.KeyForObj(c, a)
-			ar := &model.AttemptResult{Attempt: ak}
-			e := &model.Execution{
-				ID: 1, Attempt: ak, State: dm.Execution_RUNNING, Token: []byte("exekey")}
-
-			So(ds.Put(c, a, e), ShouldBeNil)
-
-			Convey("Good", func() {
-				muts, err := fa.RollForward(c)
-				memlogger.MustDumpStdout(c)
-				So(err, ShouldBeNil)
-				So(muts, ShouldBeEmpty)
-
-				So(ds.Get(c, a, e, ar), ShouldBeNil)
-				So(e.Token, ShouldBeEmpty)
-				So(a.Result.Data.Expiration.AsTime(), ShouldResemble, testclock.TestTimeUTC)
-				So(ar.Data.Object, ShouldResemble, `{"result":true}`)
-			})
-
-			Convey("Bad ExecutionKey", func() {
-				fa.Auth.Token = []byte("wat")
-				_, err := fa.RollForward(c)
-				So(err, ShouldBeRPCPermissionDenied, "execution Auth")
-
-				So(ds.Get(c, a, e), ShouldBeNil)
-				So(e.Token, ShouldNotBeEmpty)
-				So(a.State, ShouldEqual, dm.Attempt_EXECUTING)
-
-				So(ds.Get(c, ar), ShouldEqual, ds.ErrNoSuchEntity)
-			})
-
-		})
-	})
-}
diff --git a/dm/appengine/mutate/finish_execution.go b/dm/appengine/mutate/finish_execution.go
deleted file mode 100644
index 162c7e1..0000000
--- a/dm/appengine/mutate/finish_execution.go
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"fmt"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/tumble"
-)
-
-// FinishExecution records the final state of the Execution, and advances the
-// Attempt state machine.
-type FinishExecution struct {
-	EID    *dm.Execution_ID
-	Result *dm.Result
-}
-
-// Root implements tumble.Mutation
-func (f *FinishExecution) Root(c context.Context) *ds.Key {
-	return model.ExecutionKeyFromID(c, f.EID)
-}
-
-// shouldRetry loads the quest for this attempt, to determine if the attempt can
-// be retried. As a side-effect, it increments the RetryState counter for the
-// indicated failure type.
-//
-// If stat is not a retryable AbnormalFinish_Status, this will panic.
-func shouldRetry(c context.Context, a *model.Attempt, stat dm.AbnormalFinish_Status) (retry bool, err error) {
-	if !stat.CouldRetry() {
-		return
-	}
-	q := model.QuestFromID(a.ID.Quest)
-
-	if err = ds.Get(ds.WithoutTransaction(c), q); err != nil {
-		return
-	}
-	var cur, max uint32
-	switch stat {
-	case dm.AbnormalFinish_FAILED:
-		cur, max = a.RetryState.Failed, q.Desc.Meta.Retry.Failed
-		a.RetryState.Failed++
-	case dm.AbnormalFinish_CRASHED:
-		cur, max = a.RetryState.Crashed, q.Desc.Meta.Retry.Crashed
-		a.RetryState.Crashed++
-	case dm.AbnormalFinish_EXPIRED:
-		cur, max = a.RetryState.Expired, q.Desc.Meta.Retry.Expired
-		a.RetryState.Expired++
-	case dm.AbnormalFinish_TIMED_OUT:
-		cur, max = a.RetryState.TimedOut, q.Desc.Meta.Retry.TimedOut
-		a.RetryState.TimedOut++
-	default:
-		panic(fmt.Errorf("do not know how to retry %q", stat))
-	}
-	retry = cur < max
-	return
-}
-
-// RollForward implements tumble.Mutation
-func (f *FinishExecution) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	a := model.AttemptFromID(f.EID.AttemptID())
-	e := model.ExecutionFromID(c, f.EID)
-
-	if err = ds.Get(c, a, e); err != nil {
-		return
-	}
-
-	if a.State != dm.Attempt_EXECUTING || a.CurExecution != f.EID.Id || e.State.Terminal() {
-		logging.Errorf(c, "EARLY EXIT: %s: %s v %s: terminal: %s", a.State, a.CurExecution, f.EID.Id, e.State.Terminal())
-		return
-	}
-
-	if f.Result.AbnormalFinish == nil && e.State != dm.Execution_STOPPING {
-		f.Result.AbnormalFinish = &dm.AbnormalFinish{
-			Status: dm.AbnormalFinish_FAILED,
-			Reason: fmt.Sprintf("distributor finished execution while it was in the %s state.", e.State),
-		}
-	}
-
-	e.Result = *f.Result
-
-	if ab := e.Result.AbnormalFinish; ab != nil {
-		a.IsAbnormal = true
-		e.IsAbnormal = true
-		if err = e.ModifyState(c, dm.Execution_ABNORMAL_FINISHED); err != nil {
-			return
-		}
-
-		var retry bool
-		if retry, err = shouldRetry(c, a, ab.Status); err != nil {
-			return
-		} else if retry {
-			if err = a.ModifyState(c, dm.Attempt_SCHEDULING); err != nil {
-				return
-			}
-			a.DepMap.Reset()
-			muts = append(muts, &ScheduleExecution{&a.ID})
-		} else {
-			// ran out of retries, or non-retriable error type
-			if err = a.ModifyState(c, dm.Attempt_ABNORMAL_FINISHED); err != nil {
-				return
-			}
-			a.Result.AbnormalFinish = ab
-		}
-	} else {
-		if err = e.ModifyState(c, dm.Execution_FINISHED); err != nil {
-			return
-		}
-		a.LastSuccessfulExecution = uint32(e.ID)
-		a.RetryState.Reset()
-
-		if a.DepMap.Size() > 0 {
-			if a.DepMap.All(true) {
-				if err = a.ModifyState(c, dm.Attempt_SCHEDULING); err != nil {
-					return
-				}
-				a.DepMap.Reset()
-				muts = append(muts, &ScheduleExecution{&a.ID})
-			} else if err = a.ModifyState(c, dm.Attempt_WAITING); err != nil {
-				return
-			}
-		} else {
-			if err = a.ModifyState(c, dm.Attempt_FINISHED); err != nil {
-				return
-			}
-			muts = append(muts, &RecordCompletion{f.EID.AttemptID()})
-		}
-	}
-
-	// best-effort reset execution timeout
-	_ = ResetExecutionTimeout(c, e)
-
-	err = ds.Put(c, a, e)
-	return
-}
-
-// FinishExecutionFn is the implementation of distributor.FinishExecutionFn.
-// It's defined here to avoid a circular dependency.
-func FinishExecutionFn(c context.Context, eid *dm.Execution_ID, rslt *dm.Result) ([]tumble.Mutation, error) {
-	if rslt.Data != nil {
-		if normErr := rslt.Data.Normalize(); normErr != nil {
-			logging.WithError(normErr).Errorf(c, "Could not normalize distributor Result!")
-			rslt = &dm.Result{
-				AbnormalFinish: &dm.AbnormalFinish{
-					Status: dm.AbnormalFinish_RESULT_MALFORMED,
-					Reason: fmt.Sprintf("distributor result malformed: %q in %q", normErr, rslt.Data.Object),
-				},
-			}
-		}
-	}
-
-	return []tumble.Mutation{&FinishExecution{EID: eid, Result: rslt}}, nil
-}
-
-// NewFinishExecutionAbnormal is a shorthand to make a FinishExecution mutation
-// with some abnomal result.
-func NewFinishExecutionAbnormal(eid *dm.Execution_ID, status dm.AbnormalFinish_Status, reason string) *FinishExecution {
-	return &FinishExecution{
-		eid, &dm.Result{
-			AbnormalFinish: &dm.AbnormalFinish{Status: status, Reason: reason}}}
-}
-
-func init() {
-	tumble.Register((*FinishExecution)(nil))
-}
diff --git a/dm/appengine/mutate/merge_quest.go b/dm/appengine/mutate/merge_quest.go
deleted file mode 100644
index bb27948..0000000
--- a/dm/appengine/mutate/merge_quest.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// MergeQuest ensures that the given Quest exists and contains the merged
-// set of BuiltBy entries.
-type MergeQuest struct {
-	Quest   *model.Quest
-	AndThen []tumble.Mutation
-}
-
-// Root implements tumble.Mutation.
-func (m *MergeQuest) Root(c context.Context) *ds.Key {
-	return model.QuestKeyFromID(c, m.Quest.ID)
-}
-
-// RollForward implements tumble.Mutation.
-func (m *MergeQuest) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	curQuest := model.QuestFromID(m.Quest.ID)
-
-	c = logging.SetField(c, "qid", m.Quest.ID)
-
-	reason := "getting quest"
-	switch err = ds.Get(c, curQuest); err {
-	case nil:
-		prevLen := len(curQuest.BuiltBy)
-		curQuest.BuiltBy.Add(m.Quest.BuiltBy...)
-		if len(curQuest.BuiltBy) > prevLen {
-			reason = "putting merged quest"
-			err = ds.Put(c, curQuest)
-		}
-	case ds.ErrNoSuchEntity:
-		reason = "putting quest"
-		err = ds.Put(c, m.Quest)
-	}
-
-	if err != nil {
-		logging.WithError(err).Errorf(c, "%s", reason)
-	}
-
-	muts = m.AndThen
-
-	return
-}
-
-func init() {
-	tumble.Register((*MergeQuest)(nil))
-}
diff --git a/dm/appengine/mutate/merge_quest_test.go b/dm/appengine/mutate/merge_quest_test.go
deleted file mode 100644
index 6fb7030..0000000
--- a/dm/appengine/mutate/merge_quest_test.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"testing"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/filter/featureBreaker"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestMergeQuest(t *testing.T) {
-	t.Parallel()
-
-	Convey("MergeQuest", t, func() {
-		ttest := &tumble.Testing{}
-		c := ttest.Context()
-
-		desc := dm.NewQuestDesc("distributor", `{"data":"yes"}`, "{}", nil)
-		So(desc.Normalize(), ShouldBeNil)
-		qst := model.NewQuest(c, desc)
-		qst.BuiltBy = append(qst.BuiltBy, *dm.NewTemplateSpec("a", "b", "c", "d"))
-
-		mq := &MergeQuest{qst, nil}
-
-		Convey("root", func() {
-			So(mq.Root(c), ShouldResemble, ds.MakeKey(c, "Quest", qst.ID))
-		})
-
-		Convey("quest doesn't exist", func() {
-			muts, err := mq.RollForward(c)
-			So(err, ShouldBeNil)
-			So(muts, ShouldBeEmpty)
-
-			q := &model.Quest{ID: qst.ID}
-			So(ds.Get(c, q), ShouldBeNil)
-			So(q.Equals(qst), ShouldBeTrue)
-		})
-
-		Convey("assuming it exists", func() {
-			So(ds.Put(c, qst), ShouldBeNil)
-			Convey("noop merge", func() {
-				muts, err := mq.RollForward(c)
-				So(err, ShouldBeNil)
-				So(muts, ShouldBeEmpty)
-			})
-
-			Convey("actual merge", func() {
-				ttest.AdvanceTime(c)
-
-				mq.Quest.BuiltBy.Add(*dm.NewTemplateSpec("aa", "bb", "cc", "dd"))
-				muts, err := mq.RollForward(c)
-				So(err, ShouldBeNil)
-				So(muts, ShouldBeEmpty)
-
-				q := &model.Quest{ID: qst.ID}
-				So(ds.Get(c, q), ShouldBeNil)
-				So(len(q.BuiltBy), ShouldEqual, 2)
-				So(q.Created, ShouldResemble, qst.Created)
-			})
-
-			Convey("datastore fail", func() {
-				c, fb := featureBreaker.FilterRDS(c, nil)
-				fb.BreakFeatures(nil, "GetMulti")
-				_, err := mq.RollForward(c)
-				So(err, ShouldBeRPCUnknown)
-			})
-		})
-
-	})
-}
diff --git a/dm/appengine/mutate/record_completion.go b/dm/appengine/mutate/record_completion.go
deleted file mode 100644
index 620733f..0000000
--- a/dm/appengine/mutate/record_completion.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// Attempt to complete attempts 64-at-a-time. Rely on tumble's
-// tail-call optimization to save on transactions.
-const completionLimit = 64
-
-// RecordCompletion marks that fact that an Attempt is completed (Finished) on
-// its corresponding BackDepGroup, and fires off additional AckFwdDep mutations
-// for each incoming dependency that is blocked.
-//
-// In the case where an Attempt has hundreds or thousands of incoming
-// dependencies, the naive implementation of this mutation could easily overfill
-// a single datastore transaction. For that reason, the implementation here
-// unblocks things 64 edges at a time, and keeps returning itself as a mutation
-// until it unblocks less than 64 things (e.g. it does a tail-call).
-//
-// This relies on tumble's tail-call optimization to be performant in terms of
-// the number of transactions, otherwise this would take 1 transaction per
-// 64 dependencies. With the TCO, it could do hundreds or thousands of
-// dependencies, but it will also be fair to other work (e.g. it will allow
-// other Attempts to take dependencies on this Attempt while RecordCompletion
-// is in between tail-calls).
-type RecordCompletion struct {
-	For *dm.Attempt_ID
-}
-
-// Root implements tumble.Mutation.
-func (r *RecordCompletion) Root(c context.Context) *ds.Key {
-	return ds.KeyForObj(c, &model.BackDepGroup{Dependee: *r.For})
-}
-
-// RollForward implements tumble.Mutation.
-func (r *RecordCompletion) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	bdg := &model.BackDepGroup{Dependee: *r.For}
-	if err = ds.Get(c, bdg); err != nil && err != ds.ErrNoSuchEntity {
-		return
-	}
-
-	needProp := make([]*model.BackDep, 0, completionLimit)
-
-	q := (ds.NewQuery("BackDep").
-		Ancestor(ds.KeyForObj(c, bdg)).
-		Eq("Propagated", false).
-		Limit(completionLimit))
-
-	if err = ds.GetAll(c, q, &needProp); err != nil {
-		return
-	}
-
-	if len(needProp) > 0 {
-		muts = make([]tumble.Mutation, len(needProp))
-
-		for i, bdep := range needProp {
-			bdep.Propagated = true
-			muts[i] = &AckFwdDep{bdep.Edge()}
-		}
-
-		if len(needProp) == completionLimit {
-			// Append ourself if there might be more to do!
-			muts = append(muts, r)
-		}
-
-		if err = ds.Put(c, needProp); err != nil {
-			return
-		}
-	}
-
-	if !bdg.AttemptFinished {
-		bdg.AttemptFinished = true
-		if err = ds.Put(c, bdg); err != nil {
-			return
-		}
-	}
-
-	return
-}
-
-func init() {
-	tumble.Register((*RecordCompletion)(nil))
-}
diff --git a/dm/appengine/mutate/record_completion_test.go b/dm/appengine/mutate/record_completion_test.go
deleted file mode 100644
index d29bcae..0000000
--- a/dm/appengine/mutate/record_completion_test.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"testing"
-
-	"go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/model"
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestRecordCompletion(t *testing.T) {
-	t.Parallel()
-
-	Convey("RecordCompletion", t, func() {
-		c := memory.Use(context.Background())
-		rc := &RecordCompletion{dm.NewAttemptID("quest", 1)}
-
-		bdg := &model.BackDepGroup{Dependee: *rc.For}
-
-		Convey("Root", func() {
-			So(rc.Root(c).String(), ShouldEqual, `dev~app::/BackDepGroup,"quest|fffffffe"`)
-		})
-
-		Convey("RollForward", func() {
-
-			Convey("Good", func() {
-				Convey("No BDG", func() {
-					muts, err := rc.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeEmpty)
-
-					So(ds.Get(c, bdg), ShouldBeNil)
-					So(bdg.AttemptFinished, ShouldBeTrue)
-				})
-
-				Convey("BDG exists, no deps", func() {
-					So(ds.Put(c, bdg), ShouldBeNil)
-
-					muts, err := rc.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeEmpty)
-
-					So(ds.Get(c, bdg), ShouldBeNil)
-					So(bdg.AttemptFinished, ShouldBeTrue)
-				})
-
-				Convey("BDG exists, with unfinished deps", func() {
-					bd := &model.BackDep{
-						Depender:      *dm.NewAttemptID("from", 1),
-						DependeeGroup: rc.Root(c),
-					}
-					So(ds.Put(c, bdg, bd), ShouldBeNil)
-
-					muts, err := rc.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldResemble, []tumble.Mutation{&AckFwdDep{bd.Edge()}})
-
-					So(ds.Get(c, bdg, bd), ShouldBeNil)
-					So(bdg.AttemptFinished, ShouldBeTrue)
-					So(bd.Propagated, ShouldBeTrue)
-				})
-
-				Convey("BDG exists, with finished deps", func() {
-					bd := &model.BackDep{
-						Depender:      *dm.NewAttemptID("from", 1),
-						DependeeGroup: rc.Root(c),
-						Propagated:    true,
-					}
-					So(ds.Put(c, bdg, bd), ShouldBeNil)
-
-					muts, err := rc.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeEmpty)
-
-					So(ds.Get(c, bdg, bd), ShouldBeNil)
-					So(bdg.AttemptFinished, ShouldBeTrue)
-					So(bd.Propagated, ShouldBeTrue)
-				})
-
-				Convey("BDG exists, but too much to do in one TXN!", func() {
-					// amtWork is 1.5*completionLimit
-					amtWork := completionLimit + (completionLimit >> 1)
-
-					for i := 0; i < amtWork; i++ {
-						bd := &model.BackDep{
-							Depender:      *dm.NewAttemptID("from", 0),
-							DependeeGroup: rc.Root(c),
-						}
-						bd.Depender.Id = uint32(i + 1)
-						So(ds.Put(c, bd), ShouldBeNil)
-					}
-					So(ds.Put(c, bdg), ShouldBeNil)
-
-					muts, err := rc.RollForward(c)
-					So(err, ShouldBeNil)
-					So(len(muts), ShouldEqual, completionLimit+1)
-
-					So(muts[completionLimit], ShouldResemble, rc)
-
-					muts, err = rc.RollForward(c)
-					So(err, ShouldBeNil)
-					So(len(muts), ShouldEqual, amtWork-completionLimit)
-
-					muts, err = rc.RollForward(c)
-					So(err, ShouldBeNil)
-					So(muts, ShouldBeEmpty)
-				})
-			})
-		})
-	})
-}
diff --git a/dm/appengine/mutate/schedule_execution.go b/dm/appengine/mutate/schedule_execution.go
deleted file mode 100644
index fc60125..0000000
--- a/dm/appengine/mutate/schedule_execution.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"fmt"
-
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/retry/transient"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// ScheduleExecution is a placeholder mutation that will be an entry into the
-// Distributor scheduling state-machine.
-type ScheduleExecution struct {
-	For *dm.Attempt_ID
-}
-
-// Root implements tumble.Mutation
-func (s *ScheduleExecution) Root(c context.Context) *ds.Key {
-	return model.AttemptKeyFromID(c, s.For)
-}
-
-// RollForward implements tumble.Mutation
-func (s *ScheduleExecution) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	a := model.AttemptFromID(s.For)
-	if err = ds.Get(c, a); err != nil {
-		logging.WithError(err).Errorf(c, "loading attempt")
-		return
-	}
-
-	if a.State != dm.Attempt_SCHEDULING {
-		logging.Infof(c, "EARLY EXIT: already scheduling")
-		return
-	}
-
-	q := model.QuestFromID(s.For.Quest)
-	if err = ds.Get(ds.WithoutTransaction(c), q); err != nil {
-		logging.WithError(err).Errorf(c, "loading quest")
-		return
-	}
-
-	prevResult := (*dm.JsonResult)(nil)
-	if a.LastSuccessfulExecution != 0 {
-		prevExecution := model.ExecutionFromID(c, s.For.Execution(a.LastSuccessfulExecution))
-		if err = ds.Get(c, prevExecution); err != nil {
-			logging.Errorf(c, "loading previous execution: %s", err)
-			return
-		}
-		prevResult = prevExecution.Result.Data
-	}
-
-	reg := distributor.GetRegistry(c)
-	dist, ver, err := reg.MakeDistributor(c, q.Desc.DistributorConfigName)
-	if err != nil {
-		logging.WithError(err).Errorf(c, "making distributor %s", q.Desc.DistributorConfigName)
-		return
-	}
-
-	a.CurExecution++
-	if err = a.ModifyState(c, dm.Attempt_EXECUTING); err != nil {
-		logging.WithError(err).Errorf(c, "modifying state")
-		return
-	}
-
-	eid := dm.NewExecutionID(s.For.Quest, s.For.Id, a.CurExecution)
-	e := model.MakeExecution(c, eid, q.Desc.DistributorConfigName, ver)
-	e.TimeToStart = q.Desc.Meta.Timeouts.Start.AsDuration()
-	e.TimeToRun = q.Desc.Meta.Timeouts.Run.AsDuration()
-
-	exAuth := &dm.Execution_Auth{Id: eid, Token: e.Token}
-
-	var distTok distributor.Token
-	distTok, e.TimeToStop, err = dist.Run(&q.Desc, exAuth, prevResult)
-	if e.TimeToStop <= 0 {
-		e.TimeToStop = q.Desc.Meta.Timeouts.Stop.AsDuration()
-	}
-	e.DistributorToken = string(distTok)
-	if err != nil {
-		if transient.Tag.In(err) {
-			// tumble will retry us later
-			logging.WithError(err).Errorf(c, "got transient error in ScheduleExecution")
-			return
-		}
-		logging.WithError(err).Errorf(c, "got non-transient error in ScheduleExecution")
-		origErr := err
-
-		// put a and e to the transaction buffer, so that
-		// FinishExecution.RollForward can see them.
-		if err = ds.Put(c, a, e); err != nil {
-			logging.WithError(err).Errorf(c, "putting attempt+execution for non-transient distributor error")
-			return
-		}
-		return NewFinishExecutionAbnormal(
-			eid, dm.AbnormalFinish_REJECTED,
-			fmt.Sprintf("rejected during scheduling with non-transient error: %s", origErr),
-		).RollForward(c)
-	}
-
-	if err = ResetExecutionTimeout(c, e); err != nil {
-		logging.WithError(err).Errorf(c, "resetting timeout")
-		return
-	}
-
-	if err = ds.Put(c, a, e); err != nil {
-		logging.WithError(err).Errorf(c, "putting attempt+execution")
-	}
-
-	return
-}
-
-func init() {
-	tumble.Register((*ScheduleExecution)(nil))
-}
diff --git a/dm/appengine/mutate/schedule_execution_test.go b/dm/appengine/mutate/schedule_execution_test.go
deleted file mode 100644
index 0ce4908..0000000
--- a/dm/appengine/mutate/schedule_execution_test.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"fmt"
-	"testing"
-	"time"
-
-	"google.golang.org/protobuf/types/known/durationpb"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/retry/transient"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor/fake"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestScheduleExecution(t *testing.T) {
-	t.Parallel()
-
-	Convey("ScheduleExecution", t, func() {
-		_, c, dist := fake.Setup(FinishExecutionFn)
-
-		qdesc := fake.QuestDesc("quest")
-		qdesc.Meta.Timeouts.Start = durationpb.New(time.Minute * 5)
-		qid := qdesc.QuestID()
-		se := &ScheduleExecution{dm.NewAttemptID(qid, 1)}
-
-		Convey("Root", func() {
-			So(se.Root(c).String(), ShouldEqual, fmt.Sprintf(`dev~app::/Attempt,"%s|fffffffe"`, qid))
-		})
-
-		Convey("RollForward", func() {
-			q := &model.Quest{ID: qid, Desc: *qdesc}
-			a := &model.Attempt{
-				ID:    *se.For,
-				State: dm.Attempt_SCHEDULING,
-			}
-			e := model.ExecutionFromID(c, dm.NewExecutionID(qid, 1, 1))
-			So(ds.Put(c, q, a), ShouldBeNil)
-
-			Convey("basic", func() {
-				muts, err := se.RollForward(c)
-				So(err, ShouldBeNil)
-				So(muts, ShouldBeNil)
-
-				So(ds.Get(c, a, e), ShouldBeNil)
-				Convey("distributor information is saved", func() {
-					tok := fake.MakeToken(dm.NewExecutionID(qid, 1, 1))
-
-					So(a.State, ShouldEqual, dm.Attempt_EXECUTING)
-					So(e.State, ShouldEqual, dm.Execution_SCHEDULING)
-					So(e.DistributorConfigName, ShouldEqual, "fakeDistributor")
-					So(e.DistributorToken, ShouldEqual, tok)
-					So(e.DistributorConfigVersion, ShouldEqual, "testing")
-					So(e.TimeToStart, ShouldEqual, time.Minute*5)
-				})
-				Convey("a timeout is set", func() {
-					ex, err := ds.Exists(c, ds.MakeKey(c,
-						"Attempt", a.ID.DMEncoded(),
-						"Execution", 1,
-						"tumble.Mutation", "n:timeout"))
-					So(err, ShouldBeNil)
-					So(ex.All(), ShouldBeTrue)
-				})
-			})
-
-			Convey("transient", func() {
-				dist.RunError = errors.New("transient failure", transient.Tag)
-
-				muts, err := se.RollForward(c)
-				So(err, ShouldErrLike, "transient")
-				So(muts, ShouldBeNil)
-			})
-
-			Convey("rejection", func() {
-				dist.RunError = errors.New("no soup for you")
-
-				muts, err := se.RollForward(c)
-				So(err, ShouldBeNil)
-				So(muts, ShouldBeNil)
-
-				So(ds.Get(c, a, e), ShouldBeNil)
-				So(a.State, ShouldEqual, dm.Attempt_ABNORMAL_FINISHED)
-				So(a.Result.AbnormalFinish.Status, ShouldEqual, dm.AbnormalFinish_REJECTED)
-				So(a.Result.AbnormalFinish.Reason, ShouldContainSubstring, "non-transient")
-
-				So(e.State, ShouldEqual, dm.Execution_ABNORMAL_FINISHED)
-				So(e.Result.AbnormalFinish.Status, ShouldEqual, dm.AbnormalFinish_REJECTED)
-				So(e.Result.AbnormalFinish.Reason, ShouldContainSubstring, "non-transient")
-			})
-
-		})
-	})
-}
diff --git a/dm/appengine/mutate/timeout_execution.go b/dm/appengine/mutate/timeout_execution.go
deleted file mode 100644
index fa659f7..0000000
--- a/dm/appengine/mutate/timeout_execution.go
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mutate
-
-import (
-	"context"
-	"fmt"
-	"time"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/dm/appengine/distributor"
-	"go.chromium.org/luci/dm/appengine/model"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/tumble"
-)
-
-// TimeoutExecution is a named mutation which triggers on a delay. If the
-// execution is in the noted state when the trigger hits, this sets the
-// Execution to have an AbnormalFinish status of TIMED_OUT.
-type TimeoutExecution struct {
-	For   *dm.Execution_ID
-	State dm.Execution_State
-	// TimeoutAttempt is the number of attempts to stop a STOPPING execution,
-	// since this potentially requires an RPC to the distributor to enact.
-	TimeoutAttempt uint
-	Deadline       time.Time
-}
-
-const maxTimeoutAttempts = 3
-
-var _ tumble.DelayedMutation = (*TimeoutExecution)(nil)
-
-// Root implements tumble.Mutation
-func (t *TimeoutExecution) Root(c context.Context) *ds.Key {
-	return model.AttemptKeyFromID(c, t.For.AttemptID())
-}
-
-// RollForward implements tumble.Mutation
-func (t *TimeoutExecution) RollForward(c context.Context) (muts []tumble.Mutation, err error) {
-	e := model.ExecutionFromID(c, t.For)
-
-	if err = ds.Get(c, e); err != nil {
-		return
-	}
-	if e.State != t.State {
-		logging.Errorf(c, "EARLY EXIT: %s v %s", e.State, t.State)
-		return
-	}
-
-	// will be overwritten if this execution is STOPPING and the timeout is not
-	// abnormal
-	rslt := &dm.Result{AbnormalFinish: &dm.AbnormalFinish{
-		Reason: fmt.Sprintf("DM timeout (%s)", e.State),
-		Status: dm.AbnormalFinish_TIMED_OUT}}
-
-	if e.State == dm.Execution_STOPPING {
-		// if it's supposed to be STOPPING, maybe we just missed a notification from
-		// the distributor (or the distributor is not using pubsub).
-		reg := distributor.GetRegistry(c)
-		var dist distributor.D
-		var vers string
-		dist, vers, err = reg.MakeDistributor(c, e.DistributorConfigName)
-
-		if vers != "" && vers != e.DistributorConfigVersion {
-			logging.Fields{
-				"cfg_name":      e.DistributorConfigName,
-				"orig_cfg_vers": e.DistributorConfigVersion,
-				"cur_cfg_vers":  vers,
-			}.Warningf(c, "mismatched distributor config versions")
-		}
-
-		// TODO(iannucci): make this set the REJECTED state if we loaded the config,
-		// but the distributor no longer exists.
-		if err != nil {
-			logging.Fields{
-				logging.ErrorKey: err,
-				"cfgName":        e.DistributorConfigName,
-			}.Errorf(c, "Could not MakeDistributor")
-			return
-		}
-		var realRslt *dm.Result
-		q := model.QuestFromID(t.For.Quest)
-		if err = ds.Get(ds.WithoutTransaction(c), q); err != nil {
-			err = errors.Annotate(err, "loading quest").Err()
-			return
-		}
-		realRslt, err = dist.GetStatus(&q.Desc, distributor.Token(e.DistributorToken))
-		if (err != nil || realRslt == nil) && t.TimeoutAttempt < maxTimeoutAttempts {
-			logging.Fields{
-				logging.ErrorKey:  err,
-				"task_result":     realRslt,
-				"timeout_attempt": t.TimeoutAttempt,
-			}.Infof(c, "GetStatus failed/nop'd while timing out STOPPING execution")
-			// TODO(riannucci): do randomized exponential backoff instead of constant
-			// backoff? Kinda don't really want to spend more than 1.5m waiting
-			// anyway, and the actual GetStatus call does local retries already, so
-			// hopefully this is fine. If this is wrong, the distributor should adjust
-			// its timeToStop value to be better.
-			t.Deadline = t.Deadline.Add(time.Second * 30)
-			t.TimeoutAttempt++
-			err = nil
-			muts = append(muts, t)
-			return
-		}
-
-		if err != nil {
-			rslt.AbnormalFinish.Reason = fmt.Sprintf("DM timeout (%s) w/ error: %s", e.State, err)
-			err = nil
-		} else if realRslt != nil {
-			rslt = realRslt
-		}
-	}
-
-	muts = append(muts, &FinishExecution{t.For, rslt})
-	return
-}
-
-// ProcessAfter implements tumble.DelayedMutation
-func (t *TimeoutExecution) ProcessAfter() time.Time { return t.Deadline }
-
-// HighPriority implements tumble.DelayedMutation
-func (t *TimeoutExecution) HighPriority() bool { return false }
-
-// ResetExecutionTimeout schedules a Timeout for this Execution. It inspects the
-// Execution's State to determine which timeout should be set, if any. If no
-// timeout should be active, this will cancel any existing timeouts for this
-// Execution.
-func ResetExecutionTimeout(c context.Context, e *model.Execution) error {
-	howLong := time.Duration(0)
-	switch e.State {
-	case dm.Execution_SCHEDULING:
-		howLong = e.TimeToStart
-	case dm.Execution_RUNNING:
-		howLong = e.TimeToRun
-	case dm.Execution_STOPPING:
-		howLong = e.TimeToStop
-	}
-	eid := e.GetEID()
-	key := model.ExecutionKeyFromID(c, eid)
-	if howLong == 0 {
-		return tumble.CancelNamedMutations(c, key, "timeout")
-	}
-	return tumble.PutNamedMutations(c, key, map[string]tumble.Mutation{
-		"timeout": &TimeoutExecution{eid, e.State, 0, clock.Now(c).UTC().Add(howLong)},
-	})
-}
-
-func init() {
-	tumble.Register((*TimeoutExecution)(nil))
-}
diff --git a/dm/appengine/notes b/dm/appengine/notes
deleted file mode 100644
index 1a81e10..0000000
--- a/dm/appengine/notes
+++ /dev/null
@@ -1,4 +0,0 @@
-Add queue support
-
-Add search support
-  * See dm.GraphQuery_Search
diff --git a/dm/appengine/static/.gcloudignore b/dm/appengine/static/.gcloudignore
deleted file mode 100644
index cd43ed5..0000000
--- a/dm/appengine/static/.gcloudignore
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file specifies files that are *not* uploaded to Google Cloud Platform
-# using gcloud. It follows the same syntax as .gitignore, with the addition of
-# "#!include" directives (which insert the entries of the given .gitignore-style
-# file at that point).
-#
-# For more information, run:
-#   $ gcloud topic gcloudignore
-
-.gcloudignore
-.gitignore
diff --git a/dm/appengine/static/main.go b/dm/appengine/static/main.go
deleted file mode 100644
index c2f69bb..0000000
--- a/dm/appengine/static/main.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"google.golang.org/appengine"
-)
-
-func main() {
-	appengine.Main()
-}
diff --git a/dm/appengine/static/rpcexplorer b/dm/appengine/static/rpcexplorer
deleted file mode 120000
index 99e5946..0000000
--- a/dm/appengine/static/rpcexplorer
+++ /dev/null
@@ -1 +0,0 @@
-../../../web/dist/rpcexplorer
\ No newline at end of file
diff --git a/dm/appengine/static/service-static.yaml b/dm/appengine/static/service-static.yaml
deleted file mode 100644
index 29f4906..0000000
--- a/dm/appengine/static/service-static.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-service: static
-runtime: go111
-
-handlers:
-- url: /rpcexplorer/?
-  static_files: rpcexplorer/index.html
-  upload: rpcexplorer/index.html
-  secure: always
-
-# The entire subpath is globbed because RPC Explorer uses native URL redirecting
-# for sub-pages, and we want all of them to map to the same HTML file.
-- url: /rpcexplorer/services/.*
-  static_files: rpcexplorer/index.html
-  upload: rpcexplorer/index.html
-  secure: always
-
-- url: /rpcexplorer
-  static_dir: rpcexplorer
-  secure: always
diff --git a/dm/doc.go b/dm/doc.go
deleted file mode 100644
index 6977ccd..0000000
--- a/dm/doc.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package dm is the service and tooling for the Dungeon Master (DM) distributed
-// dependency scheduling service.
-//
-// For more information on DM itself, check out https://go.chromium.org/luci/wiki/Design-Documents
-package dm
diff --git a/dm/tools/dmtool/example.dot b/dm/tools/dmtool/example.dot
deleted file mode 100644
index 0d0b8ec..0000000
--- a/dm/tools/dmtool/example.dot
+++ /dev/null
@@ -1,21 +0,0 @@
-digraph {
-  subgraph cluster_q1 {
-    style=dashed
-    label="query1"
-
-    subgraph cluster_α {
-      style=solid
-
-      label=α
-      "α:1" [style=solid label="1"]
-      "α:2" [style=solid label="2"]
-    }
-
-    subgraph cluster_q2 {
-      style=dashed
-      "β:1" [ style=solid ]
-    }
-  }
-
-  "α:1" -> "β:1"
-}
diff --git a/dm/tools/dmtool/hashQuest.go b/dm/tools/dmtool/hashQuest.go
deleted file mode 100644
index b6ba7db..0000000
--- a/dm/tools/dmtool/hashQuest.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"fmt"
-	"os"
-
-	"github.com/golang/protobuf/jsonpb"
-	"github.com/maruel/subcommands"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-var cmdHashQuest = &subcommands.Command{
-	UsageLine: `hash [options]`,
-	ShortDesc: "Produces a DM-compliant QuestID",
-	LongDesc: `This command generates a DM QuestID from all the components of a
-	DM Quest Description. The description must be supplied via STDIN
-	in the form of JSONPB.`,
-	CommandRun: func() subcommands.CommandRun {
-		r := &hashQuestRun{}
-		r.registerOptions()
-		return r
-	},
-}
-
-type hashQuestRun struct {
-	cmdRun
-}
-
-func (r *hashQuestRun) registerOptions() {
-}
-
-func (r *hashQuestRun) Run(a subcommands.Application, args []string, _ subcommands.Env) int {
-	r.cmd = cmdHashQuest
-
-	if len(args) > 0 {
-		return r.argErr("found %d extra arguments", len(args))
-	}
-
-	desc := &dm.Quest_Desc{}
-	err := jsonpb.Unmarshal(os.Stdin, desc)
-	if err != nil {
-		return r.argErr("failed to unmarshal dm.Quest.Desc: %s", err)
-	}
-
-	if err := desc.Normalize(); err != nil {
-		return r.argErr("failed to normalize dm.Quest.Desc: %s", err)
-	}
-
-	fmt.Println(desc.QuestID())
-	return 0
-}
diff --git a/dm/tools/dmtool/main.go b/dm/tools/dmtool/main.go
deleted file mode 100644
index 5d1823e..0000000
--- a/dm/tools/dmtool/main.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-
-	"github.com/maruel/subcommands"
-
-	"go.chromium.org/luci/common/cli"
-	"go.chromium.org/luci/common/logging/gologger"
-)
-
-// cmdRun is a base of all rpc subcommands.
-type cmdRun struct {
-	subcommands.CommandRunBase
-	cmd *subcommands.Command
-}
-
-var logCfg = gologger.LoggerConfig{
-	Format: `%{message}`,
-	Out:    os.Stderr,
-}
-
-// argErr prints an err and usage to stderr and returns an exit code.
-func (r *cmdRun) argErr(format string, a ...interface{}) int {
-	if format != "" {
-		fmt.Fprintf(os.Stderr, format+"\n", a...)
-	}
-	fmt.Fprintln(os.Stderr, r.cmd.ShortDesc)
-	fmt.Fprintln(os.Stderr, r.cmd.UsageLine)
-	fmt.Fprintln(os.Stderr, "\nFlags:")
-	r.Flags.PrintDefaults()
-	return -1
-}
-
-var application = &cli.Application{
-	Name:  "dmtool",
-	Title: "Dungeon Master CLI tool",
-	Context: func(ctx context.Context) context.Context {
-		return logCfg.Use(ctx)
-	},
-	Commands: []*subcommands.Command{
-		cmdHashQuest,
-		cmdVisQuery,
-		subcommands.CmdHelp,
-	},
-}
-
-func main() {
-	os.Exit(subcommands.Run(application, os.Args[1:]))
-}
diff --git a/dm/tools/dmtool/uint32Flag.go b/dm/tools/dmtool/uint32Flag.go
deleted file mode 100644
index 083b2f3..0000000
--- a/dm/tools/dmtool/uint32Flag.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"flag"
-	"strconv"
-)
-
-type uint32Flag uint32
-
-func (f *uint32Flag) Set(s string) error {
-	v, err := strconv.ParseUint(s, 10, 32)
-	if err != nil {
-		return err
-	}
-	*f = uint32Flag((uint32)(v))
-	return nil
-}
-
-func (f *uint32Flag) String() string {
-	return strconv.FormatUint(uint64(*f), 10)
-}
-
-var _ flag.Value = (*uint32Flag)(nil)
diff --git a/dm/tools/dmtool/vizQuery.go b/dm/tools/dmtool/vizQuery.go
deleted file mode 100644
index f02c890..0000000
--- a/dm/tools/dmtool/vizQuery.go
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"bytes"
-	"context"
-	"fmt"
-	"os"
-	"os/exec"
-	"os/signal"
-	"sort"
-	"strings"
-	"sync"
-	"time"
-
-	"github.com/maruel/subcommands"
-	"google.golang.org/protobuf/proto"
-
-	"go.chromium.org/luci/client/flagpb"
-	"go.chromium.org/luci/common/cli"
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/lhttp"
-	"go.chromium.org/luci/common/logging"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/grpc/prpc"
-)
-
-var cmdVisQuery = &subcommands.Command{
-	UsageLine: `vis [options] [args for rpc command]`,
-	ShortDesc: "Runs a DM WalkGraph query and visualizes the result to a .dot file.",
-	LongDesc: `This command runs a WalkGraph query repeatedly, overwriting the .dot
-	file specified with a visual representation of the graph.`,
-	CommandRun: func() subcommands.CommandRun {
-		r := &visQueryRun{}
-		r.registerOptions()
-		return r
-	},
-}
-
-type visQueryRun struct {
-	cmdRun
-	host       string
-	path       string
-	sequence   bool
-	includeAll bool
-}
-
-func (r *visQueryRun) registerOptions() {
-	r.Flags.StringVar(&r.host, "host", ":8080",
-		"The host to connect to")
-	r.Flags.StringVar(&r.path, "path", "",
-		"The output path for the .dot file. Leave empty to query once and print the result stdout.")
-	r.Flags.BoolVar(&r.sequence, "sequence", false,
-		"Use `path` as the base path for a sequence of pngs. `path` must not be empty.")
-	r.Flags.BoolVar(&r.includeAll, "include-all", false,
-		"Modify query to have all 'Include' options.")
-}
-
-var alphabet = []rune{
-	// lower greek
-	'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο',
-	'π', 'ρ', 'ς', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω',
-
-	// lower english
-	//'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-	//'q', 'r', 's', 't', 'w', 'y', 'z',
-
-	// upper greek
-	'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο',
-	'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω',
-
-	// upper english
-	//'C', 'D', 'F', 'G', 'J', 'L', 'Q', 'R', 'S', 'U', 'V', 'W',
-}
-
-type name uint
-
-var alphabetLen = name(len(alphabet))
-
-func (n name) runes() []rune {
-	if n < alphabetLen {
-		return alphabet[n : n+1]
-	}
-	return append((n/alphabetLen - 1).runes(), alphabet[n%alphabetLen])
-}
-
-func (n name) String() string {
-	return string(n.runes())
-}
-
-var alphabetLock = sync.Mutex{}
-var curAlphabetName = name(0)
-var alphabetMap = map[string]name{}
-
-func getColor(a *dm.Attempt) string {
-	switch a.Data.State() {
-	case dm.Attempt_SCHEDULING:
-		return "cadetblue1"
-	case dm.Attempt_EXECUTING:
-		return "darkorchid"
-	case dm.Attempt_WAITING:
-		return "gold"
-	case dm.Attempt_FINISHED:
-		return "chartreuse"
-	case dm.Attempt_ABNORMAL_FINISHED:
-		return "crimson"
-	}
-	return "deeppink"
-}
-
-func nameFor(qid string) string {
-	alphabetLock.Lock()
-	defer alphabetLock.Lock()
-	if curName, ok := alphabetMap[qid]; ok {
-		return curName.String()
-	}
-	ret := curAlphabetName
-	alphabetMap[qid] = ret
-	curAlphabetName++
-	return ret.String()
-}
-
-func renderDotFile(gdata *dm.GraphData) string {
-	buf := &bytes.Buffer{}
-
-	indent := 0
-	idt := func() string { return strings.Repeat(" ", indent) }
-	p := func(format string, args ...interface{}) {
-		indent -= strings.Count(format, "}")
-		fmt.Fprintf(buf, idt()+format+"\n", args...)
-		indent += strings.Count(format, "{")
-	}
-
-	var edges []string
-
-	p("digraph {")
-
-	sortedQids := make([]string, 0, len(gdata.Quests))
-	for qid := range gdata.Quests {
-		sortedQids = append(sortedQids, qid)
-	}
-	sort.Strings(sortedQids)
-
-	for _, qid := range sortedQids {
-		q := gdata.Quests[qid]
-		qName := nameFor(qid)
-		p("subgraph cluster_%s {", qName)
-		p("label=%q", qName)
-		for aid, a := range q.Attempts {
-			if a.DNE {
-				continue
-			}
-			color := getColor(a)
-			p(`"%s:%d" [style=filled label="%d" fillcolor=%s]`, qName, aid, aid, color)
-			if a.FwdDeps != nil {
-				for depQid, aNums := range a.FwdDeps.To {
-					depQName := nameFor(depQid)
-					for _, num := range aNums.Nums {
-						edges = append(edges, fmt.Sprintf(`"%s:%d" -> "%s:%d"`, qName, aid, depQName, num))
-					}
-				}
-			}
-		}
-		p("}")
-	}
-
-	sort.Strings(edges)
-	for _, e := range edges {
-		p(e)
-	}
-	p("}")
-
-	return buf.String()
-}
-
-func runQuery(c context.Context, dc dm.DepsClient, query *dm.WalkGraphReq) (ret *dm.GraphData, err error) {
-	query = proto.Clone(query).(*dm.WalkGraphReq)
-	ret = &dm.GraphData{}
-	for c.Err() == nil {
-		newRet := (*dm.GraphData)(nil)
-		newRet, err = dc.WalkGraph(c, query)
-		if err != nil || newRet.HadErrors {
-			return
-		}
-		ret.UpdateWith(newRet)
-		if !newRet.HadMore {
-			return
-		}
-		query.Query = ret.ToQuery()
-	}
-	return
-}
-
-func (r *visQueryRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
-	r.cmd = cmdVisQuery
-
-	c, cancel := context.WithCancel(cli.GetContext(a, r, env))
-
-	if r.path == "" && r.sequence {
-		return r.argErr("path is required for sequence")
-	}
-
-	sigChan := make(chan os.Signal, 1)
-	signal.Notify(sigChan, os.Interrupt)
-	go func() {
-		<-sigChan
-		signal.Stop(sigChan)
-		cancel()
-	}()
-
-	query := &dm.WalkGraphReq{}
-	if err := flagpb.UnmarshalMessage(args, flagpb.NewResolver(dm.FileDescriptorSet()), query); err != nil {
-		logging.WithError(err).Errorf(c, "could not construct query")
-		return 1
-	}
-	if r.includeAll {
-		query.Include = dm.MakeWalkGraphIncludeAll()
-	}
-
-	client := &prpc.Client{
-		Host:    r.host,
-		Options: prpc.DefaultOptions(),
-	}
-	client.Options.Insecure = lhttp.IsLocalHost(r.host)
-	dc := dm.NewDepsPRPCClient(client)
-
-	prev := ""
-	seq := 0
-
-	for c.Err() == nil {
-		gdata, err := runQuery(c, dc, query)
-		if err != nil {
-			if errors.Any(err, func(err error) bool { return err == context.Canceled }) {
-				return 0
-			}
-			logging.WithError(err).Errorf(c, "error running query")
-			return 1
-		}
-
-		if gdata != nil {
-			newVal := renderDotFile(gdata)
-			if prev != newVal {
-				prev = newVal
-
-				if r.sequence {
-					outfile := fmt.Sprintf("%s%d.png", r.path, seq)
-					seq++
-					cmd := exec.CommandContext(c, "dot",
-						"-Gdpi=300", "-Glwidth=6", "-Glheight=17.6",
-						"-Tpng", "-o"+outfile)
-					cmd.Stdin = strings.NewReader(newVal)
-					err := cmd.Run()
-					if err != nil {
-						logging.WithError(err).Errorf(c, "error running dot")
-						return 1
-					}
-				} else {
-					ofile := os.Stdout
-					if r.path != "" {
-						ofile, err = os.Create(r.path)
-						if err != nil {
-							logging.Fields{
-								logging.ErrorKey: err,
-								"outfile":        r.path,
-							}.Errorf(c, "error opening output file")
-							return 1
-						}
-					}
-					ofile.WriteString(newVal)
-					ofile.Close()
-					if r.path == "" {
-						return 0
-					}
-				}
-			}
-		}
-
-		clock.Sleep(c, time.Second/4)
-	}
-	return 0
-}
diff --git a/dm/tools/jobsim_client/.gitignore b/dm/tools/jobsim_client/.gitignore
deleted file mode 100644
index 298232a..0000000
--- a/dm/tools/jobsim_client/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-pkg_dir
diff --git a/dm/tools/jobsim_client/edit_distance.go b/dm/tools/jobsim_client/edit_distance.go
deleted file mode 100644
index f582d24..0000000
--- a/dm/tools/jobsim_client/edit_distance.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"bytes"
-	"encoding/json"
-	"math"
-	"strings"
-
-	"github.com/maruel/subcommands"
-)
-
-var cmdEditDistance = &subcommands.Command{
-	UsageLine: `edit-distance [options]`,
-	ShortDesc: `Computes the edit distance of two strings.`,
-	LongDesc: `Computes the edit distance of two strings using insertion, deletion,
-	substitution, and optionally also transposition. This expects the properties
-	of the quest to be a single JSON dictionary with two keys "a" and "b". Each
-	key should correspond to a string. The result of the job will be a dictionary
-	with a key "dist" that is the minimum number of edit operations needed to
-	transform a into b.`,
-	CommandRun: func() subcommands.CommandRun {
-		r := &editDistanceRun{}
-		r.registerOptions()
-		return r
-	},
-}
-
-type editDistanceRun struct {
-	cmdRun
-
-	useTransposition bool
-}
-
-func (e *editDistanceRun) registerOptions() {
-	e.cmdRun.registerOptions()
-	e.Flags.BoolVar(&e.useTransposition, "use-transposition", false,
-		"Include transposition as one of the possible candidates.")
-}
-
-// EditParams is the 'parameters' for the edit-distance algorithm.
-type EditParams struct {
-	A string `json:"a"`
-	B string `json:"b"`
-}
-
-// EditResult is the normal result data for the edit-distance algorithm.
-type EditResult struct {
-	Distance uint32 `json:"dist"`
-
-	// OpHistory is a string which says which edit commands were taken. The
-	// symbols are:
-	//   = - no edit
-	//   ~ - substitute
-	//   - - delete
-	//   + - insert
-	//   X - transpose
-	//   ! - error
-	OpHistory string `json:"op_history"`
-	Error     string `json:"error,omitempty"`
-}
-
-func (e *editDistanceRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
-	e.start(a, e, env, cmdEditDistance)
-
-	p := &EditParams{}
-	err := json.NewDecoder(bytes.NewBufferString(e.questDesc.Parameters)).Decode(p)
-	if err != nil {
-		return e.finish(EditResult{Error: err.Error()})
-	}
-
-	rslt, stop := e.compute(p)
-	if stop {
-		return 0
-	}
-
-	return e.finish(rslt)
-}
-
-var editSymbolLookup = map[string]string{
-	"substitution":  "~",
-	"insertion":     "+",
-	"deletion":      "-",
-	"equality":      "=",
-	"transposition": "X",
-}
-
-func (e *editDistanceRun) compute(p *EditParams) (rslt EditResult, stop bool) {
-	// If one string is empty, the edit distance is the length of the other
-	// string.
-	if len(p.A) == 0 {
-		rslt.Distance = uint32(len(p.B))
-		rslt.OpHistory = strings.Repeat("+", len(p.B))
-		return
-	} else if len(p.B) == 0 {
-		rslt.Distance = uint32(len(p.A))
-		rslt.OpHistory = strings.Repeat("-", len(p.A))
-		return
-	}
-
-	// If both strings are exactly equality, the distance between them is 0.
-	if p.A == p.B {
-		rslt.OpHistory = strings.Repeat("=", len(p.A))
-		return
-	}
-
-	toDep := []interface{}{
-		&EditParams{ // substitution || equality
-			A: p.A[1:],
-			B: p.B[1:],
-		},
-		&EditParams{ // deletion (remove a char from A)
-			A: p.A[1:],
-			B: p.B,
-		},
-		&EditParams{ // insertion (add the char to A)
-			A: p.A,
-			B: p.B[1:],
-		},
-	}
-	if e.useTransposition && len(p.A) > 1 && len(p.B) > 1 {
-		if p.A[0] == p.B[1] && p.A[1] == p.B[0] {
-			toDep = append(toDep, &EditParams{ // transposition
-				A: p.A[2:],
-				B: p.B[2:],
-			})
-		}
-	}
-
-	opNames := []string{
-		"substitution", "deletion", "insertion", "transposition",
-	}
-	if p.A[0] == p.B[0] {
-		opNames[0] = "equality"
-	}
-
-	retval := uint32(math.MaxUint32)
-	opname := ""
-	opchain := ""
-
-	depsData, stop := e.depOn(toDep...)
-	if stop {
-		return
-	}
-
-	for i, dep := range depsData {
-		result := &EditResult{}
-		err := json.NewDecoder(bytes.NewBufferString(dep)).Decode(result)
-		if err != nil {
-			rslt.Error = err.Error()
-			return
-		}
-
-		opName := opNames[i]
-		if result.Error != "" {
-			rslt.OpHistory = "!" + result.OpHistory
-			rslt.Error = result.Error
-			return
-		}
-		cost := result.Distance
-		if opName != "equality" {
-			// all operations (except equality) cost 1
-			cost++
-		}
-		if cost < retval {
-			retval = cost
-			opname = opName
-			opchain = result.OpHistory
-		}
-	}
-
-	rslt.Distance = retval
-	rslt.OpHistory = editSymbolLookup[opname] + opchain
-	return
-}
diff --git a/dm/tools/jobsim_client/edit_distance_test.go b/dm/tools/jobsim_client/edit_distance_test.go
deleted file mode 100644
index 4e5df52..0000000
--- a/dm/tools/jobsim_client/edit_distance_test.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"context"
-	"encoding/json"
-	"testing"
-
-	"google.golang.org/grpc"
-
-	. "github.com/smartystreets/goconvey/convey"
-
-	"google.golang.org/protobuf/types/known/emptypb"
-
-	dm "go.chromium.org/luci/dm/api/service/v1"
-)
-
-type recordingClient struct {
-	deps   []*EditParams
-	result *EditResult
-
-	walkGraphRsp       *dm.GraphData
-	ensureGraphDataRsp *dm.EnsureGraphDataRsp
-}
-
-func (r *recordingClient) EnsureGraphData(ctx context.Context, in *dm.EnsureGraphDataReq, opts ...grpc.CallOption) (*dm.EnsureGraphDataRsp, error) {
-	r.deps = nil
-	for _, q := range in.Quest {
-		ep := &EditParams{}
-		if err := json.Unmarshal([]byte(q.Parameters), ep); err != nil {
-			panic(err)
-		}
-		r.deps = append(r.deps, ep)
-	}
-
-	rsp := r.ensureGraphDataRsp
-	r.ensureGraphDataRsp = nil
-	return rsp, nil
-}
-
-func (r *recordingClient) ActivateExecution(ctx context.Context, in *dm.ActivateExecutionReq, opts ...grpc.CallOption) (*emptypb.Empty, error) {
-	panic("never happens")
-}
-
-func (r *recordingClient) FinishAttempt(ctx context.Context, in *dm.FinishAttemptReq, opts ...grpc.CallOption) (*emptypb.Empty, error) {
-	r.result = &EditResult{}
-	if err := json.Unmarshal([]byte(in.Data.Object), r.result); err != nil {
-		panic(err)
-	}
-	return nil, nil
-}
-
-func (r *recordingClient) WalkGraph(ctx context.Context, in *dm.WalkGraphReq, opts ...grpc.CallOption) (*dm.GraphData, error) {
-	rsp := r.walkGraphRsp
-	r.walkGraphRsp = nil
-	return rsp, nil
-}
-
-var _ dm.DepsClient = (*recordingClient)(nil)
-
-func newEDRunner() (*editDistanceRun, *recordingClient) {
-	recorder := &recordingClient{}
-	return &editDistanceRun{cmdRun: cmdRun{
-		Context: context.Background(),
-		client:  recorder,
-		questDesc: &dm.Quest_Desc{
-			DistributorParameters: "{}",
-		},
-	}}, recorder
-}
-
-func TestEditDistance(t *testing.T) {
-	Convey("edit distance", t, func() {
-		edr, recorder := newEDRunner()
-
-		Convey("base cases", func() {
-			Convey("empty", func() {
-				er, stop := edr.compute(&EditParams{})
-				So(stop, ShouldBeFalse)
-				So(er, ShouldResemble, EditResult{0, "", ""})
-			})
-
-			Convey("all sub", func() {
-				er, stop := edr.compute(&EditParams{"hello", ""})
-				So(stop, ShouldBeFalse)
-				So(er, ShouldResemble, EditResult{5, "-----", ""})
-			})
-
-			Convey("all add", func() {
-				er, stop := edr.compute(&EditParams{"", "hello"})
-				So(stop, ShouldBeFalse)
-				So(er, ShouldResemble, EditResult{5, "+++++", ""})
-			})
-		})
-
-		Convey("single", func() {
-			Convey("equal", func() {
-				er, stop := edr.compute(&EditParams{"a", "a"})
-				So(stop, ShouldBeFalse)
-				So(er, ShouldResemble, EditResult{0, "=", ""})
-			})
-
-			Convey("different", func() {
-
-				Convey("trigger", func() {
-					recorder.ensureGraphDataRsp = &dm.EnsureGraphDataRsp{
-						Accepted: true, ShouldHalt: true}
-					_, stop := edr.compute(&EditParams{"a", "b"})
-					So(stop, ShouldBeTrue)
-					So(recorder.deps, ShouldResemble, []*EditParams{
-						{"", ""},
-						{"", "b"},
-						{"a", ""},
-					})
-				})
-
-				Convey("already done", func() {
-					recorder.ensureGraphDataRsp = &dm.EnsureGraphDataRsp{
-						Accepted: true,
-						QuestIds: []*dm.Quest_ID{{Id: "1"}, {Id: "2"}, {Id: "3"}},
-						Result: &dm.GraphData{
-							Quests: map[string]*dm.Quest{
-								"1": {Attempts: map[uint32]*dm.Attempt{
-									1: dm.NewAttemptFinished(dm.NewJsonResult("{}")),
-								}},
-								"2": {Attempts: map[uint32]*dm.Attempt{
-									1: dm.NewAttemptFinished(dm.NewJsonResult("{}")),
-								}},
-								"3": {Attempts: map[uint32]*dm.Attempt{
-									1: dm.NewAttemptFinished(dm.NewJsonResult("{}")),
-								}},
-							},
-						},
-					}
-					er, stop := edr.compute(&EditParams{"a", "b"})
-					So(stop, ShouldBeFalse)
-					So(er, ShouldResemble, EditResult{1, "~", ""})
-				})
-			})
-		})
-	})
-}
diff --git a/dm/tools/jobsim_client/generate_ensure_graph_data_req.py b/dm/tools/jobsim_client/generate_ensure_graph_data_req.py
deleted file mode 100755
index 3f82ec7..0000000
--- a/dm/tools/jobsim_client/generate_ensure_graph_data_req.py
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-
-"""
-This is a dumb script that will:
-  * compile jobsim_client (for linux-amd64)
-  * upload a simple cipd package containing only jobsim_client with the 'latest'
-    ref. The package name is 'infra/experimental/dm/jobsim_client/linux-amd64'.
-  * Print a JSONPB-encoded EnsureGraphDataReq that runs jobsim_client with the
-    provided strings to calculate edit-distance(a, b, transposition?).
-"""
-
-import argparse
-import json
-import os
-import pprint
-import shutil
-import subprocess
-import tempfile
-
-THIS_DIR = os.path.dirname(os.path.abspath(__file__))
-
-def compile_pkg(pkg_dir, os_name, arch_name):
-  print 'building jobsim_client'
-  env = os.environ.copy()
-  env.update(
-    GOOS   = os_name,
-    GOARCH = arch_name,
-  )
-  subprocess.check_call(
-      ['go', 'build', 'go.chromium.org/luci/dm/tools/jobsim_client'],
-      cwd=pkg_dir, env=env)
-
-def upload_pkg(pkg_dir, pkg_name_prefix, os_name, arch_name):
-  print 'creating jobsim_client package'
-
-  pkg_name = '%s/%s-%s' % (pkg_name_prefix, os_name, arch_name)
-
-  fd, tfile = tempfile.mkstemp('-cipd-output.json')
-  os.close(fd)
-  try:
-    subprocess.check_call(['cipd', 'create', '-name', pkg_name,
-                           '-ref', 'latest', '-in', pkg_dir,
-                           '-install-mode', 'copy', '-json-output', tfile])
-    with open(tfile, 'r') as tfileData:
-      out_json = json.load(tfileData)
-    version = out_json[u'result'][u'instance_id'].encode('utf-8')
-  finally:
-    os.unlink(tfile)
-
-  print 'uploaded %s:%s' % (pkg_name, version)
-
-  return pkg_name, version
-
-def print_req(opts, pkg_name, version):
-  def dumps(obj):
-    return json.dumps(obj, sort_keys=True, separators=(',', ':'))
-
-  cpu = {
-    'amd64': 'x86-64',
-  }[opts.arch]
-
-  os_name = {
-    'linux': 'Linux',
-  }[opts.os]
-
-  command = ['jobsim_client', 'edit-distance', '-dm-host', '${DM.HOST}',
-             '-quest-desc-path', '${DM.QUEST.DATA.DESC:PATH}']
-  if opts.use_transposition:
-    command.append('-use-transposition')
-
-  distParams = {
-    'scheduling': {
-      'dimensions': {
-        'cpu': cpu,
-        'os': os_name,
-        'pool': opts.pool,
-      },
-    },
-    'meta': {'name_prefix': 'dm jobsim client'},
-    'job': {
-      'inputs': {
-        'cipd': {
-          'server': 'https://chrome-infra-packages.appspot.com',
-          'by_path': {
-            '.': {
-              'pkg': [
-                {
-                  'name': pkg_name,
-                  'version': version if opts.pin else 'latest',
-                },
-              ]
-            }
-          }
-        }
-      },
-      'command': command,
-    }
-  }
-
-  if opts.snapshot_dimension:
-    distParams['scheduling']['snapshot_dimensions'] = opts.snapshot_dimension
-
-  params = {
-    'a': opts.a,
-    'b': opts.b,
-  }
-
-  desc = {
-    'quest': [
-      {
-        'distributor_config_name': 'swarming',
-        'parameters': dumps(params),
-        'distributor_parameters': dumps(distParams),
-        'meta': {
-          'timeouts': {
-            'start': '600s',
-            'run': '300s',
-            'stop': '300s',
-          }
-        },
-      }
-    ],
-    'quest_attempt': [
-      {'nums': [1]},
-    ]
-  }
-
-  print dumps(desc)
-
-def main():
-  parser = argparse.ArgumentParser(
-      description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
-  parser.add_argument('--use-transposition', action='store_true', default=False,
-                      help=('Use Damerau-Levenshtein distance calculation '
-                            'instead of plain Levenshtein distance.'))
-  parser.add_argument('a', type=str, help='The "a" string to calculate for.')
-  parser.add_argument('b', type=str, help='The "b" string to calculate for.')
-
-  plat_grp = parser.add_argument_group(
-      'platform', 'Options for the target platform of the job.')
-  plat_grp.add_argument('--os', choices=('linux',), default='linux',
-                        help='The OS to compile/run on.')
-  plat_grp.add_argument('--arch', choices=('amd64',), default='amd64',
-                        help='The Arch to compile/run on.')
-  plat_grp.add_argument('--pool', type=str, default='default',
-                        help='The swarming pool to use.')
-  plat_grp.add_argument('--pin', action='store_true', default=False,
-                        help='Emit the request with a pinned package version'
-                        ' instead of "latest".')
-  plat_grp.add_argument(
-    '--snapshot-dimension', action='append', help=(
-      'Pin this dimension on re-executions. This will cause re-executions to '
-      'copy the most-specific value of this dependency from the first '
-      'execution to all subsequent re-executions of the same Attempt. May be '
-      'specified multiple times.'
-    ))
-
-  cipd_grp = parser.add_argument_group('cipd', 'cipd packaging options')
-  cipd_grp.add_argument('--cipd-service-url', default=None,
-                        help='The CIPD service to upload to.')
-  cipd_grp.add_argument('--cipd-service-account-json', default=None,
-                        help='The CIPD service account JSON file to use.')
-  cipd_grp.add_argument('--cipd-name',
-                        default='infra/experimental/dm/jobsim_client',
-                        help='The CIPD package name prefix to upload to. This '
-                        'will be appended with the standard os-arch suffix.')
-
-  opts = parser.parse_args()
-
-  # Use local path for determinisim.
-  pkg_dir = os.path.join(THIS_DIR, 'pkg_dir')
-  shutil.rmtree(pkg_dir, ignore_errors=True)
-  os.mkdir(pkg_dir)
-  try:
-    compile_pkg(pkg_dir, opts.os, opts.arch)
-    pkg_name, version = upload_pkg(pkg_dir, opts.cipd_name, opts.os, opts.arch)
-    print_req(opts, pkg_name, version)
-  finally:
-    shutil.rmtree(pkg_dir, ignore_errors=True)
-
-
-if __name__ == '__main__':
-  main()
diff --git a/dm/tools/jobsim_client/main.go b/dm/tools/jobsim_client/main.go
deleted file mode 100644
index e67b75d..0000000
--- a/dm/tools/jobsim_client/main.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Jobsim client is a self-contained binary that implements various toy job
-// algorithms for use in testing DM with live distributors (like swarming).
-package main
-
-import (
-	"bytes"
-	"context"
-	"encoding/json"
-	"fmt"
-	"os"
-
-	"github.com/golang/protobuf/jsonpb"
-	"github.com/golang/protobuf/proto"
-	"github.com/maruel/subcommands"
-
-	"go.chromium.org/luci/common/cli"
-	"go.chromium.org/luci/common/data/rand/cryptorand"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/logging/gologger"
-	"go.chromium.org/luci/common/retry"
-	dm "go.chromium.org/luci/dm/api/service/v1"
-	"go.chromium.org/luci/grpc/prpc"
-	"go.chromium.org/luci/lucictx"
-)
-
-type cmdRun struct {
-	subcommands.CommandRunBase
-
-	context.Context
-
-	exAuth *dm.Execution_Auth
-
-	questDescPath string
-	questDesc     *dm.Quest_Desc
-
-	dmHost string
-
-	client dm.DepsClient
-
-	cmd *subcommands.Command
-}
-
-func (r *cmdRun) registerOptions() {
-	r.Flags.StringVar(&r.questDescPath, "quest-desc-path", "",
-		"The path to a JSONPB encoded dm.Quest.Data.Desc message of how this client"+
-			" was invoked")
-	r.Flags.StringVar(&r.dmHost, "dm-host", "", "The hostname of the DM service")
-}
-
-func loadJSONPB(c context.Context, flavor, path string, msg proto.Message) {
-	if path == "" {
-		logging.Errorf(c, "processing %q: required parameter", flavor)
-		os.Exit(-1)
-	}
-
-	fil, err := os.Open(path)
-	if err != nil {
-		logging.Errorf(c, "processing %q: %s", flavor, err)
-		os.Exit(-1)
-	}
-	defer fil.Close()
-	if err := jsonpb.Unmarshal(fil, msg); err != nil {
-		panic(err)
-	}
-}
-
-func (r *cmdRun) start(a subcommands.Application, cr subcommands.CommandRun, env subcommands.Env, c *subcommands.Command) {
-	r.cmd = c
-
-	r.Context = cli.GetContext(a, cr, env)
-
-	r.exAuth = &dm.Execution_Auth{}
-	s := lucictx.GetSwarming(r.Context)
-	if s == nil || s.SecretBytes == nil {
-		panic("LUCI_CONTEXT['swarming']['secret_bytes'] is missing")
-	}
-	if err := jsonpb.Unmarshal(bytes.NewReader(s.SecretBytes), r.exAuth); err != nil {
-		panic(fmt.Errorf("while decoding execution auth: %s", err))
-	}
-
-	r.questDesc = &dm.Quest_Desc{}
-	loadJSONPB(r, "quest-desc-path", r.questDescPath, r.questDesc)
-
-	// initialize rpc client
-	r.client = dm.NewDepsPRPCClient(&prpc.Client{
-		Host: r.dmHost,
-		Options: &prpc.Options{
-			Retry: retry.Default,
-		},
-	})
-
-	key := make([]byte, 32)
-	_, err := cryptorand.Read(r, key)
-	if err != nil {
-		panic(err)
-	}
-
-	req := &dm.ActivateExecutionReq{
-		Auth:           r.exAuth,
-		ExecutionToken: key,
-	}
-	err = retry.Retry(r, retry.Default, func() error {
-		_, err := r.client.ActivateExecution(r, req)
-		return err
-	}, retry.LogCallback(r, "ActivateExecution"))
-	if err != nil {
-		panic(err)
-	}
-
-	// activated with key!
-	r.exAuth.Token = key
-}
-
-func (r *cmdRun) depOn(jobProperties ...interface{}) (data []string, stop bool) {
-	req := &dm.EnsureGraphDataReq{
-		ForExecution: r.exAuth,
-
-		Quest:        make([]*dm.Quest_Desc, len(jobProperties)),
-		QuestAttempt: make([]*dm.AttemptList_Nums, len(jobProperties)),
-
-		Include: &dm.EnsureGraphDataReq_Include{
-			Attempt: &dm.EnsureGraphDataReq_Include_Options{Result: true},
-		},
-	}
-
-	for i, jProps := range jobProperties {
-		data, err := json.Marshal(jProps)
-		if err != nil {
-			panic(err)
-		}
-		req.Quest[i] = proto.Clone(r.questDesc).(*dm.Quest_Desc)
-		req.Quest[i].Parameters = string(data)
-		req.QuestAttempt[i] = &dm.AttemptList_Nums{Nums: []uint32{1}}
-	}
-
-	rsp := (*dm.EnsureGraphDataRsp)(nil)
-	err := retry.Retry(r, retry.Default, func() (err error) {
-		rsp, err = r.client.EnsureGraphData(r, req)
-		return
-	}, retry.LogCallback(r, "EnsureGraphData"))
-	if err != nil {
-		panic(err)
-	}
-	if rsp.ShouldHalt {
-		logging.Infof(r, "got ShouldHalt")
-		return nil, true
-	}
-
-	ret := make([]string, len(jobProperties))
-	for i, qid := range rsp.QuestIds {
-		ret[i] = rsp.Result.Quests[qid.Id].Attempts[1].Data.GetFinished().Data.Object
-	}
-
-	return ret, false
-}
-
-func (r *cmdRun) finish(data interface{}) int {
-	encData, err := json.Marshal(data)
-	if err != nil {
-		panic(err)
-	}
-	err = retry.Retry(r, retry.Default, func() error {
-		_, err := r.client.FinishAttempt(r, &dm.FinishAttemptReq{
-			Auth: r.exAuth, Data: dm.NewJsonResult(string(encData)),
-		})
-		return err
-	}, retry.LogCallback(r, "FinishAttempt"))
-	if err != nil {
-		panic(err)
-	}
-	return 0
-}
-
-var application = &cli.Application{
-	Name:  "jobsim_client",
-	Title: "Executable Job simulator client",
-	Context: func(ctx context.Context) context.Context {
-		return gologger.StdConfig.Use(ctx)
-	},
-	Commands: []*subcommands.Command{
-		cmdEditDistance,
-		subcommands.CmdHelp,
-	},
-}
-
-func main() {
-	os.Exit(subcommands.Run(application, os.Args[1:]))
-}
diff --git a/go.mod b/go.mod
index 970192a..8d6cfac 100644
--- a/go.mod
+++ b/go.mod
@@ -53,7 +53,6 @@
 	github.com/sergi/go-diff v1.2.0
 	github.com/smartystreets/assertions v1.2.0
 	github.com/smartystreets/goconvey v1.7.2
-	github.com/xtgo/set v1.0.0
 	github.com/yosuke-furukawa/json5 v0.1.1
 	go.opencensus.io v0.23.0
 	go.starlark.net v0.0.0-20210901212718-87f333178d59
diff --git a/go.sum b/go.sum
index 11b54f6..51fefbc 100644
--- a/go.sum
+++ b/go.sum
@@ -523,8 +523,6 @@
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-github.com/xtgo/set v1.0.0 h1:6BCNBRv3ORNDQ7fyoJXRv+tstJz3m1JVFQErfeZz2pY=
-github.com/xtgo/set v1.0.0/go.mod h1:d3NHzGzSa0NmB2NhFyECA+QdRp29oEn2xbT+TpeFoM8=
 github.com/yosuke-furukawa/json5 v0.1.1 h1:0F9mNwTvOuDNH243hoPqvf+dxa5QsKnZzU20uNsh3ZI=
 github.com/yosuke-furukawa/json5 v0.1.1/go.mod h1:sw49aWDqNdRJ6DYUtIQiaA3xyj2IL9tjeNYmX2ixwcU=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/tumble/OWNERS b/tumble/OWNERS
deleted file mode 100644
index 760558a..0000000
--- a/tumble/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-iannucci@chromium.org
diff --git a/tumble/add_to_journal.go b/tumble/add_to_journal.go
deleted file mode 100644
index 5477d7c..0000000
--- a/tumble/add_to_journal.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"crypto/sha256"
-	"encoding/hex"
-
-	"go.chromium.org/luci/common/logging"
-	ds "go.chromium.org/luci/gae/service/datastore"
-)
-
-// AddToJournal records one or more Mutation to the tumble journal, but does not
-// execute any of them. This does so by running a transaction on a pseudo-random
-// entity group, and journaling the mutations there.
-func AddToJournal(c context.Context, m ...Mutation) error {
-	(logging.Fields{"count": len(m)}).Infof(c, "tumble.AddToJournal")
-	if len(m) == 0 {
-		return nil
-	}
-	return RunMutation(c, addToJournalMutation(m))
-}
-
-type addToJournalMutation []Mutation
-
-func (a addToJournalMutation) Root(c context.Context) *ds.Key {
-	hsh := sha256.New()
-	for _, m := range a {
-		hsh.Write(ds.SerializeKC.ToBytes(m.Root(c)))
-	}
-	return ds.MakeKey(c, "tumble.temp", hex.EncodeToString(hsh.Sum(nil)))
-}
-
-func (a addToJournalMutation) RollForward(c context.Context) ([]Mutation, error) {
-	return a, nil
-}
diff --git a/tumble/add_to_journal_test.go b/tumble/add_to_journal_test.go
deleted file mode 100644
index 993aad1..0000000
--- a/tumble/add_to_journal_test.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"testing"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/logging/memlogger"
-)
-
-func TestAddToJournal(t *testing.T) {
-	t.Parallel()
-
-	Convey("Test AddToJournal", t, func() {
-		ttest := &Testing{}
-		c := ttest.Context()
-		ml := logging.Get(c).(*memlogger.MemLogger)
-
-		Convey("with no mutations", func() {
-			So(AddToJournal(c), ShouldBeNil)
-			So(ml.HasFunc(func(e *memlogger.LogEntry) bool {
-				return e.Msg == "tumble.AddToJournal" && e.Data["count"].(int) == 0
-			}), ShouldBeTrue)
-		})
-
-		Convey("with some mutations", func() {
-			from := &User{Name: "fromUser"}
-			So(ds.Put(c, from), ShouldBeNil)
-			So(AddToJournal(c, &WriteMessage{
-				from.MakeOutgoingMessage(c, "hey there", "a", "b")}), ShouldBeNil)
-
-			qry := ds.NewQuery("tumble.Mutation").Ancestor(ds.MakeKey(c, "tumble.temp", "8c60aac4ffd6e66142bef4e745d9d91546c115d18cc8283723699d964422a47a"))
-			pmaps := []ds.PropertyMap{}
-			So(ds.GetAll(c, qry, &pmaps), ShouldBeNil)
-			So(len(pmaps), ShouldEqual, 1)
-			So(pmaps[0].Slice("$key")[0].Value().(*ds.Key).String(), ShouldEqual,
-				`dev~app::/tumble.temp,"8c60aac4ffd6e66142bef4e745d9d91546c115d18cc8283723699d964422a47a"/tumble.Mutation,"0000000000000000_00000000_00000000"`)
-		})
-	})
-}
diff --git a/tumble/bitfield/bf.go b/tumble/bitfield/bf.go
deleted file mode 100644
index e366851..0000000
--- a/tumble/bitfield/bf.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//go:generate go run ./tool/gen.go
-
-package bitfield
-
-import (
-	"bytes"
-	"encoding"
-	"encoding/binary"
-	"fmt"
-	"math"
-
-	"go.chromium.org/luci/gae/service/datastore"
-)
-
-// BitField is a luci/gae-serializable bit field implementation. It should
-// be nice and fast for non-AppEngine use as well.
-//
-// You should construct a new one with bf.Make, rather than by direct
-// construction.
-type BitField struct {
-	// data is the actual bits data. rightmost bit of 0th byte is the first bit.
-	data []byte
-	size uint32
-}
-
-var _ interface {
-	// Compatible with luci/gae/service/datastore
-	datastore.PropertyConverter
-
-	// Compatible with gob
-	encoding.BinaryMarshaler
-	encoding.BinaryUnmarshaler
-} = (*BitField)(nil)
-
-// MarshalBinary implements encoding.BinaryMarshaller
-func (bf *BitField) MarshalBinary() ([]byte, error) {
-	ret := make([]byte, binary.MaxVarintLen32+len(bf.data))
-	n := binary.PutUvarint(ret, uint64(bf.size))
-	n += copy(ret[n:], bf.data)
-	return ret[:n], nil
-}
-
-// UnmarshalBinary implements encoding.BinaryUnmarshaler
-func (bf *BitField) UnmarshalBinary(bs []byte) error {
-	buf := bytes.NewBuffer(bs)
-	n, err := binary.ReadUvarint(buf)
-	if err != nil {
-		return err
-	}
-	if n > math.MaxUint32 {
-		return fmt.Errorf("encoded number is out of range: %d > %d", n, uint32(math.MaxUint32))
-	}
-
-	size := uint32(n)
-	if size == 0 {
-		bf.size = 0
-		bf.data = nil
-		return nil
-	}
-	data := buf.Bytes()
-	if uint32(len(data)) != (size+8-1)>>3 {
-		return fmt.Errorf("mismatched size (%d) v. byte count (%d)", size, len(data))
-	}
-
-	bf.size = size
-	bf.data = data
-	return nil
-}
-
-// ToProperty implements datastore.PropertyConverter
-func (bf *BitField) ToProperty() (datastore.Property, error) {
-	bs, err := bf.MarshalBinary()
-	return datastore.MkPropertyNI(bs), err
-}
-
-// FromProperty implements datastore.PropertyConverter
-func (bf *BitField) FromProperty(p datastore.Property) error {
-	bin, ok := p.Value().([]byte)
-	if !ok {
-		return fmt.Errorf("expected %s, got %s", datastore.PTBytes, p.Type())
-	}
-	return bf.UnmarshalBinary(bin)
-}
-
-// Reset resets this BitField to the 'empty' (size-0) state.
-func (bf *BitField) Reset() {
-	bf.data = nil
-	bf.size = 0
-}
-
-// Make creates a new BitField.
-func Make(size uint32) BitField {
-	if size == 0 {
-		return BitField{}
-	}
-	return BitField{
-		data: make([]byte, (size+8-1)>>3),
-		size: size,
-	}
-}
-
-// Size returns the number of bits which this BitField can hold.
-func (bf BitField) Size() uint32 {
-	return bf.size
-}
-
-// Set turns the given bit to true, regardless of its previous value. Will panic
-// if idx >= Size().
-func (bf BitField) Set(idx uint32) {
-	if idx >= bf.size {
-		panic(fmt.Errorf("cannot set bit %d in BitField of size %d", idx, bf.size))
-	}
-	bf.data[idx>>3] |= 1 << (idx % 8)
-}
-
-// Clear turns the given bit to false, regardless of its previous value. Will
-// panic if idx >= Size().
-func (bf BitField) Clear(idx uint32) {
-	if idx >= bf.size {
-		panic(fmt.Errorf("cannot clear bit %d in BitField of size %d", idx, bf.size))
-	}
-	bf.data[idx>>3] &^= 1 << (idx % 8)
-}
-
-// All returns true iff all of the bits are equal to `val`.
-func (bf BitField) All(val bool) bool {
-	targ := bf.size
-	if !val {
-		targ = 0
-	}
-	return bf.CountSet() == targ
-}
-
-// CountSet returns the number of true bits.
-func (bf BitField) CountSet() (ret uint32) {
-	for _, b := range bf.data {
-		if b != 0 {
-			ret += uint32(bitCount[b])
-		}
-	}
-	return ret
-}
-
-// IsSet returns the value of a given bit.
-func (bf BitField) IsSet(idx uint32) bool {
-	return idx < bf.size && ((bf.data[idx>>3] & (1 << (idx % 8))) != 0)
-}
diff --git a/tumble/bitfield/bf_table.gen.go b/tumble/bitfield/bf_table.gen.go
deleted file mode 100644
index 9d45c26..0000000
--- a/tumble/bitfield/bf_table.gen.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The LUCI Authors. All rights reserved.
-// Use of this source code is governed under the Apache License, Version 2.0
-// that can be found in the LICENSE file.
-
-// AUTOGENERATED: DO NOT EDIT
-
-package bitfield
-
-var bitCount = [256]byte{
-	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
-	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-	4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
-}
diff --git a/tumble/bitfield/bf_test.go b/tumble/bitfield/bf_test.go
deleted file mode 100644
index 871f8f8..0000000
--- a/tumble/bitfield/bf_test.go
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package bitfield
-
-import (
-	"encoding/binary"
-	"math/rand"
-	"testing"
-
-	. "go.chromium.org/luci/common/testing/assertions"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestBitField(t *testing.T) {
-	Convey("BitField", t, func() {
-		bf := Make(2000)
-
-		Convey("Should be sized right", func() {
-			So(bf.Size(), ShouldEqual, 2000)
-			So(len(bf.data), ShouldEqual, 250)
-		})
-
-		Convey("Should be empty", func() {
-			So(bf.All(false), ShouldBeTrue)
-			So(bf.data[0], ShouldEqual, 0)
-			So(bf.CountSet(), ShouldEqual, 0)
-			So(bf.IsSet(20), ShouldBeFalse)
-			So(bf.IsSet(200001), ShouldBeFalse)
-
-			Convey("and be unset", func() {
-				for i := uint32(0); i < 20; i++ {
-					So(bf.IsSet(i), ShouldBeFalse)
-				}
-			})
-		})
-
-		Convey("Boundary conditions are caught", func() {
-			So(func() { bf.Set(2000) }, ShouldPanicLike, "cannot set bit 2000")
-			So(func() { bf.Clear(2000) }, ShouldPanicLike, "cannot clear bit 2000")
-		})
-
-		Convey("and setting [0, 1, 19, 197, 4]", func() {
-			bf.Set(0)
-			bf.Set(1)
-			bf.Set(19)
-			bf.Set(197)
-			bf.Set(1999)
-			bf.Set(4)
-
-			Convey("should count correctly", func() {
-				So(bf.CountSet(), ShouldEqual, 6)
-			})
-
-			Convey("should retrieve correctly", func() {
-				So(bf.IsSet(2), ShouldBeFalse)
-				So(bf.IsSet(18), ShouldBeFalse)
-
-				So(bf.IsSet(0), ShouldBeTrue)
-				So(bf.IsSet(1), ShouldBeTrue)
-				So(bf.IsSet(4), ShouldBeTrue)
-				So(bf.IsSet(19), ShouldBeTrue)
-				So(bf.IsSet(197), ShouldBeTrue)
-				So(bf.IsSet(1999), ShouldBeTrue)
-			})
-
-			Convey("should clear correctly", func() {
-				bf.Clear(3)
-				bf.Clear(4)
-				bf.Clear(197)
-
-				So(bf.IsSet(2), ShouldBeFalse)
-				So(bf.IsSet(3), ShouldBeFalse)
-				So(bf.IsSet(18), ShouldBeFalse)
-
-				So(bf.IsSet(4), ShouldBeFalse)
-				So(bf.IsSet(197), ShouldBeFalse)
-
-				So(bf.IsSet(0), ShouldBeTrue)
-				So(bf.IsSet(1), ShouldBeTrue)
-				So(bf.IsSet(19), ShouldBeTrue)
-
-				So(bf.CountSet(), ShouldEqual, 4)
-			})
-
-			Convey("should reset correctly", func() {
-				bf.Reset()
-				So(bf.Size(), ShouldEqual, 0)
-				So(bf.data, ShouldBeEmpty)
-			})
-		})
-
-		Convey("Can interact with datastore", func() {
-			Convey("encodes to a []byte", func() {
-				p, err := bf.ToProperty()
-				So(err, ShouldBeNil)
-
-				bval := make([]byte, 252)
-				// varint encoding of 2000
-				bval[0] = 208
-				bval[1] = 15
-				So(p.Value(), ShouldResemble, bval)
-
-				Convey("decodes as well", func() {
-					nbf := BitField{}
-					So(nbf.FromProperty(p), ShouldBeNil)
-					So(nbf, ShouldResemble, bf)
-				})
-			})
-
-			Convey("zero-length BitField has small representation", func() {
-				bf = Make(0)
-				p, err := bf.ToProperty()
-				So(err, ShouldBeNil)
-				So(p.Value(), ShouldResemble, []byte{0})
-
-				Convey("decodes as well", func() {
-					nbf := BitField{}
-					So(nbf.FromProperty(p), ShouldBeNil)
-					So(nbf, ShouldResemble, bf)
-				})
-			})
-
-			Convey("setting bits round-trips", func() {
-				bf.Set(0)
-				bf.Set(1)
-				bf.Set(19)
-				bf.Set(197)
-				bf.Set(1999)
-				bf.Set(4)
-
-				p, err := bf.ToProperty()
-				So(err, ShouldBeNil)
-
-				bval := make([]byte, 252)
-				// varint encoding of 2000
-				bval[0] = 208
-				bval[1] = 15
-				// various bits set
-				bval[2] = 19    // 0 and 1 and 4
-				bval[4] = 8     // 19
-				bval[26] = 32   // 197
-				bval[251] = 128 // 1999
-				So(p.Value(), ShouldResemble, bval)
-
-				nbf := BitField{}
-				So(nbf.FromProperty(p), ShouldBeNil)
-				So(nbf, ShouldResemble, bf)
-
-				So(nbf.IsSet(2), ShouldBeFalse)
-				So(nbf.IsSet(18), ShouldBeFalse)
-
-				So(nbf.IsSet(0), ShouldBeTrue)
-				So(nbf.IsSet(1), ShouldBeTrue)
-				So(nbf.IsSet(4), ShouldBeTrue)
-				So(nbf.IsSet(19), ShouldBeTrue)
-				So(nbf.IsSet(197), ShouldBeTrue)
-				So(nbf.IsSet(1999), ShouldBeTrue)
-			})
-
-			Convey("empty sets have canonical representation", func() {
-				bf = Make(0)
-				p, err := bf.ToProperty()
-				So(err, ShouldBeNil)
-				So(p.Value(), ShouldResemble, []byte{0})
-
-				nbf := BitField{}
-				So(nbf.FromProperty(p), ShouldBeNil)
-				So(nbf, ShouldResemble, bf)
-			})
-
-			Convey("small sets correctly encode", func() {
-				bf = Make(2)
-				bf.Set(0)
-				p, err := bf.ToProperty()
-				So(err, ShouldBeNil)
-				So(p.Value(), ShouldResemble, []byte{2, 1})
-
-				nbf := BitField{}
-				So(nbf.FromProperty(p), ShouldBeNil)
-				So(nbf, ShouldResemble, bf)
-			})
-		})
-	})
-}
-
-func BenchmarkCount(b *testing.B) {
-	b.StopTimer()
-	r := rand.New(rand.NewSource(193482))
-	bf := Make(1000000)
-	if len(bf.data) != 125000 {
-		b.Fatalf("unexpected length of bf.data: %d", len(bf.data))
-	}
-	for i := 0; i < len(bf.data); i += 4 {
-		binary.BigEndian.PutUint32(bf.data[i:i+4], r.Uint32())
-	}
-	b.StartTimer()
-
-	for i := 0; i < b.N; i++ {
-		num := bf.CountSet()
-		if num != 500188 {
-			b.Fatalf("expected to see %d set, got %d", 500188, num)
-		}
-	}
-}
diff --git a/tumble/bitfield/tool/gen.go b/tumble/bitfield/tool/gen.go
deleted file mode 100644
index 703140f..0000000
--- a/tumble/bitfield/tool/gen.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"fmt"
-	"os"
-)
-
-func main() {
-	f, err := os.Create("bf_table.gen.go")
-	if err != nil {
-		panic(err)
-	}
-	defer f.Close()
-
-	w := func(format string, a ...interface{}) {
-		_, err := fmt.Fprintf(f, format, a...)
-		if err != nil {
-			panic(err)
-		}
-	}
-
-	w("// Copyright 2016 The LUCI Authors. All rights reserved.\n")
-	w("// Use of this source code is governed under the Apache License, Version 2.0\n")
-	w("// that can be found in the LICENSE file.\n\n")
-	w("// AUTOGENERATED: DO NOT EDIT\n")
-	w("\npackage bitfield\n\n")
-	w("var bitCount = [256]byte{")
-	tbl := [256]int{}
-	for i := 0; i < 256; i++ {
-		if i%16 == 0 {
-			w("\n\t")
-		} else {
-			w(" ")
-		}
-		tbl[i] = (i & 1) + tbl[i/2]
-		w("%d,", tbl[i])
-	}
-	w("\n}\n")
-}
diff --git a/tumble/config.go b/tumble/config.go
deleted file mode 100644
index 57507e5..0000000
--- a/tumble/config.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"fmt"
-	"time"
-
-	"go.chromium.org/luci/common/clock/clockflag"
-	"go.chromium.org/luci/server/settings"
-)
-
-const (
-	// baseName is the base tumble name. It is also the name of the tumble task
-	// queue and settings dict.
-	baseName = "tumble"
-)
-
-// Config is the set of tweakable things for tumble. If you use something other
-// than the defaults (e.g. unset values), you must ensure that all aspects of
-// your application use the same config.
-//
-// The JSON annotations are for settings module storage (see settings.go).
-type Config struct {
-	// NumShards is the number of tumble shards that will process concurrently.
-	// It defaults to 32.
-	NumShards uint64 `json:"numShards,omitempty"`
-
-	// NumGoroutines is the number of gorountines that will process in parallel
-	// in a single shard. Each goroutine will process exactly one root entity.
-	// It defaults to 16.
-	NumGoroutines int `json:"numGoroutines,omitempty"`
-
-	// TemporalMinDelay is the minimum number of seconds to wait before the
-	// task queue entry for a given shard will run. It defaults to 1 second.
-	TemporalMinDelay clockflag.Duration `json:"temporalMinDelay,omitempty"`
-
-	// TemporalRoundFactor is the number of seconds to batch together in task
-	// queue tasks. It defaults to 4 seconds.
-	TemporalRoundFactor clockflag.Duration `json:"temporalRoundFactor,omitempty"`
-
-	// ProcessLoopDuration is the maximum lifetime of a process loop. A process
-	// batch will refrain from re-entering its loop after this much time has
-	// elapsed.
-	//
-	// This is not a hard termination boundary. If a loop round starts before
-	// ProcessLoopDuration has been reached, it will be permitted to continue past
-	// the duration.
-	//
-	// If this is <= 0, the process will loop at most once.
-	ProcessLoopDuration clockflag.Duration `json:"processLoopDuration,omitempty"`
-
-	// DustSettleTimeout is the amount of time to wait in between mutation
-	// processing iterations.
-	//
-	// This should be chosen as a compromise between higher expectations of the
-	// eventually-consistent datastore and task processing latency.
-	DustSettleTimeout clockflag.Duration `json:"dustSettleTimeout,omitempty"`
-
-	// MaxNoWorkDelay is the maximum amount of time to wait in between mutation
-	// processing iterations when there was no work the previous iteration.
-	//
-	// When no work has been done, each round will begin by waiting
-	// DustSettleTimeout seconds (minimum of 1 second). If no work was done that
-	// round, this will continue to exponentially grow each successive no-work
-	// round until capped at MaxNoWorkDelay. If work is encountered during any
-	// round, the delay is reset.
-	//
-	// If MaxNoWorkDelay is <= 0, the delay will continue exponentially growing
-	// until the shard terminates.
-	//
-	// This should be chosen as a compromise between higher expectations of the
-	// eventually-consistent datastore and task processing latency.
-	MaxNoWorkDelay clockflag.Duration `json:"MaxNoWorkDelay,omitempty"`
-
-	// NoWorkDelayGrowth is the exponential growth factor for the delay in
-	// between processing loop rounds when no work was done.
-	//
-	// If NoWorkDelayGrowth is <= 1, a growth factor of 1 will be used.
-	NoWorkDelayGrowth int `json:"NoWorkDelayGrowth,omitempty"`
-
-	// ProcessMaxBatchSize is the number of mutations that each processor
-	// goroutine will attempt to include in each commit.
-	//
-	// It defaults to 128. A negative value means no limit.
-	ProcessMaxBatchSize int `json:"processMaxBatchSize,omitempty"`
-
-	// DelayedMutations enables the 'DelayedMutation' mutation subtype.
-	//
-	// If you set this to true, you MUST also add the second index mentioned
-	// in the package docs.
-	DelayedMutations bool `json:"delayedMutations,omitempty"`
-}
-
-// TotalShardCount returns the number of shard counts that should be used.
-func (c *Config) TotalShardCount(namespace string) uint64 {
-	// HACK(hinoka): This namespace requires a lot more shards than your average
-	// namespace.  crbug.com/920852
-	if namespace == "luci.chromium" {
-		return 64
-	}
-	return c.NumShards
-}
-
-// defaultConfig returns the default configuration settings.
-var defaultConfig = Config{
-	NumShards:           32,
-	TemporalMinDelay:    clockflag.Duration(time.Second),
-	TemporalRoundFactor: clockflag.Duration(4 * time.Second),
-	// The AppEngine timeout for backend instances is 10 minutes.
-	// Set this to less than half of that by default to allow for a large margin.
-	ProcessLoopDuration: clockflag.Duration(4*time.Minute + 30*time.Second),
-	DustSettleTimeout:   clockflag.Duration(2 * time.Second),
-	MaxNoWorkDelay:      clockflag.Duration(2 * time.Second), // == DustSettleTimeout
-	NoWorkDelayGrowth:   3,
-	NumGoroutines:       16,
-	ProcessMaxBatchSize: 128,
-}
-
-// getConfig returns the current configuration.
-//
-// It first tries to load it from settings. If no settings is installed, or if
-// there is no configuration in settings, defaultConfig is returned.
-func getConfig(c context.Context) *Config {
-	cfg := Config{}
-	switch err := settings.Get(c, baseName, &cfg); err {
-	case nil:
-		break
-	case settings.ErrNoSettings:
-		// Defaults.
-		cfg = defaultConfig
-	default:
-		panic(fmt.Errorf("could not fetch Tumble settings - %s", err))
-	}
-	return &cfg
-}
diff --git a/tumble/configs/README.md b/tumble/configs/README.md
deleted file mode 100644
index 5da6649..0000000
--- a/tumble/configs/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-## Tumble Configuration Files
-
-This directory contains configuration files for `luci_deploy`.
-
-### Task Queue
-
-The task queue configuration files (`tq_shards_*`) configure the Tumble task
-queue. As Tumble accumulates mutations, it adds tasks to the task queue. The
-queue throughput is a function of Tumble's active configuration, namely the
-number of shards, the number of namespaces, and TemporalRoundFactor that is
-employed.
diff --git a/tumble/doc.go b/tumble/doc.go
deleted file mode 100644
index 2aed748..0000000
--- a/tumble/doc.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package tumble is a distributed multi-stage transaction processor for
-// appengine.
-//
-// What it is
-//
-// Tumble allows you to make multi-entity-group transaction chains, even when
-// you need to affect more than the number of entities allowed by appengine
-// (currently capped at 25 entity groups). These chains can be transactionally
-// started from a single entity group, and will process 'in the background'.
-// Tumble guarantees that once a transaction chain starts, it will eventually
-// complete, though it makes no guarantees of how long that might take.
-//
-// This can be used for doing very large-scale fan-out, and also for large-scale
-// fan-in.
-//
-// How it works
-//
-// An app using tumble declares one or more Mutation object. These objects
-// are responsible for enacting a single link in the transaction chain, and
-// may affect entities within a single entity group. Mutations must be
-// idempotent (they will occasionally be run more than once). Mutations
-// primarially implement a RollForward method which transactionally manipulates
-// an entity, and then returns zero or more Mutations (which may be for other
-// entities). Tumble's task queues and/or cron job (see Setup), will eventually
-// pick up these new Mutations and process them, possibly introducing more
-// Mutations, etc.
-//
-// When the app wants to begin a transaction chain, it uses
-// tumble.EnterTransaction, allows the app to transactionally manipulate the
-// starting entity, and also return one or more Mutation objects. If
-// the transaction is successful, EnterTransaction will also fire off any
-// necessary taskqueue tasks to process the new mutations in the background.
-//
-// When the transaction is committed, it's committed along with all the
-// Mutations it produced. Either they're all committed successfully (and so
-// the tumble transaction chain is started), or none of them are committed.
-//
-// Required Setup
-//
-// There are a couple prerequisites for using tumble.
-//
-// 1. You must register the tumble routes in your appengine module. You can do
-// this like:
-//
-//   import (
-//     "net/http"
-//
-//     "github.com/julienschmidt/httprouter"
-//     "go.chromium.org/luci/appengine/gaemiddleware"
-//     "go.chromium.org/luci/tumble"
-//   )
-//
-//   var tumbleService = tumble.Service{}
-//
-//   def init() {
-//     router := httprouter.New()
-//     tumbleService.InstallHandlers(router, gaemiddleware.BaseProd())
-//     http.Handle("/", router)
-//   }
-//
-// Make sure /internal/tumble routes in app.yaml (and/or dispatch.yaml) point
-// to the module with the Tumble. Additionally, make sure Tumble routes are
-// protected with `login: admin`, as they should never be accessed from
-// non-backend processes.
-//
-// For example:
-//
-//   handlers:
-//   - url: /internal/tumble/.*
-//     script: _go_app
-//     secure: always
-//     login: admin
-//
-// 2. You must add the following index to your index.yaml:
-//
-//   - kind: tumble.Mutation
-//     properties:
-//     - name: ExpandedShard
-//     - name: TargetRoot
-//
-// 2a. If you enable DelayedMutations in your configuration, you must also add
-//   - kind: tumble.Mutation
-//     properties:
-//     - name: TargetRoot
-//     - name: ProcessAfter
-//
-// 3. You must add a new taskqueue for tumble (example parameters):
-//
-//   - name: tumble
-//     rate: 32/s
-//     bucket_size: 32
-//     retry_parameters:
-//       task_age_limit: 2m   # aggressive task age pruning is desirable
-//       min_backoff_seconds: 2
-//       max_backoff_seconds: 6
-//       max_doublings: 7     # tops out at 2**(6 - 1) * 2 == 128 sec
-//
-// 4. All Mutation implementations must be registered at init() time using
-// tumble.Register((*MyMutation)(nil)).
-//
-// Optional Setup
-//
-// You may choose to add a new cron entry. This prevents work from slipping
-// through the cracks. If your app has constant tumble throughput and good key
-// distribution, this is not necessary.
-//
-//   - description: tumble fire_all_tasks invocation
-//     url: /internal/tumble/fire_all_tasks
-//     schedule: every 5 minutes  # maximum task latency you can tolerate.
-package tumble
diff --git a/tumble/example_test.go b/tumble/example_test.go
deleted file mode 100644
index 6281d9e..0000000
--- a/tumble/example_test.go
+++ /dev/null
@@ -1,602 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"bytes"
-	"context"
-	"encoding/base64"
-	"encoding/gob"
-	"fmt"
-	"sort"
-	"strings"
-	"testing"
-	"time"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/clock/testclock"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/logging/memlogger"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/info"
-	"go.chromium.org/luci/tumble/bitfield"
-
-	. "github.com/smartystreets/goconvey/convey"
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-type User struct {
-	Name string `gae:"$id"`
-}
-
-type TimeoutMessageSend struct {
-	Out       *ds.Key
-	WaitUntil time.Time
-}
-
-func (t *TimeoutMessageSend) ProcessAfter() time.Time { return t.WaitUntil }
-func (t *TimeoutMessageSend) HighPriority() bool      { return false }
-
-func (t *TimeoutMessageSend) Root(context.Context) *ds.Key {
-	return t.Out.Root()
-}
-
-func (t *TimeoutMessageSend) RollForward(c context.Context) ([]Mutation, error) {
-	logging.Warningf(c, "TimeoutMessageSend.RollForward(%s)", t.Out)
-	out := &OutgoingMessage{}
-	ds.PopulateKey(out, t.Out)
-	if err := ds.Get(c, out); err != nil {
-		return nil, err
-	}
-	if out.Notified || out.TimedOut {
-		return nil, nil
-	}
-	out.TimedOut = true
-	return nil, ds.Put(c, out)
-}
-
-type WriteMessage struct {
-	Out *OutgoingMessage
-}
-
-func (w *WriteMessage) Root(context.Context) *ds.Key {
-	return w.Out.FromUser
-}
-
-func (w *WriteMessage) RollForward(c context.Context) ([]Mutation, error) {
-	if err := ds.Put(c, w.Out); err != nil {
-		return nil, err
-	}
-	outKey := ds.KeyForObj(c, w.Out)
-	muts := make([]Mutation, len(w.Out.Recipients))
-	for i, p := range w.Out.Recipients {
-		muts[i] = &SendMessage{outKey, p, time.Time{}}
-		if p == "slowmojoe" {
-			muts[i].(*SendMessage).WaitUntil = clock.Now(c).Add(10 * time.Minute)
-		}
-	}
-	return muts, PutNamedMutations(c, outKey, map[string]Mutation{
-		"timeout": &TimeoutMessageSend{outKey, clock.Now(c).Add(5 * time.Minute)},
-	})
-}
-
-func (u *User) MakeOutgoingMessage(c context.Context, msg string, toUsers ...string) *OutgoingMessage {
-	sort.Strings(toUsers)
-
-	return &OutgoingMessage{
-		FromUser:   ds.KeyForObj(c, u),
-		Message:    msg,
-		Recipients: toUsers,
-		Success:    bitfield.Make(uint32(len(toUsers))),
-		Failure:    bitfield.Make(uint32(len(toUsers))),
-	}
-}
-
-func (u *User) SendMessage(c context.Context, msg string, toUsers ...string) (*OutgoingMessage, error) {
-	outMsg := u.MakeOutgoingMessage(c, msg, toUsers...)
-
-	err := RunMutation(c, &WriteMessage{outMsg})
-	if err != nil {
-		outMsg = nil
-	}
-	return outMsg, err
-}
-
-type OutgoingMessage struct {
-	// datastore-assigned
-	ID       int64   `gae:"$id"`
-	FromUser *ds.Key `gae:"$parent"`
-
-	Message    string   `gae:",noindex"`
-	Recipients []string `gae:",noindex"`
-
-	Success bitfield.BitField
-	Failure bitfield.BitField
-
-	Notified bool
-	TimedOut bool
-}
-
-type IncomingMessage struct {
-	// OtherUser|OutgoingMessageID
-	ID      string  `gae:"$id"`
-	ForUser *ds.Key `gae:"$parent"`
-}
-
-type SendMessage struct {
-	Message   *ds.Key
-	ToUser    string
-	WaitUntil time.Time
-}
-
-func (m *SendMessage) Root(ctx context.Context) *ds.Key {
-	return ds.KeyForObj(ctx, &User{Name: m.ToUser})
-}
-
-func (m *SendMessage) ProcessAfter() time.Time { return m.WaitUntil }
-func (m *SendMessage) HighPriority() bool      { return false }
-
-func (m *SendMessage) RollForward(c context.Context) ([]Mutation, error) {
-	u := &User{Name: m.ToUser}
-	if err := ds.Get(c, u); err != nil {
-		if err == ds.ErrNoSuchEntity {
-			return []Mutation{&WriteReceipt{m.Message, m.ToUser, false}}, nil
-		}
-		return nil, err
-	}
-	im := &IncomingMessage{
-		ID:      fmt.Sprintf("%s|%d", m.Message.Parent().StringID(), m.Message.IntID()),
-		ForUser: ds.KeyForObj(c, &User{Name: m.ToUser}),
-	}
-	err := ds.Get(c, im)
-	if err == ds.ErrNoSuchEntity {
-		err = ds.Put(c, im)
-		return []Mutation{&WriteReceipt{m.Message, m.ToUser, true}}, err
-	}
-	return nil, err
-}
-
-type WriteReceipt struct {
-	Message   *ds.Key
-	Recipient string
-	Success   bool
-}
-
-func (w *WriteReceipt) Root(ctx context.Context) *ds.Key {
-	return w.Message.Root()
-}
-
-func (w *WriteReceipt) RollForward(c context.Context) ([]Mutation, error) {
-	m := &OutgoingMessage{ID: w.Message.IntID(), FromUser: w.Message.Parent()}
-	if err := ds.Get(c, m); err != nil {
-		return nil, err
-	}
-
-	idx := uint32(sort.SearchStrings(m.Recipients, w.Recipient))
-	if w.Success {
-		m.Success.Set(idx)
-	} else {
-		m.Failure.Set(idx)
-	}
-
-	err := ds.Put(c, m)
-	if err != nil {
-		return nil, err
-	}
-
-	if m.Success.CountSet()+m.Failure.CountSet() == uint32(len(m.Recipients)) {
-		err := CancelNamedMutations(c, w.Message, "timeout")
-		muts := []Mutation{&ReminderMessage{
-			w.Message, m.FromUser.StringID(), clock.Now(c).UTC().Add(time.Minute * 5)},
-		}
-		return muts, err
-	}
-
-	return nil, nil
-}
-
-type ReminderMessage struct {
-	Message   *ds.Key
-	Recipient string
-	When      time.Time
-}
-
-var _ DelayedMutation = (*ReminderMessage)(nil)
-var _ DelayedMutation = (*TimeoutMessageSend)(nil)
-var _ DelayedMutation = (*SendMessage)(nil)
-
-func (r *ReminderMessage) Root(ctx context.Context) *ds.Key {
-	return r.Message.Root()
-}
-
-func (r *ReminderMessage) RollForward(c context.Context) ([]Mutation, error) {
-	m := &OutgoingMessage{}
-	ds.PopulateKey(m, r.Message)
-	if err := ds.Get(c, m); err != nil {
-		return nil, err
-	}
-	if m.Notified {
-		return nil, nil
-	}
-	m.Notified = true
-	return nil, ds.Put(c, m)
-}
-
-func (r *ReminderMessage) HighPriority() bool      { return false }
-func (r *ReminderMessage) ProcessAfter() time.Time { return r.When }
-
-// Embedder is just to prove that gob doesn't flip out when serializing
-// Mutations within Mutations now. Presumably in a real instance of this you
-// would have some other fields and do some general bookkeeping in Root() before
-// returning Next from RollForward.
-type Embedder struct {
-	Next Mutation
-}
-
-func (*Embedder) Root(c context.Context) *ds.Key {
-	return ds.MakeKey(c, "GeneralBookkeeping", 1)
-}
-
-func (e *Embedder) RollForward(context.Context) ([]Mutation, error) {
-	// do something inside of Root()
-	return []Mutation{e.Next}, nil
-}
-
-// NotRegistered is just to prove that gob does flip out if we don't
-// gob.Register Mutations
-type NotRegistered struct{}
-
-func (*NotRegistered) Root(c context.Context) *ds.Key                  { return nil }
-func (*NotRegistered) RollForward(context.Context) ([]Mutation, error) { return nil, nil }
-
-func init() {
-	Register((*Embedder)(nil))
-	Register((*ReminderMessage)(nil))
-	Register((*SendMessage)(nil))
-	Register((*TimeoutMessageSend)(nil))
-	Register((*WriteMessage)(nil))
-	Register((*WriteReceipt)(nil))
-}
-
-func shouldHaveLogMessage(actual interface{}, expected ...interface{}) string {
-	l := actual.(*memlogger.MemLogger)
-	if len(expected) != 1 {
-		panic("expected must contain a single string")
-	}
-	exp := expected[0].(string)
-
-	msgs := l.Messages()
-	msgText := make([]string, len(msgs))
-	for i, msg := range msgs {
-		msgText[i] = msg.Msg
-	}
-	return ShouldContainSubstring(strings.Join(msgText, "\n"), exp)
-}
-
-func testHighLevelImpl(t *testing.T, namespaces []string) {
-	Convey("Tumble", t, func() {
-
-		Convey("Check registration", func() {
-			So(registry, ShouldContainKey, "*tumble.SendMessage")
-
-			Convey("registered mutations can be embedded within each other", func() {
-				buf := &bytes.Buffer{}
-				enc := gob.NewEncoder(buf)
-				So(enc.Encode(&Embedder{&WriteMessage{}}), ShouldBeNil)
-				So(enc.Encode(&Embedder{&NotRegistered{}}), ShouldErrLike,
-					"type not registered for interface")
-			})
-		})
-
-		Convey("Good", func() {
-			testing := &Testing{}
-			testing.Service.Namespaces = func(context.Context) ([]string, error) { return namespaces, nil }
-
-			ctx := testing.Context()
-
-			forEachNS := func(c context.Context, fn func(context.Context, int)) {
-				for i, ns := range namespaces {
-					fn(info.MustNamespace(c, ns), i)
-				}
-			}
-
-			outMsgs := make([]*OutgoingMessage, len(namespaces))
-
-			l := logging.Get(ctx).(*memlogger.MemLogger)
-
-			charlie := &User{Name: "charlie"}
-			forEachNS(ctx, func(ctx context.Context, i int) {
-				So(ds.Put(ctx, charlie), ShouldBeNil)
-			})
-
-			// gctx is a default-namespace Context for global operations.
-			gctx := ctx
-
-			Convey("can't send to someone who doesn't exist", func() {
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					var err error
-					outMsgs[i], err = charlie.SendMessage(ctx, "Hey there", "lennon")
-					So(err, ShouldBeNil)
-				})
-
-				testing.DrainAll(ctx)
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					So(ds.Get(ctx, outMsgs[i]), ShouldBeNil)
-					So(outMsgs[i].Failure.All(true), ShouldBeTrue)
-				})
-			})
-
-			Convey("sending to yourself could be done in one iteration", func() {
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					var err error
-					outMsgs[i], err = charlie.SendMessage(ctx, "Hey there", "charlie")
-					So(err, ShouldBeNil)
-				})
-
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldBeGreaterThan, 0)
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					So(ds.Get(ctx, outMsgs[i]), ShouldBeNil)
-					So(outMsgs[i].Success.All(true), ShouldBeTrue)
-				})
-			})
-
-			Convey("different version IDs log a warning", func() {
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					var err error
-					outMsgs[i], err = charlie.SendMessage(ctx, "Hey there", "charlie")
-					So(err, ShouldBeNil)
-
-					rm := &realMutation{
-						ID:     "0000000000000001_00000000_00000000",
-						Parent: ds.KeyForObj(ctx, charlie),
-					}
-					So(ds.Get(ctx, rm), ShouldBeNil)
-					So(rm.Version, ShouldEqual, "testVersionID")
-					rm.Version = "otherCodeVersion"
-					So(ds.Put(ctx, rm), ShouldBeNil)
-				})
-
-				l.Reset()
-				testing.DrainAll(ctx)
-				So(l, shouldHaveLogMessage, "loading mutation with different code version")
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					So(ds.Get(ctx, outMsgs[i]), ShouldBeNil)
-					So(outMsgs[i].Success.All(true), ShouldBeTrue)
-				})
-			})
-
-			Convey("sending to 100 people is no big deal", func() {
-				ds.GetTestable(gctx).Consistent(false)
-
-				users := make([]User, 100)
-				recipients := make([]string, len(users))
-				for i := range recipients {
-					name := base64.StdEncoding.EncodeToString([]byte{byte(i)})
-					recipients[i] = name
-					users[i].Name = name
-				}
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					So(ds.Put(ctx, users), ShouldBeNil)
-
-					var err error
-					outMsgs[i], err = charlie.SendMessage(ctx, "Hey there", recipients...)
-					So(err, ShouldBeNil)
-				})
-
-				// do all the SendMessages
-				ds.GetTestable(gctx).CatchupIndexes()
-				testing.AdvanceTime(ctx)
-				testing.IterateAll(ctx)
-
-				// do all the WriteReceipts
-				l.Reset()
-				ds.GetTestable(gctx).CatchupIndexes()
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldBeGreaterThan, 0)
-
-				// hacky proof that all 100 incoming message receipts were buffered
-				// appropriately, +1 for the outgoing tail call, which will be processed
-				// immediately since delayed mutations are not enabled.
-				So(l, shouldHaveLogMessage, "successfully processed 101 mutations (1 tail-call), delta 0")
-				// And the counter passed in to keep track of things should also match.
-				So(l, shouldHaveLogMessage, "cumulatively processed 101 items with 0 errors(s) and 0 transient error(s)")
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					So(ds.Get(ctx, outMsgs[i]), ShouldBeNil)
-					So(outMsgs[i].Success.All(true), ShouldBeTrue)
-					So(outMsgs[i].Success.Size(), ShouldEqual, len(users))
-				})
-			})
-
-			Convey("delaying messages works", func() {
-				ds.GetTestable(gctx).Consistent(false)
-				cfg := testing.Config(ctx)
-				cfg.DelayedMutations = true
-				testing.UpdateSettings(ctx, cfg)
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					So(ds.Put(ctx,
-						&User{"recipient"},
-					), ShouldBeNil)
-				})
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					var err error
-					outMsgs[i], err = charlie.SendMessage(ctx, "Hey there", "recipient")
-					So(err, ShouldBeNil)
-				})
-
-				// do all the SendMessages
-				l.Reset()
-				ds.GetTestable(gctx).CatchupIndexes()
-				testing.AdvanceTime(ctx)
-
-				// forgot to add the extra index!
-				So(func() { testing.IterateAll(ctx) }, ShouldPanic)
-				So(l, shouldHaveLogMessage, "Insufficient indexes")
-
-				ds.GetTestable(gctx).AddIndexes(&ds.IndexDefinition{
-					Kind: "tumble.Mutation",
-					SortBy: []ds.IndexColumn{
-						{Property: "TargetRoot"},
-						{Property: "ProcessAfter"},
-					},
-				})
-				ds.GetTestable(gctx).CatchupIndexes()
-
-				So(testing.IterateAll(ctx), ShouldBeGreaterThan, 0)
-
-				// do all the WriteReceipts
-				ds.GetTestable(gctx).CatchupIndexes()
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldBeGreaterThan, 0)
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					So(ds.Get(ctx, outMsgs[i]), ShouldBeNil)
-					So(outMsgs[i].Success.All(true), ShouldBeTrue)
-					So(outMsgs[i].Success.Size(), ShouldEqual, 1)
-					So(outMsgs[i].Notified, ShouldBeFalse)
-				})
-
-				// Running another iteration should find nothing
-				l.Reset()
-				ds.GetTestable(gctx).CatchupIndexes()
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldEqual, 0)
-				So(l, shouldHaveLogMessage, "skipping task: ETA(0001-02-03 04:10:24 +0000 UTC)")
-
-				// Now it'll find something
-				ds.GetTestable(gctx).CatchupIndexes()
-				clock.Get(ctx).(testclock.TestClock).Add(time.Minute * 5)
-				So(testing.IterateAll(ctx), ShouldBeGreaterThan, 0)
-
-				forEachNS(ctx, func(ctx context.Context, i int) {
-					So(ds.Get(ctx, outMsgs[i]), ShouldBeNil)
-					So(outMsgs[i].Notified, ShouldBeTrue)
-				})
-			})
-
-			Convey("named mutations work", func() {
-				if len(namespaces) > 1 {
-					// Disable this test for multi-namespace case.
-					return
-				}
-
-				testing.EnableDelayedMutations(ctx)
-
-				So(ds.Put(gctx,
-					&User{"recipient"},
-					&User{"slowmojoe"},
-				), ShouldBeNil)
-
-				outMsg, err := charlie.SendMessage(ctx, "Hey there", "recipient", "slowmojoe")
-				So(err, ShouldBeNil)
-
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldEqual, 1) // sent to "recipient"
-
-				testing.AdvanceTime(ctx)
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldEqual, 1) // receipt from "recipient"
-
-				clock.Get(ctx).(testclock.TestClock).Add(time.Minute * 5)
-				So(testing.IterateAll(ctx), ShouldEqual, 1) // timeout!
-				So(l.HasFunc(func(ent *memlogger.LogEntry) bool {
-					return strings.Contains(ent.Msg, "TimeoutMessageSend")
-				}), ShouldBeTrue)
-
-				So(ds.Get(gctx, outMsg), ShouldBeNil)
-				So(outMsg.TimedOut, ShouldBeTrue)
-				So(outMsg.Notified, ShouldBeFalse)
-				So(outMsg.Success.CountSet(), ShouldEqual, 1)
-
-				clock.Get(ctx).(testclock.TestClock).Add(time.Minute * 5)
-				So(testing.IterateAll(ctx), ShouldEqual, 1) // WriteReceipt slowmojoe
-
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldEqual, 1) // Notification submitted
-				So(ds.Get(gctx, outMsg), ShouldBeNil)
-				So(outMsg.Failure.CountSet(), ShouldEqual, 0)
-				So(outMsg.Success.CountSet(), ShouldEqual, 2)
-
-				testing.AdvanceTime(ctx)
-				clock.Get(ctx).(testclock.TestClock).Add(time.Minute * 5)
-				So(testing.IterateAll(ctx), ShouldEqual, 1) // ReminderMessage set
-				So(ds.Get(gctx, outMsg), ShouldBeNil)
-				So(outMsg.Notified, ShouldBeTrue)
-
-			})
-
-			Convey("can cancel named mutations", func() {
-				if len(namespaces) > 1 {
-					// Disable this test for multi-namespace case.
-					return
-				}
-
-				testing.EnableDelayedMutations(ctx)
-
-				So(ds.Put(gctx,
-					&User{"recipient"},
-					&User{"other"},
-				), ShouldBeNil)
-
-				outMsg, err := charlie.SendMessage(ctx, "Hey there", "recipient", "other")
-				So(err, ShouldBeNil)
-
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldEqual, 2) // sent to "recipient" and "other"
-
-				testing.AdvanceTime(ctx)
-				testing.AdvanceTime(ctx)
-				So(testing.IterateAll(ctx), ShouldEqual, 1) // receipt from "recipient" and "other", Notification pending
-
-				testing.AdvanceTime(ctx)
-				clock.Get(ctx).(testclock.TestClock).Add(time.Minute * 5)
-				So(testing.IterateAll(ctx), ShouldEqual, 2) // ReminderMessage set
-
-				clock.Get(ctx).(testclock.TestClock).Add(time.Minute * 5)
-				So(testing.IterateAll(ctx), ShouldEqual, 0) // Nothing else
-
-				So(ds.Get(gctx, outMsg), ShouldBeNil)
-				So(outMsg.TimedOut, ShouldBeFalse)
-				So(outMsg.Notified, ShouldBeTrue)
-				So(outMsg.Success.CountSet(), ShouldEqual, 2)
-
-				So(l.HasFunc(func(ent *memlogger.LogEntry) bool {
-					return strings.Contains(ent.Msg, "TimeoutMessageSend")
-				}), ShouldBeFalse)
-			})
-
-		})
-
-	})
-}
-
-func TestHighLevelSingleNamespace(t *testing.T) {
-	t.Parallel()
-
-	testHighLevelImpl(t, []string{""})
-}
-
-func TestHighLevelMultiNamespace(t *testing.T) {
-	t.Parallel()
-
-	testHighLevelImpl(t, []string{"foo", "bar.baz_qux"})
-}
diff --git a/tumble/fire_tasks.go b/tumble/fire_tasks.go
deleted file mode 100644
index e370d5a..0000000
--- a/tumble/fire_tasks.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"fmt"
-	"math"
-	"strings"
-	"time"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/info"
-	tq "go.chromium.org/luci/gae/service/taskqueue"
-)
-
-type timestamp int64
-
-const minTS timestamp = math.MinInt64
-
-func (t timestamp) Unix() time.Time {
-	return time.Unix((int64)(t), 0).UTC()
-}
-
-func mkTimestamp(cfg *Config, t time.Time) timestamp {
-	trf := time.Duration(cfg.TemporalRoundFactor)
-	eta := t.UTC().Add(time.Duration(cfg.TemporalMinDelay) + trf).Round(trf)
-	return timestamp(eta.Unix())
-}
-
-type taskShard struct {
-	shard uint64
-	time  timestamp
-}
-
-func fireTasks(c context.Context, cfg *Config, shards map[taskShard]struct{}, loop bool) bool {
-	if len(shards) == 0 {
-		return true
-	}
-
-	nextSlot := mkTimestamp(cfg, clock.Now(c).UTC())
-	logging.Fields{
-		"slot": nextSlot,
-	}.Debugf(c, "got next slot")
-
-	tasks := make([]*tq.Task, 0, len(shards))
-
-	// Transform our namespace into a valid task queue task name.
-	ns := info.GetNamespace(c)
-	taskNS := nsToTaskName(ns)
-
-	for shard := range shards {
-		eta := nextSlot
-		if cfg.DelayedMutations && shard.time > eta {
-			eta = shard.time
-		}
-
-		// Generate our task name.
-		//
-		// Fold namespace into the task name, since task names must be unique across
-		// all namespaces.
-		taskName := fmt.Sprintf("%d_%s_%d", eta, taskNS, shard.shard)
-		if !loop {
-			// Differentiate non-loop (cron) tasks from loop (Mutation-scheduled)
-			// tasks so we don't supplant a long-running task with a cron task due to
-			// timing.
-			taskName += "_single"
-		}
-
-		tsk := &tq.Task{
-			Name: taskName,
-			Path: processURL(eta, shard.shard, ns, loop),
-			ETA:  eta.Unix(),
-
-			// TODO(riannucci): Tune RetryOptions?
-		}
-		tasks = append(tasks, tsk)
-		logging.Infof(c, "added task %q %s %s", tsk.Name, tsk.Path, tsk.ETA)
-	}
-
-	if err := errors.Filter(tq.Add(ds.WithoutTransaction(c), baseName, tasks...), tq.ErrTaskAlreadyAdded); err != nil {
-		logging.Warningf(c, "attempted to fire tasks %v, but failed: %s", shards, err)
-		return false
-	}
-	return true
-}
-
-// nsToTaskName flattens a namespace into a string that can be part of a valid
-// task queue task name.
-func nsToTaskName(v string) string {
-	// Escape single underscores in the namespace name.
-	v = strings.Replace(v, "_", "__", -1)
-
-	// Replace any invalid task queue name characters with underscore.
-	return strings.Map(func(r rune) rune {
-		switch {
-		case (r >= 'a' && r <= 'z'),
-			(r >= 'A' && r <= 'Z'),
-			r == '_', r == '-':
-			return r
-		default:
-			return '_'
-		}
-	}, v)
-}
diff --git a/tumble/fire_tasks_test.go b/tumble/fire_tasks_test.go
deleted file mode 100644
index f055bda..0000000
--- a/tumble/fire_tasks_test.go
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"math"
-	"net/http"
-	"testing"
-	"time"
-
-	"go.chromium.org/luci/common/clock/testclock"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/logging/memlogger"
-
-	"go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/info"
-	tq "go.chromium.org/luci/gae/service/taskqueue"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestShardCalculation(t *testing.T) {
-	t.Parallel()
-
-	Convey("shard calculation", t, func() {
-		tt := &Testing{}
-		ctx := tt.Context()
-		cfg := tt.Config(ctx)
-		cfg.NumShards = 11
-		tt.UpdateSettings(ctx, cfg)
-
-		l := logging.Get(ctx).(*memlogger.MemLogger)
-
-		Convey("ExpandedShard->Shard covers the full int64 range", func() {
-			tcs := []struct {
-				es int64
-				s  uint64
-			}{
-				{math.MinInt64, 0},
-				{0, cfg.NumShards / 2},
-				{math.MaxInt64, cfg.NumShards - 1},
-			}
-
-			for _, tc := range tcs {
-				So((&realMutation{ExpandedShard: tc.es, TargetRoot: &datastore.Key{}}).shard(cfg).shard, ShouldEqual, tc.s)
-				low, high := expandedShardBounds(ctx, cfg, tc.s)
-				So(tc.es, ShouldBeGreaterThanOrEqualTo, low)
-				So(tc.es, ShouldBeLessThanOrEqualTo, high)
-				So(l.Messages(), ShouldBeEmpty)
-			}
-		})
-
-		Convey("expandedShardsPerShard returns crossed ranges on shard reduction", func() {
-			low, high := expandedShardBounds(ctx, cfg, 256)
-			So(low, ShouldBeGreaterThan, high)
-			So(l, memlogger.ShouldHaveLog, logging.Warning, "Invalid shard: 256")
-		})
-	})
-}
-
-func TestFireTasks(t *testing.T) {
-	t.Parallel()
-
-	Convey("fireTasks works as expected", t, func() {
-		tt := &Testing{}
-		ctx := tt.Context()
-
-		Convey("empty", func() {
-			So(fireTasks(ctx, tt.Config(ctx), nil, true), ShouldBeTrue)
-			So(len(tq.GetTestable(ctx).GetScheduledTasks()[baseName]), ShouldEqual, 0)
-		})
-
-		Convey("basic", func() {
-			So(fireTasks(ctx, tt.Config(ctx), map[taskShard]struct{}{
-				{2, minTS}: {},
-				{7, minTS}: {},
-
-				// since DelayedMutations is false, this timew will be reset
-				{5, mkTimestamp(tt.Config(ctx), testclock.TestTimeUTC.Add(time.Minute))}: {},
-			}, true), ShouldBeTrue)
-			So(tq.GetTestable(ctx).GetScheduledTasks()[baseName], ShouldResemble, map[string]*tq.Task{
-				"-62132730888__2": {
-					Name:   "-62132730888__2",
-					Method: "POST",
-					Path:   processURL(-62132730888, 2, "", true),
-					ETA:    testclock.TestTimeUTC.Add(6 * time.Second).Round(time.Second),
-				},
-				"-62132730888__7": {
-					Name:   "-62132730888__7",
-					Method: "POST",
-					Path:   processURL(-62132730888, 7, "", true),
-					ETA:    testclock.TestTimeUTC.Add(6 * time.Second).Round(time.Second),
-				},
-				"-62132730888__5": {
-					Name:   "-62132730888__5",
-					Method: "POST",
-					Path:   processURL(-62132730888, 5, "", true),
-					ETA:    testclock.TestTimeUTC.Add(6 * time.Second).Round(time.Second),
-				},
-			})
-		})
-
-		Convey("namespaced", func() {
-			ctx = info.MustNamespace(ctx, "foo.bar")
-			So(fireTasks(ctx, tt.Config(ctx), map[taskShard]struct{}{
-				{2, minTS}: {},
-			}, true), ShouldBeTrue)
-			So(tq.GetTestable(ctx).GetScheduledTasks()[baseName], ShouldResemble, map[string]*tq.Task{
-				"-62132730888_foo_bar_2": {
-					Name:   "-62132730888_foo_bar_2",
-					Method: "POST",
-					Header: http.Header{
-						"X-Appengine-Current-Namespace": []string{"foo.bar"},
-					},
-					Path: processURL(-62132730888, 2, "foo.bar", true),
-					ETA:  testclock.TestTimeUTC.Add(6 * time.Second).Round(time.Second),
-				},
-			})
-		})
-
-		Convey("delayed", func() {
-			cfg := tt.Config(ctx)
-			cfg.DelayedMutations = true
-			tt.UpdateSettings(ctx, cfg)
-			delayedTS := mkTimestamp(cfg, testclock.TestTimeUTC.Add(time.Minute*10))
-			So(fireTasks(ctx, cfg, map[taskShard]struct{}{
-				{1, delayedTS}: {},
-			}, true), ShouldBeTrue)
-			So(tq.GetTestable(ctx).GetScheduledTasks()[baseName], ShouldResemble, map[string]*tq.Task{
-				"-62132730288__1": {
-					Name:   "-62132730288__1",
-					Method: "POST",
-					Path:   processURL(-62132730288, 1, "", true),
-					ETA:    testclock.TestTimeUTC.Add(time.Minute * 10).Add(6 * time.Second).Round(time.Second),
-				},
-			})
-		})
-	})
-}
diff --git a/tumble/model_mutation.go b/tumble/model_mutation.go
deleted file mode 100644
index d080426..0000000
--- a/tumble/model_mutation.go
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"bytes"
-	"context"
-	"crypto/sha1"
-	"encoding/binary"
-	"encoding/gob"
-	"fmt"
-	"math"
-	"reflect"
-	"strings"
-	"sync"
-	"time"
-
-	"go.chromium.org/luci/appengine/meta"
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/tsmon/field"
-	"go.chromium.org/luci/common/tsmon/metric"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/info"
-)
-
-var registry = map[string]reflect.Type{}
-
-var metricCreated = metric.NewCounter(
-	"luci/tumble/mutations/created",
-	"The number of mutations created in tumble",
-	nil,
-	field.String("namespace"),
-)
-
-// Register allows |mut| to be played by the tumble backend. This should be
-// called at init() time once for every Mutation implementation.
-//
-// This will also gob.Register your mutation implementation.
-//
-// Example:
-//   Register((*MyMutationImpl)(nil))
-func Register(mut Mutation) {
-	gob.Register(mut)
-	t := reflect.TypeOf(mut)
-	registry[t.String()] = t
-}
-
-// Mutation is the interface that your tumble mutations must implement.
-//
-// Mutation implementations can be registered with the Register function.
-type Mutation interface {
-	// Root returns a datastore.Key which will be used to derive the Key for the
-	// entity group which this Mutation will operate on. This is used to batch
-	// together Entries for more efficient processing.
-	//
-	// Returning nil is an error.
-	Root(c context.Context) *ds.Key
-
-	// RollForward performs the action of the Mutation.
-	//
-	// It is only considered successful if it returns nil. If it returns non-nil,
-	// then it will be retried at a later time. If it never returns nil, then it
-	// will never be flushed from tumble's queue, and you'll have to manually
-	// delete it or fix the code so that it can be handled without error.
-	//
-	// This method runs inside of a single-group transaction. It must modify only
-	// the entity group specified by Root().
-	//
-	// As a side effect, RollForward may return new arbitrary Mutations. These
-	// will be committed in the same transaction as RollForward.
-	//
-	// The context contains an implementation of "luci/gae/service/datastore",
-	// using the "luci/gae/filter/txnBuf" transaction buffer. This means that
-	// all functionality (including additional transactions) is available, with
-	// the limitations mentioned by that package (notably, no cursors are
-	// allowed).
-	RollForward(c context.Context) ([]Mutation, error)
-}
-
-// DelayedMutation is a Mutation which allows you to defer its processing
-// until a certain absolute time.
-//
-// As a side effect, tumble will /mostly/ process items in their chronological
-// ProcessAfter order, instead of the undefined order.
-//
-// Your tumble configuration must have DelayedMutations set, and you must have
-// added the appropriate index to use these. If DelayedMutations is not set,
-// then tumble will ignore the ProcessAfter and HighPriorty values here, and
-// process mutations as quickly as possible in no particular order.
-type DelayedMutation interface {
-	Mutation
-
-	// ProcessAfter will be called once when scheduling this Mutation. The
-	// mutation will be recorded to datastore immediately, but tumble will skip it
-	// for processing until at least the time that's returned here. Multiple calls
-	// to this method should always return the same time.
-	//
-	// A Time value in the past will get reset to "next available time slot",
-	// unless HighPriority() returns true.
-	ProcessAfter() time.Time
-
-	// HighPriority indicates that this mutation should be processed before
-	// others, if possible, and must be set in conjunction with a ProcessAfter
-	// timestamp that occurs in the past.
-	//
-	// Tumble works by processing Mutations in the order of their creation, or
-	// ProcessAfter times, whichever is later. If HighPriority is true, then a
-	// ProcessAfter time in the past will take precedence over Mutations which
-	// may actually have been recorded after this one, in the event that tumble
-	// is processing tasks slower than they're being created.
-	HighPriority() bool
-}
-
-type realMutation struct {
-	// TODO(riannucci): add functionality to luci/gae/service/datastore so that
-	// GetMeta/SetMeta may be overridden by the struct.
-	_kind  string  `gae:"$kind,tumble.Mutation"`
-	ID     string  `gae:"$id"`
-	Parent *ds.Key `gae:"$parent"`
-
-	ExpandedShard int64
-	ProcessAfter  time.Time
-	TargetRoot    *ds.Key
-
-	Version string
-	Type    string
-	Data    []byte `gae:",noindex"`
-}
-
-func (r *realMutation) shard(cfg *Config) taskShard {
-	shardCount := cfg.TotalShardCount(r.TargetRoot.Namespace())
-	expandedShardsPerShard := math.MaxUint64 / shardCount
-	ret := uint64(r.ExpandedShard-math.MinInt64) / expandedShardsPerShard
-	// account for rounding errors on the last shard.
-	if ret >= shardCount {
-		ret = shardCount - 1
-	}
-	return taskShard{ret, mkTimestamp(cfg, r.ProcessAfter)}
-}
-
-func putMutations(c context.Context, cfg *Config, fromRoot *ds.Key, muts []Mutation, round uint64) (
-	shardSet map[taskShard]struct{}, mutKeys []*ds.Key, err error) {
-	if len(muts) == 0 {
-		return
-	}
-
-	version, err := meta.GetEntityGroupVersion(c, fromRoot)
-	if err != nil {
-		return
-	}
-
-	now := clock.Now(c).UTC()
-
-	shardSet = map[taskShard]struct{}{}
-	toPut := make([]*realMutation, len(muts))
-	mutKeys = make([]*ds.Key, len(muts))
-	for i, m := range muts {
-		id := fmt.Sprintf("%016x_%08x_%08x", version, round, i)
-		toPut[i], err = newRealMutation(c, cfg, id, fromRoot, m, now)
-		if err != nil {
-			logging.Errorf(c, "error creating real mutation for %v: %s", m, err)
-			return
-		}
-		mutKeys[i] = ds.KeyForObj(c, toPut[i])
-
-		shardSet[toPut[i].shard(cfg)] = struct{}{}
-	}
-
-	if err = ds.Put(c, toPut); err != nil {
-		logging.Errorf(c, "error putting %d new mutations: %s", len(toPut), err)
-	} else {
-		metricCreated.Add(c, int64(len(toPut)), fromRoot.Namespace())
-	}
-	return
-}
-
-var appVersion = struct {
-	sync.Once
-	version string
-}{}
-
-func getAppVersion(c context.Context) string {
-	appVersion.Do(func() {
-		appVersion.version = info.VersionID(c)
-
-		// AppEngine version is <app-yaml-version>.<unique-upload-id>
-		//
-		// The upload ID prevents version consistency between different AppEngine
-		// modules, which will necessarily have different IDs, so we base our
-		// comparable version off of the app.yaml-supplied value.
-		if idx := strings.LastIndex(appVersion.version, "."); idx > 0 {
-			appVersion.version = appVersion.version[:idx]
-		}
-	})
-	return appVersion.version
-}
-
-func newRealMutation(c context.Context, cfg *Config, id string, parent *ds.Key, m Mutation, now time.Time) (*realMutation, error) {
-	when := now
-	if cfg.DelayedMutations {
-		if dm, ok := m.(DelayedMutation); ok {
-			targetTime := dm.ProcessAfter()
-			if dm.HighPriority() || targetTime.After(now) {
-				when = targetTime
-			}
-		}
-	}
-
-	t := reflect.TypeOf(m).String()
-	if _, ok := registry[t]; !ok {
-		return nil, fmt.Errorf("Attempting to add unregistered mutation %v: %v", t, m)
-	}
-
-	buf := &bytes.Buffer{}
-	err := gob.NewEncoder(buf).Encode(m)
-	if err != nil {
-		return nil, err
-	}
-
-	root := m.Root(c).Root()
-
-	hash := sha1.Sum([]byte(root.Encode()))
-	eshard := int64(binary.BigEndian.Uint64(hash[:]))
-
-	return &realMutation{
-		ID:     id,
-		Parent: parent,
-
-		ExpandedShard: eshard,
-		ProcessAfter:  when,
-		TargetRoot:    root,
-
-		Version: getAppVersion(c),
-		Type:    t,
-		Data:    buf.Bytes(),
-	}, nil
-}
-
-func (r *realMutation) GetMutation() (Mutation, error) {
-	typ, ok := registry[r.Type]
-	if !ok {
-		return nil, fmt.Errorf("unable to load reflect.Type for %q", r.Type)
-	}
-
-	ret := reflect.New(typ)
-	if err := gob.NewDecoder(bytes.NewBuffer(r.Data)).DecodeValue(ret); err != nil {
-		return nil, err
-	}
-
-	return ret.Elem().Interface().(Mutation), nil
-}
diff --git a/tumble/process.go b/tumble/process.go
deleted file mode 100644
index 97e24de..0000000
--- a/tumble/process.go
+++ /dev/null
@@ -1,546 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"bytes"
-	"context"
-	"fmt"
-	"math"
-	"sync/atomic"
-	"time"
-
-	"go.chromium.org/luci/appengine/memlock"
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/data/stringset"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/retry/transient"
-	"go.chromium.org/luci/common/sync/parallel"
-	"go.chromium.org/luci/common/tsmon/field"
-	"go.chromium.org/luci/common/tsmon/metric"
-
-	"go.chromium.org/luci/gae/filter/txnBuf"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/info"
-	mc "go.chromium.org/luci/gae/service/memcache"
-)
-
-const (
-	// minNoWorkDelay is the minimum amount of time to sleep in between rounds if
-	// there was no work done in that round.
-	minNoWorkDelay = time.Second
-)
-
-var metricCompleted = metric.NewCounter(
-	"luci/tumble/mutations/completed",
-	"The number of mutations completed by tumble, but not necessarily deleted.",
-	nil,
-	field.String("namespace"),
-)
-
-var metricFailed = metric.NewCounter(
-	"luci/tumble/mutations/failed",
-	"The number of mutations attempted in tumble, but failed to complete.",
-	nil,
-	field.String("namespace"),
-)
-
-var metricDeleted = metric.NewCounter(
-	"luci/tumble/mutations/deleted",
-	"The number of mutations deleted by tumble.",
-	nil,
-	field.String("namespace"),
-)
-
-// expandedShardBounds returns the boundary of the expandedShard order that
-// currently corresponds to this shard number. If Shard is < 0 or > NumShards
-// (the currently configured number of shards), this will return a low > high.
-// Otherwise low < high.
-func expandedShardBounds(c context.Context, cfg *Config, shard uint64) (low, high int64) {
-	totalShards := cfg.TotalShardCount(info.GetNamespace(c))
-	if shard < 0 || uint64(shard) >= totalShards {
-		logging.Warningf(c, "Invalid shard: %d", shard)
-		// return inverted bounds
-		return 0, -1
-	}
-
-	expandedShardsPerShard := int64(math.MaxUint64 / totalShards)
-	low = math.MinInt64 + (int64(shard) * expandedShardsPerShard)
-	if uint64(shard) == totalShards-1 {
-		high = math.MaxInt64
-	} else {
-		high = low + expandedShardsPerShard
-	}
-	return
-}
-
-func processShardQuery(c context.Context, cfg *Config, shard uint64) *ds.Query {
-	low, high := expandedShardBounds(c, cfg, shard)
-	if low > high {
-		return nil
-	}
-
-	q := ds.NewQuery("tumble.Mutation").
-		Gte("ExpandedShard", low).Lte("ExpandedShard", high).
-		Project("TargetRoot").Distinct(true)
-
-	return q
-}
-
-// processShard is the tumble backend endpoint. This accepts a shard number
-// which is expected to be < GlobalConfig.NumShards.
-func processShard(c context.Context, cfg *Config, timestamp time.Time, shard uint64, loop bool) error {
-
-	logging.Fields{
-		"shard": shard,
-	}.Infof(c, "Processing tumble shard.")
-
-	q := processShardQuery(c, cfg, shard)
-	if q == nil {
-		logging.Warningf(c, "dead shard, quitting")
-		return nil
-	}
-
-	// Calculate our end itme. If we're not looping or we have a <= 0 duration,
-	// we will perform a single loop.
-	var endTime time.Time
-	if cfg.ProcessLoopDuration > 0 {
-		endTime = clock.Now(c).Add(time.Duration(cfg.ProcessLoopDuration))
-		logging.Debugf(c, "Process loop is configured to exit after [%s] at %s",
-			cfg.ProcessLoopDuration.String(), endTime)
-	}
-
-	// Lock around the shard that we are trying to modify.
-	//
-	// Since memcache is namespaced, we don't need to include the namespace in our
-	// lock name.
-	task := makeProcessTask(timestamp, endTime, shard, loop)
-	lockKey := fmt.Sprintf("%s.%d.lock", baseName, shard)
-	clientID := fmt.Sprintf("%d_%d_%s", timestamp.Unix(), shard, info.RequestID(c))
-
-	err := memlock.TryWithLock(c, lockKey, clientID, func(c context.Context) error {
-		return task.process(c, cfg, q)
-	})
-	if err == memlock.ErrFailedToLock {
-		logging.Infof(c, "Couldn't obtain lock (giving up): %s", err)
-		return nil
-	}
-	return err
-}
-
-// processTask is a stateful processing task.
-type processTask struct {
-	timestamp time.Time
-	endTime   time.Time
-	lastKey   string
-	banSets   map[string]stringset.Set
-	loop      bool
-}
-
-func makeProcessTask(timestamp, endTime time.Time, shard uint64, loop bool) *processTask {
-	return &processTask{
-		timestamp: timestamp,
-		endTime:   endTime,
-		lastKey:   fmt.Sprintf("%s.%d.last", baseName, shard),
-		banSets:   make(map[string]stringset.Set),
-		loop:      loop,
-	}
-}
-
-func (t *processTask) process(c context.Context, cfg *Config, q *ds.Query) error {
-	// this last key allows buffered tasks to early exit if some other shard
-	// processor has already processed past this task's target timestamp.
-	lastItm, err := mc.GetKey(c, t.lastKey)
-	if err != nil {
-		if err != mc.ErrCacheMiss {
-			logging.Warningf(c, "couldn't obtain last timestamp: %s", err)
-		}
-	} else {
-		val := lastItm.Value()
-		last, err := ds.Deserialize.Time(bytes.NewBuffer(val))
-		if err != nil {
-			logging.Warningf(c, "could not decode timestamp %v: %s", val, err)
-		} else {
-			last = last.Add(time.Duration(cfg.TemporalRoundFactor))
-			if last.After(t.timestamp) {
-				logging.Infof(c, "early exit, %s > %s", last, t.timestamp)
-				return nil
-			}
-		}
-	}
-	err = nil
-
-	// Loop until our shard processing session expires.
-	prd := processRoundDelay{
-		cfg: cfg,
-	}
-	prd.reset()
-
-	for {
-		var numProcessed, errCount, transientErrCount counter
-
-		// Run our query against a work pool.
-		//
-		// NO work pool methods will return errors, so there is no need to collect
-		// the result. Rather, any error that is encountered will atomically update
-		// the "errCount" counter (for non-transient errors) or "transientErrCount"
-		// counter (for transient errors).
-		_ = parallel.WorkPool(int(cfg.NumGoroutines), func(ch chan<- func() error) {
-			err := ds.Run(c, q, func(pm ds.PropertyMap) error {
-				root := pm.Slice("TargetRoot")[0].Value().(*ds.Key)
-				encRoot := root.Encode()
-
-				// TODO(riannucci): make banSets remove keys from the banSet which
-				// weren't hit. Once they stop showing up, they'll never show up
-				// again.
-
-				bs := t.banSets[encRoot]
-				if bs == nil {
-					bs = stringset.New(0)
-					t.banSets[encRoot] = bs
-				}
-				ch <- func() error {
-					switch err := processRoot(c, cfg, root, bs, &numProcessed); err {
-					case nil:
-						return nil
-
-					case ds.ErrConcurrentTransaction:
-						logging.Fields{
-							logging.ErrorKey: err,
-							"root":           root,
-						}.Warningf(c, "Transient error encountered processing root.")
-						transientErrCount.inc()
-						return nil
-
-					default:
-						logging.Fields{
-							logging.ErrorKey: err,
-							"root":           root,
-						}.Errorf(c, "Failed to process root.")
-						errCount.inc()
-						return nil
-					}
-				}
-
-				if err := c.Err(); err != nil {
-					logging.WithError(err).Warningf(c, "Context canceled (lost lock?).")
-					return ds.Stop
-				}
-				return nil
-			})
-			if err != nil {
-				var qstr string
-				if fq, err := q.Finalize(); err == nil {
-					qstr = fq.String()
-				}
-
-				logging.Fields{
-					logging.ErrorKey: err,
-					"query":          qstr,
-				}.Errorf(c, "Failure to run shard query.")
-				errCount.inc()
-			}
-		})
-
-		logging.Infof(c, "cumulatively processed %d items with %d errors(s) and %d transient error(s)",
-			numProcessed, errCount, transientErrCount)
-		switch {
-		case transientErrCount > 0:
-			return errors.New("transient error during shard processing", transient.Tag)
-		case errCount > 0:
-			return errors.New("encountered non-transient error during shard processing")
-		}
-
-		now := clock.Now(c)
-		didWork := numProcessed > 0
-		if didWork {
-			// Set our last key value for next round.
-			err = mc.Set(c, mc.NewItem(c, t.lastKey).SetValue(ds.Serialize.ToBytes(now.UTC())))
-			if err != nil {
-				logging.Warningf(c, "could not update last process memcache key %s: %s", t.lastKey, err)
-			}
-		} else if t.endTime.IsZero() || !t.loop {
-			// We didn't do any work this round, and we're configured for a single
-			// loop, so we're done.
-			logging.Debugf(c, "Configured for single loop.")
-			return nil
-		}
-
-		// If we're past our end time, then we're done.
-		if !t.endTime.IsZero() && now.After(t.endTime) {
-			logging.Debugf(c, "Exceeded our process loop time by [%s]; terminating loop.", now.Sub(t.endTime))
-			return nil
-		}
-
-		// Either we are looping, we did work last round, or both. Sleep in between
-		// processing rounds for a duration based on whether or not we did work.
-		delay := prd.next(didWork)
-		if delay > 0 {
-			// If we have an end time, and this delay would exceed that end time, then
-			// don't bother sleeping; we're done.
-			if !t.endTime.IsZero() && now.Add(delay).After(t.endTime) {
-				logging.Debugf(c, "Delay (%s) exceeds process loop time (%s); terminating loop.",
-					delay, t.endTime)
-				return nil
-			}
-
-			logging.Debugf(c, "Sleeping %s in between rounds...", delay)
-			if err := clock.Sleep(c, delay).Err; err != nil {
-				logging.WithError(err).Warningf(c, "Sleep interrupted, terminating loop.")
-				return nil
-			}
-		}
-	}
-}
-
-func getBatchByRoot(c context.Context, cfg *Config, root *ds.Key, banSet stringset.Set) ([]*realMutation, error) {
-	q := ds.NewQuery("tumble.Mutation").Eq("TargetRoot", root)
-	if cfg.DelayedMutations {
-		q = q.Lte("ProcessAfter", clock.Now(c).UTC())
-	}
-
-	fetchAllocSize := cfg.ProcessMaxBatchSize
-	if fetchAllocSize < 0 {
-		fetchAllocSize = 0
-	}
-	toFetch := make([]*realMutation, 0, fetchAllocSize)
-	err := ds.Run(c, q, func(k *ds.Key) error {
-		if !banSet.Has(k.Encode()) {
-			toFetch = append(toFetch, &realMutation{
-				ID:     k.StringID(),
-				Parent: k.Parent(),
-			})
-		}
-		if len(toFetch) < cap(toFetch) {
-			return nil
-		}
-		return ds.Stop
-	})
-	return toFetch, err
-}
-
-func loadFilteredMutations(c context.Context, rms []*realMutation) ([]*ds.Key, []Mutation, error) {
-	mutKeys := make([]*ds.Key, 0, len(rms))
-	muts := make([]Mutation, 0, len(rms))
-	err := ds.Get(c, rms)
-	me, ok := err.(errors.MultiError)
-	if !ok && err != nil {
-		return nil, nil, err
-	}
-
-	for i, rm := range rms {
-		err = nil
-		if me != nil {
-			err = me[i]
-		}
-		if err == nil {
-			if rm.Version != getAppVersion(c) {
-				logging.Fields{
-					"mut_version": rm.Version,
-					"cur_version": getAppVersion(c),
-				}.Warningf(c, "loading mutation with different code version")
-			}
-			m, err := rm.GetMutation()
-			if err != nil {
-				logging.Errorf(c, "couldn't load mutation: %s", err)
-				continue
-			}
-			muts = append(muts, m)
-			mutKeys = append(mutKeys, ds.KeyForObj(c, rm))
-		} else if err != ds.ErrNoSuchEntity {
-			return nil, nil, me
-		}
-	}
-
-	return mutKeys, muts, nil
-}
-
-type overrideRoot struct {
-	Mutation
-
-	root *ds.Key
-}
-
-func (o overrideRoot) Root(context.Context) *ds.Key {
-	return o.root
-}
-
-func processRoot(c context.Context, cfg *Config, root *ds.Key, banSet stringset.Set, cnt *counter) error {
-	l := logging.Get(c)
-
-	toFetch, err := getBatchByRoot(c, cfg, root, banSet)
-	switch {
-	case err != nil:
-		l.Errorf("Failed to get batch for root [%s]: %s", root, err)
-		return err
-	case len(toFetch) == 0:
-		return nil
-	}
-
-	mutKeys, muts, err := loadFilteredMutations(c, toFetch)
-	if err != nil {
-		return err
-	}
-
-	if c.Err() != nil {
-		l.Warningf("Lost lock during processRoot")
-		return nil
-	}
-
-	allShards := map[taskShard]struct{}{}
-
-	toDel := make([]*ds.Key, 0, len(muts))
-	var numMuts, deletedMuts, processedMuts int
-	err = ds.RunInTransaction(txnBuf.FilterRDS(c), func(c context.Context) error {
-		toDel = toDel[:0]
-		numMuts = 0
-		deletedMuts = 0
-		processedMuts = 0
-
-		iterMuts := muts
-		iterMutKeys := mutKeys
-
-		for i := 0; i < len(iterMuts); i++ {
-			m := iterMuts[i]
-
-			s := clock.Now(c)
-			logging.Fields{"m": m}.Infof(c, "running RollForward")
-			shards, newMuts, newMutKeys, err := enterTransactionMutation(c, cfg, overrideRoot{m, root}, uint64(i))
-			logging.Fields{"m": m}.Infof(c, "done RollForward, took %s", clock.Now(c).Sub(s))
-			if err != nil {
-				l.Errorf("Executing decoded gob(%T) failed: %q: %+v", m, err, m)
-				continue
-			}
-			processedMuts++
-
-			for j, nm := range newMuts {
-				if nm.Root(c).HasAncestor(root) {
-					runNow := !cfg.DelayedMutations
-					if !runNow {
-						dm, isDelayedMutation := nm.(DelayedMutation)
-						runNow = !isDelayedMutation || clock.Now(c).UTC().After(dm.ProcessAfter())
-					}
-					if runNow {
-						iterMuts = append(iterMuts, nm)
-						iterMutKeys = append(iterMutKeys, newMutKeys[j])
-					}
-				}
-			}
-
-			// Finished processing this Mutation.
-			key := iterMutKeys[i]
-			switch {
-			case key.HasAncestor(root):
-				// try to delete it as part of the same transaction.
-				if err := ds.Delete(c, key); err == nil {
-					deletedMuts++
-					break
-				}
-				fallthrough // Failed to delete, try again outside of the transaction.
-			default:
-				toDel = append(toDel, key)
-			}
-
-			numMuts += len(newMuts)
-			for shard := range shards {
-				allShards[shard] = struct{}{}
-			}
-		}
-
-		return nil
-	}, nil)
-	if err != nil {
-		l.Errorf("failed running transaction: %s", err)
-		metricFailed.Add(c, int64(numMuts), root.Namespace())
-		return err
-	}
-
-	fireTasks(c, cfg, allShards, true)
-	l.Debugf("successfully processed %d mutations (%d tail-call), delta %d",
-		processedMuts, deletedMuts, (numMuts - deletedMuts))
-	metricCompleted.Add(c, int64(processedMuts), root.Namespace())
-	// This is for the mutations deleted in a transaction.
-	metricDeleted.Add(c, int64(deletedMuts), root.Namespace())
-
-	cnt.add(processedMuts)
-	if len(toDel) > 0 {
-		for _, k := range toDel {
-			banSet.Add(k.Encode())
-		}
-		if err := ds.Delete(c, toDel); err != nil {
-			// This is categorized as failed because it's going to get retried again.
-			metricFailed.Add(c, int64(len(toDel)), root.Namespace())
-			l.Warningf("error deleting finished mutations: %s", err)
-		} else {
-			// This is for mutations deleted outside of the transaction,
-			// because they failed to delete the first time we tried to do it
-			// inside the transaction.
-			metricDeleted.Add(c, int64(len(toDel)), root.Namespace())
-		}
-	}
-
-	return nil
-}
-
-// counter is an atomic integer counter.
-//
-// When concurrent access is possible, a counter must only be manipulated with
-// its "inc" and "add" methods, and must not be read.
-//
-// We use an int32 because that is atomically safe across all architectures.
-type counter int32
-
-func (c *counter) inc() int      { return c.add(1) }
-func (c *counter) add(n int) int { return int(atomic.AddInt32((*int32)(c), int32(n))) }
-
-// processRoundDelay calculates the delay to impose in between processing
-// rounds.
-type processRoundDelay struct {
-	cfg       *Config
-	nextDelay time.Duration
-}
-
-func (prd *processRoundDelay) reset() {
-	// Reset our delay to DustSettleTimeout.
-	prd.nextDelay = time.Duration(prd.cfg.DustSettleTimeout)
-}
-
-func (prd *processRoundDelay) next(didWork bool) time.Duration {
-	if didWork {
-		// Reset our delay to DustSettleTimeout.
-		prd.reset()
-		return prd.nextDelay
-	}
-
-	delay := prd.nextDelay
-	if growth := prd.cfg.NoWorkDelayGrowth; growth > 1 {
-		prd.nextDelay *= time.Duration(growth)
-	}
-
-	if max := time.Duration(prd.cfg.MaxNoWorkDelay); max > 0 && delay > max {
-		delay = max
-
-		// Cap our "next delay" so it doesn't grow unbounded in the background.
-		prd.nextDelay = delay
-	}
-
-	// Enforce a no work lower bound.
-	if delay < minNoWorkDelay {
-		delay = minNoWorkDelay
-	}
-
-	return delay
-}
diff --git a/tumble/process_test.go b/tumble/process_test.go
deleted file mode 100644
index 903d732..0000000
--- a/tumble/process_test.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"fmt"
-	"testing"
-	"time"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/logging/memlogger"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	mc "go.chromium.org/luci/gae/service/memcache"
-)
-
-func TestTumbleFiddlyBits(t *testing.T) {
-	t.Parallel()
-
-	Convey("Fiddly bits", t, func() {
-		tt := &Testing{}
-		ctx := tt.Context()
-		l := logging.Get(ctx).(*memlogger.MemLogger)
-
-		Convey("early exit logic works", func() {
-			future := clock.Now(ctx).UTC().Add(time.Hour)
-			itm := mc.NewItem(ctx, fmt.Sprintf("%s.%d.last", baseName, 10)).SetValue(ds.Serialize.ToBytes(future))
-			So(mc.Set(ctx, itm), ShouldBeNil)
-
-			So(fireTasks(ctx, tt.Config(ctx), map[taskShard]struct{}{
-				{10, minTS}: {},
-			}, true), ShouldBeTrue)
-			tt.Drain(ctx)
-
-			So(l.Has(logging.Info,
-				"Processing tumble shard.", map[string]interface{}{"shard": uint64(10)}),
-				ShouldBeTrue)
-			So(l.Has(logging.Info,
-				"early exit, 0001-02-03 05:05:10 +0000 UTC > 0001-02-03 04:05:12 +0000 UTC", nil),
-				ShouldBeTrue)
-		})
-	})
-}
diff --git a/tumble/service.go b/tumble/service.go
deleted file mode 100644
index 0ef4e70..0000000
--- a/tumble/service.go
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"fmt"
-	"net/http"
-	"net/url"
-	"strconv"
-	"strings"
-	"time"
-
-	"go.chromium.org/luci/appengine/gaemiddleware"
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/retry/transient"
-	"go.chromium.org/luci/common/sync/parallel"
-	"go.chromium.org/luci/server/router"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/info"
-)
-
-const (
-	baseURL             = "/internal/" + baseName
-	fireAllTasksURL     = baseURL + "/fire_all_tasks"
-	processShardPattern = baseURL + "/process_shard/:shard_id/at/:timestamp"
-
-	transientHTTPHeader = "X-LUCI-Tumble-Transient"
-)
-
-// Service is an instance of a Tumble service. It installs its handlers into an
-// HTTP router and services Tumble request tasks.
-type Service struct {
-	// Namespaces is a function that returns the datastore namespaces that Tumble
-	// will poll.
-	//
-	// If nil, Tumble will be executed against all namespaces registered in the
-	// datastore.
-	Namespaces func(context.Context) ([]string, error)
-}
-
-// InstallHandlers installs http handlers.
-//
-// 'base' is usually gaemiddleware.BaseProd(), but can also be its derivative
-// if something else it needed in the context.
-func (s *Service) InstallHandlers(r *router.Router, base router.MiddlewareChain) {
-	// GET so that this can be invoked from cron
-	r.GET(fireAllTasksURL, base.Extend(gaemiddleware.RequireCron), s.FireAllTasksHandler)
-	r.POST(processShardPattern, base.Extend(gaemiddleware.RequireTaskQueue(baseName)),
-		func(ctx *router.Context) {
-			loop := ctx.Request.URL.Query().Get("single") == ""
-			s.ProcessShardHandler(ctx, loop)
-		})
-}
-
-// FireAllTasksHandler is an HTTP handler that expects `logging` and `luci/gae`
-// services to be installed into the context.
-//
-// FireAllTasksHandler verifies that it was called within an Appengine Cron
-// request, and then invokes the FireAllTasks function.
-func (s *Service) FireAllTasksHandler(c *router.Context) {
-	if err := s.FireAllTasks(c.Context); err != nil {
-		c.Writer.WriteHeader(http.StatusInternalServerError)
-		fmt.Fprintf(c.Writer, "fire_all_tasks failed: %s", err)
-	} else {
-		c.Writer.Write([]byte("ok"))
-	}
-}
-
-// FireAllTasks searches for work in all namespaces, and fires off a process
-// task for any shards it finds that have at least one Mutation present to
-// ensure that no work languishes forever. This may not be needed in
-// a constantly-loaded system with good tumble key distribution.
-func (s *Service) FireAllTasks(c context.Context) error {
-	cfg := getConfig(c)
-
-	namespaces, err := s.getNamespaces(c, cfg)
-	if err != nil {
-		return err
-	}
-
-	// Probe each namespace in parallel. Each probe function reports its own
-	// errors, so the work pool will never return any non-nil error response.
-	var errCount, taskCount counter
-	_ = parallel.WorkPool(cfg.NumGoroutines, func(ch chan<- func() error) {
-		for _, ns := range namespaces {
-			ns := ns
-			ch <- func() error {
-				// Generate a list of all shards.
-				allShards := make([]taskShard, 0, cfg.TotalShardCount(ns))
-				for i := uint64(0); i < cfg.TotalShardCount(ns); i++ {
-					allShards = append(allShards, taskShard{i, minTS})
-				}
-				s.fireAllTasksForNamespace(c, cfg, ns, allShards, &errCount, &taskCount)
-				return nil
-			}
-		}
-	})
-	if errCount > 0 {
-		logging.Errorf(c, "Encountered %d error(s).", errCount)
-		return errors.New("errors were encountered while probing for tasks")
-	}
-
-	logging.Debugf(c, "Successfully probed %d namespace(s) and fired %d tasks(s).",
-		len(namespaces), taskCount)
-	return err
-}
-
-func (s *Service) fireAllTasksForNamespace(c context.Context, cfg *Config, ns string, allShards []taskShard,
-	errCount, taskCount *counter) {
-
-	// Enter the supplied namespace.
-	logging.Infof(c, "Firing all tasks for namespace %q", ns)
-	c = info.MustNamespace(c, ns)
-	if ns != "" {
-		c = logging.SetField(c, "namespace", ns)
-	}
-
-	// First, check if the namespace has *any* Mutations.
-	q := ds.NewQuery("tumble.Mutation").KeysOnly(true).Limit(1)
-	switch amt, err := ds.Count(c, q); {
-	case err != nil:
-		logging.WithError(err).Errorf(c, "Error querying for Mutations")
-		errCount.inc()
-		return
-
-	case amt == 0:
-		logging.Infof(c, "No Mutations registered for this namespace.")
-		return
-	}
-
-	// We have at least one Mutation for this namespace. Iterate through all
-	// shards and dispatch a processing task for each one that has Mutations.
-	//
-	// Track shards that we find work for. After scanning is complete, fire off
-	// tasks for all identified shards.
-	triggerShards := make(map[taskShard]struct{}, len(allShards))
-	for _, shrd := range allShards {
-		amt, err := ds.Count(c, processShardQuery(c, cfg, shrd.shard).Limit(1))
-		if err != nil {
-			logging.Fields{
-				logging.ErrorKey: err,
-				"shard":          shrd.shard,
-			}.Errorf(c, "Error querying for shards")
-			errCount.inc()
-			break
-		}
-		if amt > 0 {
-			logging.Infof(c, "Found work in shard [%d]", shrd.shard)
-			triggerShards[shrd] = struct{}{}
-		}
-	}
-
-	// Fire tasks for shards with identified work.
-	if len(triggerShards) > 0 {
-		logging.Infof(c, "Firing tasks for %d tasked shard(s).", len(triggerShards))
-		if !fireTasks(c, cfg, triggerShards, false) {
-			logging.Errorf(c, "Failed to fire tasks.")
-			errCount.inc()
-		} else {
-			taskCount.add(len(triggerShards))
-		}
-	} else {
-		logging.Infof(c, "No tasked shards were found.")
-	}
-}
-
-func (s *Service) getNamespaces(c context.Context, cfg *Config) ([]string, error) {
-	// Get the set of namespaces to handle.
-	nsFn := s.Namespaces
-	if nsFn == nil {
-		nsFn = getDatastoreNamespaces
-	}
-
-	namespaces, err := nsFn(c)
-	if err != nil {
-		logging.WithError(err).Errorf(c, "Failed to enumerate namespaces.")
-		return nil, err
-	}
-	return namespaces, nil
-}
-
-// ProcessShardHandler is an HTTP handler that expects `logging` and `luci/gae`
-// services to be installed into the context.
-//
-// ProcessShardHandler verifies that its being run as a taskqueue task and that
-// the following parameters exist and are well-formed:
-//   * timestamp: decimal-encoded UNIX/UTC timestamp in seconds.
-//   * shard_id: decimal-encoded shard identifier.
-//
-// ProcessShardHandler then invokes ProcessShard with the parsed parameters. It
-// runs in the namespace of the task which scheduled it and processes mutations
-// for that namespace.
-func (s *Service) ProcessShardHandler(ctx *router.Context, loop bool) {
-	c, rw, p := ctx.Context, ctx.Writer, ctx.Params
-
-	tstampStr := p.ByName("timestamp")
-	sidStr := p.ByName("shard_id")
-
-	tstamp, err := strconv.ParseInt(tstampStr, 10, 64)
-	if err != nil {
-		logging.Errorf(c, "bad timestamp %q", tstampStr)
-		rw.WriteHeader(http.StatusNotFound)
-		fmt.Fprintf(rw, "bad timestamp")
-		return
-	}
-
-	sid, err := strconv.ParseUint(sidStr, 10, 64)
-	if err != nil {
-		logging.Errorf(c, "bad shardID %q", tstampStr)
-		rw.WriteHeader(http.StatusNotFound)
-		fmt.Fprintf(rw, "bad shardID")
-		return
-	}
-
-	cfg := getConfig(c)
-
-	logging.Infof(c, "Processing tasks in namespace %q", info.GetNamespace(c))
-	// AppEngine backend instances run for 10 minute at most,
-	// set the overall context deadline to 9 minutes.
-	c, cancel := clock.WithDeadline(c, clock.Now(c).Add(9*time.Minute))
-	defer cancel()
-	err = processShard(c, cfg, time.Unix(tstamp, 0).UTC(), sid, loop)
-	if err != nil {
-		logging.Errorf(c, "failure! %s", err)
-
-		if transient.Tag.In(err) {
-			rw.Header().Add(transientHTTPHeader, "true")
-		}
-		rw.WriteHeader(http.StatusInternalServerError)
-		fmt.Fprintf(rw, "error: %s", err)
-	} else {
-		rw.Write([]byte("ok"))
-	}
-}
-
-// getDatastoreNamespaces returns a list of all of the namespaces in the
-// datastore.
-//
-// This is done by issuing a datastore query for kind "__namespace__". The
-// resulting keys will have IDs for the namespaces, namely:
-//	- The default namespace will have integer ID 1.
-//	- Other namespaces will have string IDs.
-func getDatastoreNamespaces(c context.Context) ([]string, error) {
-	q := ds.NewQuery("__namespace__").KeysOnly(true)
-
-	// Query our datastore for the full set of namespaces.
-	var namespaceKeys []*ds.Key
-	if err := ds.GetAll(c, q, &namespaceKeys); err != nil {
-		logging.WithError(err).Errorf(c, "Failed to execute namespace query.")
-		return nil, err
-	}
-
-	namespaces := make([]string, 0, len(namespaceKeys))
-	for _, nk := range namespaceKeys {
-		// Add our namespace ID. For the default namespace, the key will have an
-		// integer ID of 1, so StringID will correctly be an empty string.
-		namespaces = append(namespaces, nk.StringID())
-	}
-	return namespaces, nil
-}
-
-// processURL creates a new url for a process shard taskqueue task, including
-// the given timestamp and shard number.
-func processURL(ts timestamp, shard uint64, ns string, loop bool) string {
-	v := strings.NewReplacer(
-		":shard_id", fmt.Sprint(shard),
-		":timestamp", strconv.FormatInt(int64(ts), 10),
-	).Replace(processShardPattern)
-
-	// Append our namespace query parameter. This is cosmetic, and the default
-	// namespace will have this query parameter omitted.
-	query := url.Values{}
-	if ns != "" {
-		query.Set("ns", ns)
-	}
-	if !loop {
-		query.Set("single", "1")
-	}
-	if len(query) > 0 {
-		v += "?" + query.Encode()
-	}
-	return v
-}
diff --git a/tumble/service_test.go b/tumble/service_test.go
deleted file mode 100644
index 2a26dd4..0000000
--- a/tumble/service_test.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"testing"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/info"
-	tq "go.chromium.org/luci/gae/service/taskqueue"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestGetDatastoreNamespaces(t *testing.T) {
-	t.Parallel()
-
-	Convey(`A testing datastore`, t, func() {
-		tt := &Testing{}
-		ctx := tt.Context()
-
-		// Call to add a datastore entry under the supplied namespace.
-		addNamespace := func(ns string) {
-			c := info.MustNamespace(ctx, ns)
-
-			err := ds.Raw(c).PutMulti(
-				[]*ds.Key{
-					ds.NewKey(c, "Warblegarble", "", 1, nil),
-				},
-				[]ds.PropertyMap{
-					make(ds.PropertyMap),
-				},
-				func(int, *ds.Key, error) {})
-			if err != nil {
-				panic(err)
-			}
-
-			ds.GetTestable(ctx).CatchupIndexes()
-		}
-
-		Convey(`A datastore with no namespaces returns {}.`, func() {
-			namespaces, err := getDatastoreNamespaces(ctx)
-			So(err, ShouldBeNil)
-			So(namespaces, ShouldBeEmpty)
-		})
-
-		Convey(`A datastore with namespaces {"foo", "bar"} will return {"bar", "foo"}.`, func() {
-			addNamespace("foo")
-			addNamespace("bar")
-
-			namespaces, err := getDatastoreNamespaces(ctx)
-			So(err, ShouldBeNil)
-			So(namespaces, ShouldResemble, []string{"bar", "foo"})
-		})
-	})
-}
-
-func TestFireAllTasks(t *testing.T) {
-	t.Parallel()
-
-	Convey("FireAllTasks", t, func() {
-		tt := &Testing{}
-		c := tt.Context()
-		s := &Service{}
-
-		Convey("with no work is a noop", func() {
-			So(s.FireAllTasks(c), ShouldBeNil)
-
-			for _, tsks := range tq.GetTestable(c).GetScheduledTasks() {
-				So(tsks, ShouldBeEmpty)
-			}
-		})
-
-		Convey("with some work emits a task", func() {
-			So(ds.Put(c, &realMutation{ID: "bogus", Parent: ds.MakeKey(c, "Parent", 1)}), ShouldBeNil)
-
-			So(s.FireAllTasks(c), ShouldBeNil)
-			So(tq.GetTestable(c).GetScheduledTasks()["tumble"], ShouldHaveLength, 1)
-		})
-
-		Convey("with some work in a different namespaces emits a task for each namespace", func() {
-			namespaces := []string{"first", "other"}
-			s.Namespaces = func(context.Context) ([]string, error) { return namespaces, nil }
-
-			for _, ns := range namespaces {
-				c := info.MustNamespace(c, ns)
-				So(ds.Put(c, &realMutation{ID: "bogus", Parent: ds.MakeKey(c, "Parent", 1)}), ShouldBeNil)
-			}
-
-			So(s.FireAllTasks(c), ShouldBeNil)
-			for _, ns := range namespaces {
-				So(tq.GetTestable(info.MustNamespace(c, ns)).GetScheduledTasks()["tumble"], ShouldHaveLength, 1)
-			}
-		})
-	})
-}
diff --git a/tumble/settings.go b/tumble/settings.go
deleted file mode 100644
index 45bcc3d..0000000
--- a/tumble/settings.go
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright 2016 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"fmt"
-	"html/template"
-	"strconv"
-
-	"go.chromium.org/luci/common/clock/clockflag"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/server/portal"
-	"go.chromium.org/luci/server/settings"
-)
-
-const (
-	settingDisabled = "disabled"
-	settingEnabled  = "enabled"
-)
-
-// settingsPage is a UI page to configure a static Tumble configuration.
-type settingsPage struct {
-	portal.BasePage
-}
-
-func (settingsPage) Title(c context.Context) (string, error) {
-	return "Tumble settings", nil
-}
-
-func (settingsPage) Overview(c context.Context) (template.HTML, error) {
-	return template.HTML(`<p>Configuration parameters for the
-<a href="https://github.com/luci/luci-go/tree/master/tumble">tumble
-service</a> can be found in its
-<a href="https://godoc.org/go.chromium.org/luci/tumble">
-documentation</a>.</p>.`), nil
-}
-
-func (settingsPage) Fields(c context.Context) ([]portal.Field, error) {
-	return []portal.Field{
-		{
-			ID:          "NumShards",
-			Title:       "Number of shards to use",
-			Type:        portal.FieldText,
-			Placeholder: strconv.FormatUint(defaultConfig.NumShards, 10),
-			Validator:   intValidator(true),
-		},
-		{
-			ID:          "NumGoroutines",
-			Title:       "Number of goroutines per shard",
-			Type:        portal.FieldText,
-			Placeholder: strconv.Itoa(defaultConfig.NumGoroutines),
-			Validator:   intValidator(true),
-		},
-		{
-			ID:          "TemporalMinDelay",
-			Title:       "Temporal minimum delay (s, m, h)",
-			Type:        portal.FieldText,
-			Placeholder: defaultConfig.TemporalMinDelay.String(),
-			Validator:   validateDuration,
-		},
-		{
-			ID:          "TemporalRoundFactor",
-			Title:       "Temporal round factor, for batching (s, m, h)",
-			Type:        portal.FieldText,
-			Placeholder: defaultConfig.TemporalRoundFactor.String(),
-			Validator:   validateDuration,
-		},
-		{
-			ID:          "ProcessLoopDuration",
-			Title:       "Maximum lifetime of batch processing loop",
-			Type:        portal.FieldText,
-			Placeholder: defaultConfig.ProcessLoopDuration.String(),
-			Validator:   validateDuration,
-		},
-		{
-			ID:          "DustSettleTimeout",
-			Title:       "Amount of time to wait for datastore to settle in between mutation rounds (s, m, h)",
-			Type:        portal.FieldText,
-			Placeholder: defaultConfig.DustSettleTimeout.String(),
-			Validator:   validateDuration,
-		},
-		{
-			ID: "MaxNoWorkDelay",
-			Title: "Maximum amount of time to sleep in between rounds if here was no work done " +
-				"the previous round (s, m, h)",
-			Type:        portal.FieldText,
-			Placeholder: defaultConfig.MaxNoWorkDelay.String(),
-			Validator:   validateDuration,
-		},
-		{
-			ID: "NoWorkDelayGrowth",
-			Title: "Growth factor for the delay in between loops when no work was done. " +
-				"If <= 1, no growth will be applied. The delay is capped by MaxNoWorkDelay.",
-			Type:        portal.FieldText,
-			Placeholder: strconv.Itoa(int(defaultConfig.NoWorkDelayGrowth)),
-			Validator:   intValidator(true),
-		},
-		{
-			ID:          "ProcessMaxBatchSize",
-			Title:       "Number of mutations to include per commit (negative for unlimited)",
-			Type:        portal.FieldText,
-			Placeholder: strconv.Itoa(int(defaultConfig.ProcessMaxBatchSize)),
-			Validator:   intValidator(false),
-		},
-		{
-			ID:             "DelayedMutations",
-			Title:          "Delayed mutations (index MUST be present)",
-			Type:           portal.FieldChoice,
-			ChoiceVariants: []string{settingDisabled, settingEnabled},
-		},
-	}, nil
-}
-
-func (settingsPage) ReadSettings(c context.Context) (map[string]string, error) {
-	var cfg Config
-	switch err := settings.GetUncached(c, baseName, &cfg); err {
-	case nil:
-		break
-	case settings.ErrNoSettings:
-		logging.WithError(err).Infof(c, "No settings available, using defaults.")
-		cfg = defaultConfig
-	default:
-		return nil, err
-	}
-
-	values := map[string]string{}
-
-	// Only render values if they differ from our default config.
-	if cfg.NumShards != defaultConfig.NumShards {
-		values["NumShards"] = strconv.FormatUint(cfg.NumShards, 10)
-	}
-	if cfg.NumGoroutines != defaultConfig.NumGoroutines {
-		values["NumGoroutines"] = strconv.Itoa(cfg.NumGoroutines)
-	}
-	if cfg.TemporalMinDelay != defaultConfig.TemporalMinDelay {
-		values["TemporalMinDelay"] = cfg.TemporalMinDelay.String()
-	}
-	if cfg.TemporalRoundFactor != defaultConfig.TemporalRoundFactor {
-		values["TemporalRoundFactor"] = cfg.TemporalRoundFactor.String()
-	}
-	if cfg.ProcessLoopDuration != defaultConfig.ProcessLoopDuration {
-		values["ProcessLoopDuration"] = cfg.ProcessLoopDuration.String()
-	}
-	if cfg.DustSettleTimeout != defaultConfig.DustSettleTimeout {
-		values["DustSettleTimeout"] = cfg.DustSettleTimeout.String()
-	}
-	if cfg.MaxNoWorkDelay != defaultConfig.MaxNoWorkDelay {
-		values["MaxNoWorkDelay"] = cfg.MaxNoWorkDelay.String()
-	}
-	if cfg.NoWorkDelayGrowth != defaultConfig.NoWorkDelayGrowth {
-		values["NoWorkDelayGrowth"] = strconv.Itoa(int(cfg.NoWorkDelayGrowth))
-	}
-	if cfg.ProcessMaxBatchSize != defaultConfig.ProcessMaxBatchSize {
-		values["ProcessMaxBatchSize"] = strconv.Itoa(int(cfg.ProcessMaxBatchSize))
-	}
-
-	values["DelayedMutations"] = getToggleSetting(cfg.DelayedMutations)
-
-	return values, nil
-}
-
-func (settingsPage) WriteSettings(c context.Context, values map[string]string, who, why string) error {
-	// Start with our default config and shape it with populated values.
-	cfg := defaultConfig
-
-	var err error
-	if v := values["NumShards"]; v != "" {
-		cfg.NumShards, err = strconv.ParseUint(v, 10, 64)
-		if err != nil {
-			return fmt.Errorf("could not parse NumShards: %v", err)
-		}
-	}
-	if v := values["NumGoroutines"]; v != "" {
-		cfg.NumGoroutines, err = strconv.Atoi(v)
-		if err != nil {
-			return fmt.Errorf("could not parse NumGoroutines: %v", err)
-		}
-	}
-	if v := values["TemporalMinDelay"]; v != "" {
-		cfg.TemporalMinDelay, err = clockflag.ParseDuration(v)
-		if err != nil {
-			return fmt.Errorf("could not parse TemporalMinDelay: %v", err)
-		}
-	}
-	if v := values["TemporalRoundFactor"]; v != "" {
-		cfg.TemporalRoundFactor, err = clockflag.ParseDuration(v)
-		if err != nil {
-			return fmt.Errorf("could not parse TemporalRoundFactor: %v", err)
-		}
-	}
-	if v := values["ProcessLoopDuration"]; v != "" {
-		cfg.ProcessLoopDuration, err = clockflag.ParseDuration(v)
-		if err != nil {
-			return fmt.Errorf("could not parse ProcessLoopDuration: %v", err)
-		}
-	}
-	if v := values["DustSettleTimeout"]; v != "" {
-		cfg.DustSettleTimeout, err = clockflag.ParseDuration(v)
-		if err != nil {
-			return fmt.Errorf("could not parse DustSettleTimeout: %v", err)
-		}
-	}
-	if v := values["MaxNoWorkDelay"]; v != "" {
-		cfg.MaxNoWorkDelay, err = clockflag.ParseDuration(v)
-		if err != nil {
-			return fmt.Errorf("could not parse MaxNoWorkDelay: %v", err)
-		}
-	}
-	if v := values["NoWorkDelayGrowth"]; v != "" {
-		val, err := strconv.Atoi(v)
-		if err != nil {
-			return fmt.Errorf("could not parse ProcessMaxBatchSize: %v", err)
-		}
-		cfg.NoWorkDelayGrowth = val
-	}
-	if v := values["ProcessMaxBatchSize"]; v != "" {
-		val, err := strconv.Atoi(v)
-		if err != nil {
-			return fmt.Errorf("could not parse ProcessMaxBatchSize: %v", err)
-		}
-		cfg.ProcessMaxBatchSize = val
-	}
-	cfg.DelayedMutations = values["DelayedMutations"] == settingEnabled
-
-	return settings.SetIfChanged(c, baseName, &cfg, who, why)
-}
-
-func intValidator(positive bool) func(string) error {
-	return func(v string) error {
-		if v == "" {
-			return nil
-		}
-		i, err := strconv.Atoi(v)
-		if err != nil {
-			return fmt.Errorf("invalid integer %q - %s", v, err)
-		}
-		if positive && i <= 0 {
-			return fmt.Errorf("value %q must be positive", v)
-		}
-		return nil
-	}
-}
-
-func validateDuration(v string) error {
-	if v == "" {
-		return nil
-	}
-
-	var cf clockflag.Duration
-	if err := cf.Set(v); err != nil {
-		return fmt.Errorf("bad duration %q - %s", v, err)
-	}
-	if cf <= 0 {
-		return fmt.Errorf("duration %q must be positive", v)
-	}
-	return nil
-}
-
-func getToggleSetting(v bool) string {
-	if v {
-		return settingEnabled
-	}
-	return settingDisabled
-}
-
-func init() {
-	portal.RegisterPage("tumble", settingsPage{})
-}
diff --git a/tumble/tco_test.go b/tumble/tco_test.go
deleted file mode 100644
index 7d895fe..0000000
--- a/tumble/tco_test.go
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"testing"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-type BigObjectGroup struct {
-	_id int64 `gae:"$id,1"`
-
-	Count int64
-}
-
-type BigObject struct {
-	ID    int64   `gae:"$id"`
-	Group *ds.Key `gae:"$parent"`
-
-	Data []byte `gae:",noindex"`
-}
-
-type SlowMutation struct {
-	Count int64
-}
-
-func (s *SlowMutation) Root(c context.Context) *ds.Key {
-	return ds.MakeKey(c, "BigObjectGroup", 1)
-}
-
-var JunkBytes = make([]byte, 512*1024)
-
-func init() {
-	for i := 0; i < 32768; i += 16 {
-		copy(JunkBytes[i:i+16], []byte("BuhNerfCatBlarty"))
-	}
-}
-
-func (s *SlowMutation) RollForward(c context.Context) (muts []Mutation, err error) {
-	grp := &BigObjectGroup{}
-	err = ds.Get(c, grp)
-	if err == ds.ErrNoSuchEntity {
-		err = ds.Put(c, grp)
-	}
-	if err != nil {
-		return
-	}
-
-	grp.Count++
-	bo := &BigObject{ID: grp.Count, Group: ds.KeyForObj(c, grp), Data: JunkBytes}
-	err = ds.Put(c, grp, bo)
-
-	retMut := *s
-	retMut.Count--
-	if retMut.Count > 0 {
-		muts = append(muts, &retMut)
-	}
-	return
-}
-
-func init() {
-	Register((*SlowMutation)(nil))
-}
-
-func TestTailCallOptimization(t *testing.T) {
-	if testing.Short() {
-		t.Skip("TCO test skipped in -short mode")
-	}
-
-	t.Parallel()
-
-	Convey("Tail Call optimization test", t, func() {
-		testing := &Testing{}
-		c := testing.Context()
-
-		// This will start a chain.
-		So(RunMutation(c, &SlowMutation{40}), ShouldBeNil)
-
-		// 2 processed shards shows that we did 1 transaction and 1 empty tail call.
-		So(testing.Drain(c), ShouldEqual, 2)
-
-		bog := &BigObjectGroup{}
-		So(ds.Get(c, bog), ShouldBeNil)
-
-		// Hey look at that, bog shows all 40 :)
-		So(bog.Count, ShouldEqual, 40)
-	})
-}
diff --git a/tumble/tumble.go b/tumble/tumble.go
deleted file mode 100644
index 8bf2864..0000000
--- a/tumble/tumble.go
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"fmt"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/data/stringset"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-
-	"go.chromium.org/luci/gae/filter/txnBuf"
-	ds "go.chromium.org/luci/gae/service/datastore"
-)
-
-// RunMutation immediately runs the Mutation `m` in a transaction. This method
-// should be used to start a tumble chain when you have transactional checks
-// to do (e.g. `m` implements the first transactional link in the chain).
-//
-// Usually this is called from your application's handlers to begin a tumble
-// state machine as a result of some API interaction.
-func RunMutation(c context.Context, m Mutation) error {
-	cfg := getConfig(c)
-	shardSet, _, _, err := enterTransactionMutation(txnBuf.FilterRDS(c), cfg, m, 0)
-	if err != nil {
-		return err
-	}
-	fireTasks(c, cfg, shardSet, true)
-	return nil
-}
-
-// RunUnbuffered opens a lightweight unbuffered transaction on "root"
-// runs "fn" inside of it. Any mutations returned by "fn" will be registered
-// at the end of the transaction if "fn" doesn't return an error.
-//
-// This is useful as an initial starting point without incurring any of the
-// overhead of spinning up a new buffered transaction.
-//
-// During "fn"'s execution, standard Tumble operations such as PutNamedMutation
-// and CancelNamedMutation may be performed.
-func RunUnbuffered(c context.Context, root *ds.Key, fn func(context.Context) ([]Mutation, error)) error {
-	cfg := getConfig(c)
-	shardSet, _, _, err := enterTransactionInternal(c, cfg, root, fn, 0)
-	if err != nil {
-		return err
-	}
-	fireTasks(c, cfg, shardSet, true)
-	return nil
-}
-
-func enterTransactionMutation(c context.Context, cfg *Config, m Mutation, round uint64) (
-	map[taskShard]struct{}, []Mutation, []*ds.Key, error) {
-
-	return enterTransactionInternal(c, cfg, m.Root(c), m.RollForward, round)
-}
-
-func enterTransactionInternal(c context.Context, cfg *Config, root *ds.Key, fn func(context.Context) ([]Mutation, error), round uint64) (
-	map[taskShard]struct{}, []Mutation, []*ds.Key, error) {
-
-	if root == nil {
-		return nil, nil, nil, fmt.Errorf("tumble: Passing nil as root is illegal")
-	}
-
-	shardSet := map[taskShard]struct{}(nil)
-	retMuts := []Mutation(nil)
-	retMutKeys := []*ds.Key(nil)
-
-	err := ds.RunInTransaction(c, func(c context.Context) error {
-		// do a Get on the root to ensure that this transaction is associated
-		// with that entity group.
-		_, _ = ds.Exists(c, root)
-
-		muts, err := fn(c)
-		if err != nil {
-			return err
-		}
-
-		retMuts = muts
-		shardSet, retMutKeys, err = putMutations(c, cfg, root, muts, round)
-
-		return err
-	}, nil)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	return shardSet, retMuts, retMutKeys, nil
-}
-
-// PutNamedMutations writes the provided named mutations to the datastore.
-//
-// Named mutations are singletons children of a given `parent`. So for any given
-// `parent`, there can be only one mutation with any given name.  Named
-// mutations, by design, cannot collide with unnamed (anonymous) mutations.
-// `parent` does NOT need to be a root Key; the mutations will be created as
-// direct descendants of the provided parent entity. The names of the various
-// mutations should be valid datastore key StringIDs, which generally means that
-// they should be UTF-8 strings.
-//
-// The current implementation reserves 2 characters of the StringID (as of
-// writing this means that a named mutation name may only be 498 bytes long).
-//
-// This can be used to leverage tumble for e.g. cancellable, delayed cleanup
-// tasks (like timeouts).
-//
-// This may be called from within an existing datastore transaction which
-// includes `parent` to make this Put atomic with the remainder of the
-// transaction.
-//
-// If called multiple times with the same name, the newly named mutation will
-// overwrite the existing mutation (assuming it hasn't run already).
-func PutNamedMutations(c context.Context, parent *ds.Key, muts map[string]Mutation) error {
-	cfg := getConfig(c)
-
-	now := clock.Now(c).UTC()
-
-	shardSet := map[taskShard]struct{}{}
-	toPut := make([]*realMutation, 0, len(muts))
-	for name, m := range muts {
-		realMut, err := newRealMutation(c, cfg, "n:"+name, parent, m, now)
-		if err != nil {
-			logging.WithError(err).Errorf(c, "error creating real mutation for %v", m)
-			return err
-		}
-		toPut = append(toPut, realMut)
-		shardSet[realMut.shard(cfg)] = struct{}{}
-	}
-
-	err := ds.Put(c, toPut)
-	if err == nil {
-		metricCreated.Add(c, int64(len(toPut)), parent.Namespace())
-	}
-	fireTasks(c, getConfig(c), shardSet, true)
-	return err
-}
-
-// CancelNamedMutations does a best-effort cancellation of the named mutations.
-func CancelNamedMutations(c context.Context, parent *ds.Key, names ...string) error {
-	toDel := make([]*ds.Key, 0, len(names))
-	nameSet := stringset.NewFromSlice(names...)
-	nameSet.Iter(func(name string) bool {
-		toDel = append(toDel, ds.NewKey(c, "tumble.Mutation", "n:"+name, 0, parent))
-		return true
-	})
-	err := ds.Delete(c, toDel)
-	numFailed := int64(0)
-	if me, ok := err.(errors.MultiError); ok {
-		numFailed = int64(len(me))
-	}
-	metricDeleted.Add(c, int64(len(toDel))-numFailed, parent.Namespace())
-	return errors.Filter(err, ds.ErrNoSuchEntity)
-}
diff --git a/tumble/tumble_test.go b/tumble/tumble_test.go
deleted file mode 100644
index 2836dc1..0000000
--- a/tumble/tumble_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"fmt"
-	"testing"
-
-	ds "go.chromium.org/luci/gae/service/datastore"
-)
-
-func init() {
-	Register(&registerBenchmarkMutation{})
-}
-
-type registerBenchmarkMutation struct {
-	Parent *ds.Key
-	ID     string
-	Rounds int
-}
-
-func (m *registerBenchmarkMutation) RollForward(c context.Context) ([]Mutation, error) {
-	type testEntity struct {
-		Parent *ds.Key `gae:"$parent"`
-		Kind   string  `gae:"$kind,test"`
-		ID     string  `gae:"$id"`
-
-		Name string
-	}
-
-	// Perform a Get, Query, then Put.
-	e := testEntity{Parent: m.Root(c), ID: m.ID}
-	if err := ds.Get(c, &e); err != nil && err != ds.ErrNoSuchEntity {
-		return nil, err
-	}
-
-	var all []*testEntity
-	if err := ds.GetAll(c, ds.NewQuery("test").Ancestor(m.Parent), &all); err != nil {
-		return nil, err
-	}
-
-	ents := make([]*testEntity, m.Rounds)
-	for i := range ents {
-		ents[i] = &testEntity{Parent: m.Parent, ID: fmt.Sprintf("%s.%d", m.ID, i)}
-	}
-	if err := ds.Put(c, ents); err != nil {
-		return nil, err
-	}
-
-	// Put the entity, add some new Mutations at the end.
-	return []Mutation{
-		&registerBenchmarkMutation{m.Parent, "bar", m.Rounds},
-		&registerBenchmarkMutation{m.Parent, "baz", m.Rounds},
-	}, nil
-}
-
-func (m *registerBenchmarkMutation) Root(c context.Context) *ds.Key { return m.Parent }
-
-func runRegisterBenchmark(b *testing.B, reg func(context.Context, Mutation) error) {
-	var t Testing
-	c := t.Context()
-	mut := registerBenchmarkMutation{ds.MakeKey(c, "parent", 1), "foo", 500}
-
-	b.ResetTimer()
-	if err := reg(c, &mut); err != nil {
-		panic(err)
-	}
-}
-
-func BenchmarkRegisterWithRunMutation(b *testing.B) {
-	runRegisterBenchmark(b, RunMutation)
-}
-
-func BenchmarkRegisterWithRunUnbuffered(b *testing.B) {
-	runRegisterBenchmark(b, func(c context.Context, m Mutation) error {
-		return RunUnbuffered(c, m.Root(c), m.RollForward)
-	})
-}
-
-//BenchmarkRegisterWithRunMutation-32             1000000000       0.52 ns/op
-//BenchmarkRegisterWithRunUnbuffered-32           1000000000       0.22 ns/op
diff --git a/tumble/tumbletest.go b/tumble/tumbletest.go
deleted file mode 100644
index cffaede..0000000
--- a/tumble/tumbletest.go
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tumble
-
-import (
-	"context"
-	"fmt"
-	"net/http"
-	"net/http/httptest"
-	"os"
-	"time"
-
-	"go.chromium.org/luci/common/clock"
-	"go.chromium.org/luci/common/clock/testclock"
-	"go.chromium.org/luci/common/data/rand/cryptorand"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/logging/memlogger"
-	"go.chromium.org/luci/server/router"
-	"go.chromium.org/luci/server/settings"
-
-	"go.chromium.org/luci/gae/impl/memory"
-	ds "go.chromium.org/luci/gae/service/datastore"
-	"go.chromium.org/luci/gae/service/info"
-	tq "go.chromium.org/luci/gae/service/taskqueue"
-)
-
-// Testing is a high-level testing object for testing applications that use
-// tumble.
-type Testing struct {
-	Service
-}
-
-// UpdateSettings changes the tumble settings in the context to match cfg.
-//
-// If cfg == nil, this resets the settings to their default values.
-func (t *Testing) UpdateSettings(c context.Context, cfg *Config) {
-	if cfg == nil {
-		dflt := defaultConfig
-		dflt.DustSettleTimeout = 0
-		cfg = &dflt
-	}
-	settings.Set(c, baseName, cfg, "tumble.Testing", "for testing")
-}
-
-// Config retrieves the current tumble settings
-func (t *Testing) Config(c context.Context) *Config {
-	return getConfig(c)
-}
-
-// Context generates a correctly configured context with:
-//   * luci/gae/impl/memory
-//   * luci/luci-go/common/clock/testclock
-//   * luci/luci-go/common/logging/memlogger
-//   * luci/luci-go/server/settings (MemoryStorage)
-//
-// It also correctly configures the "tumble.Mutation" indexes and taskqueue
-// named in this Testing config.
-func (t *Testing) Context() context.Context {
-	ctx := memory.Use(memlogger.Use(context.Background()))
-	ctx, _ = testclock.UseTime(ctx, testclock.TestTimeUTC.Round(time.Millisecond))
-	ctx = settings.Use(ctx, settings.New(&settings.MemoryStorage{}))
-	ctx = cryptorand.MockForTest(ctx, 765589025) // as chosen by fair dice roll
-	t.UpdateSettings(ctx, nil)
-
-	tq.GetTestable(ctx).CreateQueue(baseName)
-
-	ds.GetTestable(ctx).AddIndexes(&ds.IndexDefinition{
-		Kind: "tumble.Mutation",
-		SortBy: []ds.IndexColumn{
-			{Property: "ExpandedShard"},
-			{Property: "TargetRoot"},
-		},
-	})
-	ds.GetTestable(ctx).Consistent(true)
-
-	return ctx
-}
-
-// EnableDelayedMutations turns on delayed mutations for this context.
-func (t *Testing) EnableDelayedMutations(c context.Context) {
-	cfg := t.Config(c)
-	if !cfg.DelayedMutations {
-		cfg.DelayedMutations = true
-		ds.GetTestable(c).AddIndexes(&ds.IndexDefinition{
-			Kind: "tumble.Mutation",
-			SortBy: []ds.IndexColumn{
-				{Property: "TargetRoot"},
-				{Property: "ProcessAfter"},
-			},
-		})
-		t.UpdateSettings(c, cfg)
-	}
-}
-
-// Iterate makes a single iteration of the tumble service worker, and returns
-// the number of shards that were processed. Iterate operates on the Context's
-// current namespace.
-//
-// It will skip all work items if the test clock hasn't advanced in time
-// enough.
-func (t *Testing) Iterate(c context.Context) int {
-	clk := clock.Get(c).(testclock.TestClock)
-	logging.Debugf(c, "tumble.Testing.Iterate: time(%d|%s)", timestamp(clk.Now().Unix()), clk.Now().UTC())
-
-	r := router.New()
-	t.InstallHandlers(r, nil)
-
-	ret := 0
-	tsks := tq.GetTestable(c).GetScheduledTasks()[baseName]
-	logging.Debugf(c, "got tasks: %v", tsks)
-	for _, tsk := range tsks {
-		logging.Debugf(c, "found task: %v", tsk)
-		if tsk.ETA.After(clk.Now().UTC()) {
-			logging.Infof(c, "skipping task: ETA(%s): %s", tsk.ETA, tsk.Path)
-			continue
-		}
-
-		req, err := http.NewRequest("POST", tsk.Path, nil)
-		if err != nil {
-			panic(err)
-		}
-		req.Header.Set("X-AppEngine-QueueName", baseName)
-
-		// Determine our parameters.
-		params, ok := r.Params("POST", req.URL.Path)
-		if !ok {
-			panic(fmt.Errorf("failed to lookup path: %s", req.URL.Path))
-		}
-
-		// Process the shard until a success or hard failure.
-		retryHTTP(c, func(rec *httptest.ResponseRecorder) {
-			t.ProcessShardHandler(&router.Context{
-				Context: c,
-				Writer:  rec,
-				Request: req,
-				Params:  params,
-			}, false)
-		})
-
-		if err := tq.Delete(c, baseName, tsk); err != nil {
-			panic(fmt.Errorf("Deleting task failed: %s", err))
-		}
-		ret++
-	}
-	return ret
-}
-
-// IterateAll iterates over all namespaces and calls Iterate on each.
-func (t *Testing) IterateAll(c context.Context) int {
-	total := 0
-	for _, ns := range t.MustGetNamespaces(c) {
-		total += t.Iterate(info.MustNamespace(c, ns))
-	}
-	return total
-}
-
-// FireAllTasks will force all tumble shards to run in the future.
-func (t *Testing) FireAllTasks(c context.Context) {
-	retryHTTP(c, func(rec *httptest.ResponseRecorder) {
-		// Fire all tasks until a success or hard failure.
-		t.FireAllTasksHandler(&router.Context{
-			Context: c,
-			Writer:  rec,
-			Request: &http.Request{
-				Header: http.Header{"X-Appengine-Cron": []string{"true"}},
-			},
-		})
-	})
-}
-
-// AdvanceTime advances the test clock enough so that Iterate will be able to
-// pick up tasks in the task queue.
-func (t *Testing) AdvanceTime(c context.Context) {
-	clk := clock.Get(c).(testclock.TestClock)
-	cfg := t.Config(c)
-	toAdd := time.Duration(cfg.TemporalMinDelay) + time.Duration(cfg.TemporalRoundFactor) + time.Second
-	logging.Infof(c, "adding %s to %s", toAdd, clk.Now().UTC())
-	clk.Add(toAdd)
-}
-
-// Drain will run a loop, advancing time and iterating through tumble mutations
-// until tumble's queue is empty. It returns the total number of processed
-// shards.
-func (t *Testing) Drain(c context.Context) int {
-	ret := 0
-	for {
-		t.AdvanceTime(c)
-		processed := t.Iterate(c)
-		if processed == 0 {
-			break
-		}
-		ret += processed
-	}
-	return ret
-}
-
-// DrainAll iterates over all namespaces and drains each independently.
-func (t *Testing) DrainAll(c context.Context) int {
-	total := 0
-	for _, ns := range t.MustGetNamespaces(c) {
-		total += t.Drain(info.MustNamespace(c, ns))
-	}
-	return total
-}
-
-// ResetLog resets the current memory logger to the empty state.
-func (t *Testing) ResetLog(c context.Context) {
-	logging.Get(c).(*memlogger.MemLogger).Reset()
-}
-
-// DumpLog dumps the current memory logger to stdout to help with debugging.
-func (t *Testing) DumpLog(c context.Context) {
-	logging.Get(c).(*memlogger.MemLogger).Dump(os.Stdout)
-}
-
-// MustGetNamespaces returns all active namespaces in t's Service.
-//
-// If the namespace function returns an error, MustGetNamespaces will panic.
-func (t *Testing) MustGetNamespaces(c context.Context) []string {
-	namespaces, err := t.getNamespaces(c, t.Config(c))
-	if err != nil {
-		panic(err)
-	}
-	return namespaces
-}
-
-// retryHTTP will record an HTTP request and handle its response.
-//
-// It will return if the response indicated success, retry the request if the
-// response indicated a transient failure, or panic if the response indicated a
-// hard failure.
-func retryHTTP(c context.Context, reqFn func(rec *httptest.ResponseRecorder)) {
-	for {
-		rec := httptest.NewRecorder()
-		reqFn(rec)
-
-		switch rec.Code {
-		case http.StatusOK, http.StatusNoContent:
-			return
-
-		case http.StatusInternalServerError:
-			bodyStr := rec.Body.String()
-			err := fmt.Errorf("internal server error: %s", bodyStr)
-			if rec.Header().Get(transientHTTPHeader) == "" {
-				lmsg := logging.Get(c).(*memlogger.MemLogger).Messages()
-				panic(fmt.Errorf("HTTP non-transient error: %s: %#v", err, lmsg))
-			}
-			logging.WithError(err).Warningf(c, "Transient error encountered, retrying.")
-
-		default:
-			panic(fmt.Errorf("HTTP error %d (%s): %s", rec.Code, http.StatusText(rec.Code), rec.Body.String()))
-		}
-	}
-}