diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,131 @@
 
 ---
 
+## [0.17.5] - 2026-08-19
+
+Point release on the 0.17.x line. Two language-surface changes lead: sum-type eliminators unify on
+`match` (scrutinee-first), and the primitive set is tentatively finalized — `strings.lines`/`unlines`
+are removed in favour of `hydra.formatting` term helpers. A symlink-aware filesystem family lands
+across all ten hosts, and Hydra's own build system continues its migration into Hydra.
+
+**Backward-incompatible.** The `cases` -> `match` rename and the `strings.lines`/`unlines` removal
+both change the published kernel surface. Code written against 0.17.4 that uses `Optionals.cases`
+or `strings.lines`/`strings.unlines` must be updated.
+
+### Highlights
+
+- **Sum-type eliminators unify on `match`** ([#615](https://github.com/CategoricalData/hydra/issues/615)):
+  the `cases`/`match` helper pair is flipped to a single scrutinee-first `match` convention across the
+  Haskell, Java, Python, and Scala DSLs, the `optionals.cases` -> `optionals.match` kernel primitive,
+  and the corresponding implementations in TypeScript and all four Lisp dialects.
+- **Primitive set tentatively finalized** ([#417](https://github.com/CategoricalData/hydra/issues/417)):
+  `strings.lines` and `strings.unlines` are removed as primitives; their semantics are preserved as
+  `hydra.formatting.lines`/`unlines` term helpers, with overlay implementations dropped across all ten
+  hosts and callers repointed.
+- **Symlink-aware filesystem primitives** ([#666](https://github.com/CategoricalData/hydra/issues/666)):
+  `status(followLinks)`, `createSymlink`, and `readSymlink` land with native implementations for every
+  host — Haskell, Java, Python, Scala, TypeScript, Clojure, Common Lisp, Scheme, and Emacs Lisp.
+- **Build system promotion continues** ([#416](https://github.com/CategoricalData/hydra/issues/416)):
+  adds `hydra.build.walk` extension-glob helpers (`extensionOf`/`filterByExtension`/`matchesExtension`)
+  and `hydra.build.comparereportlogic`, a set of pure snapshot-compare decision helpers.
+
+### Bug fixes
+
+- **`math.range` was inclusive of both bounds** ([#647](https://github.com/CategoricalData/hydra/issues/647)),
+  silently fabricating an extra element in index arithmetic.
+- **Java coder TCO-`cases` codegen** dropped enclosing-method type parameters from union-variant casts
+  (found via [#666](https://github.com/CategoricalData/hydra/issues/666)).
+- **`ShaclRdf` promoted to a DSL module** ([#652](https://github.com/CategoricalData/hydra/issues/652))
+  so the SHACL pipeline works outside Haskell.
+- **Cold-seed shim portability**: the R22 bootstrap shim used GNU-only `\+` and `\b`, which fail under
+  BSD `sed` on macOS ([#417](https://github.com/CategoricalData/hydra/issues/417)).
+- **Bootstrap Haskell target missing `unix`**: the demo's static `package.yaml` was not updated when
+  `System.Posix.Files` entered the kernel overlay, breaking every `*-to-haskell` bootstrap cell
+  ([#670](https://github.com/CategoricalData/hydra/issues/670)).
+- **Bootstrap comparison scored Scala and TypeScript cells as passing without comparing anything**:
+  `compare_output`'s target switch was missing both languages, so the baseline path was malformed,
+  every file counted as "no baseline found", and a zero-file comparison reported `pass`. A Scala or
+  TypeScript *target* cell could never fail ([#671](https://github.com/CategoricalData/hydra/issues/671)).
+
+### Known issues
+
+- A pre-#630 post-generation text pass rewrites `hydra.lib.<sub>` -> `hydra.overlay.<lang>.lib.<sub>`
+  in generated **doc comments** as well as code, because its quote-prefix guard does not recognize
+  mid-sentence prose references. Affects two kernel doc strings in `src/main`
+  (`hydra.error.system`, `hydra.error.packaging`) plus ~20 generated docstrings in the test tree;
+  cosmetic only, no behavioral impact. Tracked as part of
+  [#633](https://github.com/CategoricalData/hydra/issues/633).
+- Bootstrap comparison diff detail is not persisted to the run directory
+  ([#671](https://github.com/CategoricalData/hydra/issues/671)).
+
+---
+
+## [0.17.4] - 2026-08-09
+
+Point release on the 0.17.x line. Fixes an inference bug that mis-typed generated Java and Python for
+`readFile`, adds the `divide` primitive, and restores `hydra-ext` to the published package set. Release
+validation also surfaced a family of pre-existing cross-host code-generation defects — none of which the
+per-host CI jobs can catch, because only the bootstrap exercises one host generating *another*.
+
+### Highlights
+
+- **Output-only nominal generalization fixed** ([#637](https://github.com/CategoricalData/hydra/issues/637),
+  with [#638](https://github.com/CategoricalData/hydra/issues/638) /
+  [#639](https://github.com/CategoricalData/hydra/issues/639) /
+  [#640](https://github.com/CategoricalData/hydra/issues/640)): a nominal type appearing only in the
+  *output* position of a primitive's signature was generalized to a free type variable instead of resolving
+  as nominal, mis-typing the generated Java and Python for `readFile`. Also widens universe closure and adds
+  a `kernelTypeUniverse` helper, an effect DSL builder, and `effects`/`files`/`text`/`system` lib wrappers.
+- **`divide` primitive** ([#317](https://github.com/CategoricalData/hydra/issues/317)): now present in the
+  published kernel. This also clears the cold-clone dangle, since a cold seed against published 0.17.4
+  resolves `DefMath.divide`.
+- **`hydra-ext` republished** ([#636](https://github.com/CategoricalData/hydra/issues/636)): back in the
+  published set after its absence from 0.17.1–0.17.3, shipping to Hackage and PyPI.
+
+### Bug fixes
+
+- **Overlay-lib redirection skipped for the Haskell target**
+  ([#630](https://github.com/CategoricalData/hydra/issues/630)):
+  the Java, Python, Scheme, Clojure and Common Lisp heads resolved the overlay lib directory using an
+  all-lowercase path and did not lower-case the names they scanned. Haskell's overlay tree is capitalized
+  (`Hydra/Overlay/Haskell/Lib/`), so every `hydra.lib.*` redirect silently failed and the generated Haskell
+  imported `Hydra.Lib.*` instead of `Hydra.Overlay.Haskell.Lib.*`, producing hundreds of type errors. The
+  defect was invisible on case-sensitive filesystems, where the failed directory check falls back to a
+  hard-coded list that happens to be correct. The Python head carried *two* independent copies of this scan;
+  only the one in `generation.py` feeds the Haskell coder.
+- **Lisp-as-host bootstrap** ([#520](https://github.com/CategoricalData/hydra/issues/520),
+  [#630](https://github.com/CategoricalData/hydra/issues/630)): the four Lisp head decode drivers called
+  `from_json` with a stale 4-argument signature, and the Lisp bootstrap-driver coders were not pre-bound with
+  `overlaySubs`.
+- **Python-as-host dropped the `Graph` argument** ([#630](https://github.com/CategoricalData/hydra/issues/630)):
+  `overlaySubs` was not threaded into the Python head's `write_*` wrappers.
+- **Clojure `resolve-coder` and `decimal-to-float32`**
+  ([#630](https://github.com/CategoricalData/hydra/issues/630)): a stray parenthesis closed a `case` early,
+  making an unsupported-default block run unconditionally; and `(float (.doubleValue ...))` threw on
+  `Float.MAX_VALUE`, now saturating via `(.floatValue (bigdec x))`.
+- **Cold-seeder failed on macOS** ([#630](https://github.com/CategoricalData/hydra/issues/630)): the #376
+  cold seeder used a bare `sed -i -e`, which is GNU-only and aborts immediately under BSD `sed`.
+
+### Release engineering
+
+- **Review checkpoint before Maven Central publishes**
+  ([#591](https://github.com/CategoricalData/hydra/issues/591)): `HYDRA_JAVA_PUBLISH_HOLD=1` uploads the
+  aggregated Java deployment as `USER_MANAGED`, so it validates and then holds for review instead of
+  publishing automatically. This mirrors `HYDRA_SCALA_PUBLISH_HOLD` and makes an upload reversible — a held
+  deployment can be dropped, whereas an automatic one cannot be undone.
+
+### Known issues
+
+- **`hydra-ext` is not published to Maven Central**
+  ([#643](https://github.com/CategoricalData/hydra/issues/643)): it does not compile for the Java target,
+  because the visitor-pattern inner interface the Java coder emits collides with the enclosing `Visitor`
+  type in `hydra.cpp.syntax`. Only Java is affected; the Python coder emits sibling classes rather than
+  nested ones. ext ships to Hackage and PyPI at 0.17.4 and is expected to rejoin the Java set once fixed.
+- **TypeScript no longer self-hosts**
+  ([#642](https://github.com/CategoricalData/hydra/issues/642)): the TypeScript host's JSON decoder fails to
+  decode most of the kernel, so `typescript-as-host` code generation is broken. No published artifact is
+  affected — `dist/typescript` is generated by the Haskell host and passes its test suite.
+
 ## [0.17.3] - 2026-08-01
 
 Point release on the 0.17.x line, focused on **release-artifact integrity**. The 0.17.2 release shipped
diff --git a/hydra-build.cabal b/hydra-build.cabal
--- a/hydra-build.cabal
+++ b/hydra-build.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.39.1.
+-- This file has been generated from package.yaml by hpack version 0.38.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           hydra-build
-version:        0.17.4
+version:        0.17.5
 synopsis:       Hydra's build system, promoted into Hydra
 description:    Hydra is an implementation of the LambdaGraph data model, which takes advantage of an isomorphism between labeled hypergraphs and typed lambda calculus: in Hydra, "graphs are programs, and programs are graphs". This package is Hydra's build system, promoted into Hydra itself: the manifest-derived module-to-package router, kernel/host reconciliation utilities, and pure module-list helpers, expressed as Hydra modules and generated into every self-hosting dialect. It builds on hydra-kernel.
 category:       Data
@@ -27,15 +27,34 @@
 
 library
   exposed-modules:
+      Hydra.Build.Assembly
+      Hydra.Build.Assemblyplan
+      Hydra.Build.Benchresult
+      Hydra.Build.Comparereport
+      Hydra.Build.Comparereportlogic
       Hydra.Build.Format
+      Hydra.Build.Langexpansion
       Hydra.Build.Libraries
       Hydra.Build.ManifestWriter
       Hydra.Build.Modules
       Hydra.Build.PackagingProfile
+      Hydra.Build.Publishsets
       Hydra.Build.Reconcile
       Hydra.Build.Routing
+      Hydra.Build.Syncmatrix
+      Hydra.Build.Versionconsistency
+      Hydra.Build.Walk
+      Hydra.Decode.Build.Assembly
+      Hydra.Decode.Build.Benchresult
+      Hydra.Decode.Build.Comparereport
       Hydra.Decode.Build.Format
+      Hydra.Dsl.Build.Assembly
+      Hydra.Dsl.Build.Benchresult
+      Hydra.Dsl.Build.Comparereport
       Hydra.Dsl.Build.Format
+      Hydra.Encode.Build.Assembly
+      Hydra.Encode.Build.Benchresult
+      Hydra.Encode.Build.Comparereport
       Hydra.Encode.Build.Format
   other-modules:
       Paths_hydra_build
@@ -44,6 +63,6 @@
   build-depends:
       base >=4.19.0 && <4.22
     , containers >=0.6.7 && <0.8
-    , hydra-kernel ==0.17.4
+    , hydra-kernel ==0.17.5
     , scientific >=0.3.7 && <0.4
   default-language: Haskell2010
diff --git a/src/main/haskell/Hydra/Build/Assembly.hs b/src/main/haskell/Hydra/Build/Assembly.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Assembly.hs
@@ -0,0 +1,84 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Type-level model of a distribution package's assembly plan: the ordered copy/symlink entries and keep-paths that a host-native executor realizes on disk when merging overlay source onto a generated distribution package. Factors the copy(overlay/<lang>/<pkg>/) half of the governing equation into data, so the per-host copy scripts share one translingual description. See https://github.com/CategoricalData/hydra/issues/416
+
+module Hydra.Build.Assembly where
+
+import qualified Hydra.Core as Core
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | A single copy-or-link operation in an assembly plan: realize a source tree at a destination tree by the given kind, optionally excluding matching relative paths.
+data AssemblyEntry =
+  AssemblyEntry {
+    -- | The source tree to realize, as a worktree-relative path (e.g. overlay/<lang>/<pkg>/src)
+    assemblyEntrySourceTree :: String,
+    -- | The destination tree, as a worktree-relative path (e.g. dist/<lang>/<pkg>/src)
+    assemblyEntryDestTree :: String,
+    -- | How the source tree is realized at the destination
+    assemblyEntryKind :: AssemblyEntryKind,
+    -- | Relative path fragments to exclude when realizing the entry (e.g. __pycache__); empty means copy everything
+    assemblyEntryExclude :: [String]}
+  deriving (Eq, Ord, Read, Show)
+
+_AssemblyEntry = Core.Name "hydra.build.assembly.AssemblyEntry"
+
+_AssemblyEntry_sourceTree = Core.Name "sourceTree"
+
+_AssemblyEntry_destTree = Core.Name "destTree"
+
+_AssemblyEntry_kind = Core.Name "kind"
+
+_AssemblyEntry_exclude = Core.Name "exclude"
+
+-- | How an assembly entry's source tree is realized at its destination. The distinction gates the host-native executor's dispatch (merge-copy vs. wipe-then-copy vs. symlink).
+data AssemblyEntryKind =
+  -- | Merge-copy the source tree's files into the destination, leaving pre-existing files intact
+  AssemblyEntryKindMerge |
+  -- | Remove the destination tree entirely, then copy the source tree (an exact-mirror replacement)
+  AssemblyEntryKindWipeThenCopy |
+  -- | Symlink each of the source tree's files into the destination (per-file links; own real files win)
+  AssemblyEntryKindSymlinkTree |
+  -- | Symlink the source directory itself into the destination as a single directory link
+  AssemblyEntryKindSymlinkDir
+  deriving (Eq, Ord, Read, Show)
+
+_AssemblyEntryKind = Core.Name "hydra.build.assembly.AssemblyEntryKind"
+
+_AssemblyEntryKind_merge = Core.Name "merge"
+
+_AssemblyEntryKind_wipeThenCopy = Core.Name "wipeThenCopy"
+
+_AssemblyEntryKind_symlinkTree = Core.Name "symlinkTree"
+
+_AssemblyEntryKind_symlinkDir = Core.Name "symlinkDir"
+
+-- | The complete assembly plan for one distribution package in one target language: the ordered copy/symlink entries to realize and the keep-paths a pruning consumer must protect. Entries are ordered because realization order can matter (e.g. a package that links its own subtree back into an already-assembled dependency's tree).
+data AssemblyPlan =
+  AssemblyPlan {
+    -- | The copy/symlink entries to realize, in application order
+    assemblyPlanEntries :: [AssemblyEntry],
+    -- | The files this plan is responsible for, recorded so a prune-stale pass does not delete them
+    assemblyPlanKeepPaths :: [KeepPathEntry]}
+  deriving (Eq, Ord, Read, Show)
+
+_AssemblyPlan = Core.Name "hydra.build.assembly.AssemblyPlan"
+
+_AssemblyPlan_entries = Core.Name "entries"
+
+_AssemblyPlan_keepPaths = Core.Name "keepPaths"
+
+-- | One protected path in a keep-paths manifest: a source-set directory paired with a file's path relative to it. Serialized by the native executor as <sourceSetDir>\t<relPath>, bit-compatible with the prune-stale (#357) and digest-check --keep-paths-from consumers.
+data KeepPathEntry =
+  KeepPathEntry {
+    -- | The source-set directory the file belongs to, as a worktree-relative path
+    keepPathEntrySourceSetDir :: String,
+    -- | The file's path relative to its source-set directory
+    keepPathEntryRelPath :: String}
+  deriving (Eq, Ord, Read, Show)
+
+_KeepPathEntry = Core.Name "hydra.build.assembly.KeepPathEntry"
+
+_KeepPathEntry_sourceSetDir = Core.Name "sourceSetDir"
+
+_KeepPathEntry_relPath = Core.Name "relPath"
diff --git a/src/main/haskell/Hydra/Build/Assemblyplan.hs b/src/main/haskell/Hydra/Build/Assemblyplan.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Assemblyplan.hs
@@ -0,0 +1,109 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | The pure assembly-plan derivation: the ordered overlay-copy entries and keep-paths for a distribution package
+
+module Hydra.Build.Assemblyplan where
+
+import qualified Hydra.Ast as Ast
+import qualified Hydra.Coders as Coders
+import qualified Hydra.Core as Core
+import qualified Hydra.Docs as Docs
+import qualified Hydra.Error.Checking as Checking
+import qualified Hydra.Error.Core as ErrorCore
+import qualified Hydra.Error.File as ErrorFile
+import qualified Hydra.Error.Packaging as ErrorPackaging
+import qualified Hydra.Error.System as ErrorSystem
+import qualified Hydra.Errors as Errors
+import qualified Hydra.File as File
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Json.Model as Model
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import qualified Hydra.Overlay.Haskell.Lib.Pairs as Pairs
+import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
+import qualified Hydra.Packaging as Packaging
+import qualified Hydra.Parsing as Parsing
+import qualified Hydra.Paths as Paths
+import qualified Hydra.Query as Query
+import qualified Hydra.Regex as Regex
+import qualified Hydra.Relational as Relational
+import qualified Hydra.System as System
+import qualified Hydra.Tabular as Tabular
+import qualified Hydra.Testing as Testing
+import qualified Hydra.Time as Time
+import qualified Hydra.Topology as Topology
+import qualified Hydra.Typed as Typed
+import qualified Hydra.Typing as Typing
+import qualified Hydra.Util as Util
+import qualified Hydra.Validation as Validation
+import qualified Hydra.Variants as Variants
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | The full assembly plan (entries, keepPaths) for a (package, language) pair
+deriveAssemblyPlan :: String -> String -> [String] -> [(String, t0)] -> ([(String, (String, String))], [(String, t0)])
+deriveAssemblyPlan pkg lang availableTrees treeFiles =
+    (overlayEntries pkg lang availableTrees, (keepPathsFor pkg lang treeFiles))
+
+-- | The (sourceSetDir, relPath) keep-paths for a package's copied overlay files
+keepPathsFor :: String -> String -> [(String, t0)] -> [(String, t0)]
+keepPathsFor pkg lang treeFiles = Lists.map (\tf -> (remapDest pkg lang (Pairs.first tf), (Pairs.second tf))) treeFiles
+
+-- | The ordered (sourceTree, destTree, merge) overlay-copy entries for a package's available trees
+overlayEntries :: String -> String -> [String] -> [(String, (String, String))]
+overlayEntries pkg lang availableTrees =
+    Lists.map (\subdir -> (
+      sourceSetSubdir (Strings.concat [
+        "overlay/",
+        lang,
+        "/",
+        pkg]) subdir,
+      (
+        sourceSetSubdir (Strings.concat [
+          "dist/",
+          lang,
+          "/",
+          pkg]) subdir,
+        "merge"))) availableTrees
+
+-- | Remap an overlay source-set subdir to its dist/<lang>/<pkg>/<subdir> destination
+remapDest :: String -> String -> String -> String
+remapDest pkg lang subdir =
+    sourceSetSubdir (Strings.concat [
+      "dist/",
+      lang,
+      "/",
+      pkg]) subdir
+
+-- | Join a package root and a source-set subdirectory with a / separator
+sourceSetSubdir :: String -> String -> String
+sourceSetSubdir root subdir =
+    Strings.concat [
+      root,
+      "/",
+      subdir]
+
+-- | The TypeScript cross-package symlink graph as (sourceTree, destTree, kind) triples
+typescriptImportGraph :: [(String, (String, String))]
+typescriptImportGraph =
+    [
+      (kernelMain, (rdfMain, "symlinkTree")),
+      (kernelMain, (pgMain, "symlinkTree")),
+      (rdfMain, (pgMain, "symlinkTree")),
+      (kernelMain, (buildMain, "symlinkTree")),
+      (buildTest, (kernelTest, "symlinkTree")),
+      (
+        Strings.concat [
+          buildMain,
+          "/build"],
+        (
+          Strings.concat [
+            kernelMain,
+            "/build"],
+          "symlinkDir"))]
+  where
+    kernelMain = "dist/typescript/hydra-kernel/src/main/typescript/hydra"
+    kernelTest = "dist/typescript/hydra-kernel/src/test/typescript/hydra"
+    rdfMain = "dist/typescript/hydra-rdf/src/main/typescript/hydra"
+    pgMain = "dist/typescript/hydra-pg/src/main/typescript/hydra"
+    buildMain = "dist/typescript/hydra-build/src/main/typescript/hydra"
+    buildTest = "dist/typescript/hydra-build/src/test/typescript/hydra"
diff --git a/src/main/haskell/Hydra/Build/Benchresult.hs b/src/main/haskell/Hydra/Build/Benchresult.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Benchresult.hs
@@ -0,0 +1,90 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Type-level model for benchmark result JSON: a typed result model whose generated codec replaces the hand-rolled JSON assembly in the bench drivers. See https://github.com/CategoricalData/hydra/issues/416
+
+module Hydra.Build.Benchresult where
+
+import qualified Hydra.Core as Core
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+import qualified Data.Map as M
+
+-- | Per-run metadata: timestamp and git context of a benchmark run
+data BenchMetadata =
+  BenchMetadata {
+    -- | ISO-8601 UTC timestamp of the run
+    benchMetadataTimestamp :: String,
+    -- | The host language the benchmark ran on
+    benchMetadataLanguage :: String,
+    -- | The git branch
+    benchMetadataBranch :: String,
+    -- | The short git commit hash
+    benchMetadataCommit :: String,
+    -- | The commit subject line
+    benchMetadataCommitMessage :: String}
+  deriving (Eq, Ord, Read, Show)
+
+_BenchMetadata = Core.Name "hydra.build.benchresult.BenchMetadata"
+
+_BenchMetadata_timestamp = Core.Name "timestamp"
+
+_BenchMetadata_language = Core.Name "language"
+
+_BenchMetadata_branch = Core.Name "branch"
+
+_BenchMetadata_commit = Core.Name "commit"
+
+_BenchMetadata_commitMessage = Core.Name "commitMessage"
+
+-- | A generator-benchmark result: target, run count, and per-host results
+data GenBenchResult =
+  GenBenchResult {
+    -- | The target language being generated
+    genBenchResultTarget :: String,
+    -- | The number of timed runs per (host, package)
+    genBenchResultRuns :: Int,
+    -- | Per-host results, keyed by host language name
+    genBenchResultHosts :: (M.Map String HostResult),
+    -- | Optional run metadata
+    genBenchResultMetadata :: (Maybe BenchMetadata)}
+  deriving (Eq, Ord, Read, Show)
+
+_GenBenchResult = Core.Name "hydra.build.benchresult.GenBenchResult"
+
+_GenBenchResult_target = Core.Name "target"
+
+_GenBenchResult_runs = Core.Name "runs"
+
+_GenBenchResult_hosts = Core.Name "hosts"
+
+_GenBenchResult_metadata = Core.Name "metadata"
+
+-- | One host's generator-benchmark result: setup time and per-package timings
+data HostResult =
+  HostResult {
+    -- | Host setup/build time in milliseconds
+    hostResultSetupMs :: Int,
+    -- | Per-package run statistics, keyed by package name
+    hostResultPackages :: (M.Map String RunStats)}
+  deriving (Eq, Ord, Read, Show)
+
+_HostResult = Core.Name "hydra.build.benchresult.HostResult"
+
+_HostResult_setupMs = Core.Name "setupMs"
+
+_HostResult_packages = Core.Name "packages"
+
+-- | Timing statistics for one (host, package): per-run elapsed times and the median
+data RunStats =
+  RunStats {
+    -- | Each run's elapsed time in milliseconds
+    runStatsRunsMs :: [Int],
+    -- | The median elapsed time in milliseconds
+    runStatsMedianMs :: Int}
+  deriving (Eq, Ord, Read, Show)
+
+_RunStats = Core.Name "hydra.build.benchresult.RunStats"
+
+_RunStats_runsMs = Core.Name "runsMs"
+
+_RunStats_medianMs = Core.Name "medianMs"
diff --git a/src/main/haskell/Hydra/Build/Comparereport.hs b/src/main/haskell/Hydra/Build/Comparereport.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Comparereport.hs
@@ -0,0 +1,73 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Type-level model for the JSON snapshot compare-report: the per-module comparison record and the whole-report summary shared by the native generator drivers. See https://github.com/CategoricalData/hydra/issues/416
+
+module Hydra.Build.Comparereport where
+
+import qualified Hydra.Core as Core
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | The whole compare-report: per-module records plus the byte-identical tally
+data CompareReport =
+  CompareReport {
+    -- | One record per compared module
+    compareReportRows :: [ModuleCompare],
+    -- | How many modules were byte-identical
+    compareReportByteEqCount :: Int,
+    -- | How many modules were compared
+    compareReportTotal :: Int}
+  deriving (Eq, Ord, Read, Show)
+
+_CompareReport = Core.Name "hydra.build.comparereport.CompareReport"
+
+_CompareReport_rows = Core.Name "rows"
+
+_CompareReport_byteEqCount = Core.Name "byteEqCount"
+
+_CompareReport_total = Core.Name "total"
+
+-- | The result of comparing one module's JSON on the two sides
+data CompareStatus =
+  -- | The two sides are byte-identical
+  CompareStatusByteEq |
+  -- | Both sides exist but differ
+  CompareStatusDiffer |
+  -- | Our side is absent (the canonical side has the module, ours does not)
+  CompareStatusMissing
+  deriving (Eq, Ord, Read, Show)
+
+_CompareStatus = Core.Name "hydra.build.comparereport.CompareStatus"
+
+_CompareStatus_byteEq = Core.Name "byteEq"
+
+_CompareStatus_differ = Core.Name "differ"
+
+_CompareStatus_missing = Core.Name "missing"
+
+-- | One module's comparison record
+data ModuleCompare =
+  ModuleCompare {
+    -- | The module name (the JSON file's base name, without the .json suffix)
+    moduleCompareModule :: String,
+    -- | The comparison status
+    moduleCompareStatus :: CompareStatus,
+    -- | The byte size of our (freshly generated) side, or 0 if missing
+    moduleCompareOurSize :: Int,
+    -- | The byte size of the canonical side
+    moduleCompareCanonSize :: Int,
+    -- | The number of differing lines (0 when byte-identical)
+    moduleCompareDiffLines :: Int}
+  deriving (Eq, Ord, Read, Show)
+
+_ModuleCompare = Core.Name "hydra.build.comparereport.ModuleCompare"
+
+_ModuleCompare_module = Core.Name "module"
+
+_ModuleCompare_status = Core.Name "status"
+
+_ModuleCompare_ourSize = Core.Name "ourSize"
+
+_ModuleCompare_canonSize = Core.Name "canonSize"
+
+_ModuleCompare_diffLines = Core.Name "diffLines"
diff --git a/src/main/haskell/Hydra/Build/Comparereportlogic.hs b/src/main/haskell/Hydra/Build/Comparereportlogic.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Comparereportlogic.hs
@@ -0,0 +1,123 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Pure snapshot-compare decision helpers: per-module status/diff-count and the whole-report tally, over content both sides already read
+
+module Hydra.Build.Comparereportlogic where
+
+import qualified Hydra.Ast as Ast
+import qualified Hydra.Build.Walk as Walk
+import qualified Hydra.Coders as Coders
+import qualified Hydra.Core as Core
+import qualified Hydra.Docs as Docs
+import qualified Hydra.Error.Checking as Checking
+import qualified Hydra.Error.Core as ErrorCore
+import qualified Hydra.Error.File as ErrorFile
+import qualified Hydra.Error.Packaging as ErrorPackaging
+import qualified Hydra.Error.System as ErrorSystem
+import qualified Hydra.Errors as Errors
+import qualified Hydra.File as File
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Json.Model as Model
+import qualified Hydra.Overlay.Haskell.Lib.Equality as Equality
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import qualified Hydra.Overlay.Haskell.Lib.Literals as Literals
+import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
+import qualified Hydra.Overlay.Haskell.Lib.Math as Math
+import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
+import qualified Hydra.Overlay.Haskell.Lib.Ordering as Ordering
+import qualified Hydra.Overlay.Haskell.Lib.Pairs as Pairs
+import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
+import qualified Hydra.Packaging as Packaging
+import qualified Hydra.Parsing as Parsing
+import qualified Hydra.Paths as Paths
+import qualified Hydra.Query as Query
+import qualified Hydra.Regex as Regex
+import qualified Hydra.Relational as Relational
+import qualified Hydra.System as System
+import qualified Hydra.Tabular as Tabular
+import qualified Hydra.Testing as Testing
+import qualified Hydra.Time as Time
+import qualified Hydra.Topology as Topology
+import qualified Hydra.Typed as Typed
+import qualified Hydra.Typing as Typing
+import qualified Hydra.Util as Util
+import qualified Hydra.Validation as Validation
+import qualified Hydra.Variants as Variants
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | The whole compare-report (rows, byteEqCount, total) over enumerated module triples
+buildReport :: [(t0, (Maybe String, (Maybe String)))] -> ([(t0, (String, Int))], (Int, Int))
+buildReport inputs =
+
+      let rows =
+              Lists.map (\t -> compareModule (Pairs.first t) (Pairs.first (Pairs.second t)) (Pairs.second (Pairs.second t))) inputs
+          byteEqCount = Lists.length (Lists.filter (\r -> Equality.equal (Pairs.first (Pairs.second r)) "byteEq") rows)
+      in (rows, (byteEqCount, (Lists.length rows)))
+
+-- | Compare one module (both sides pre-read) to a (name, statusTag, diffLines) triple
+compareModule :: t0 -> Maybe String -> Maybe String -> (t0, (String, Int))
+compareModule name ourContent canonContent =
+    Optionals.match ourContent (name, ("missing", 0)) (\ours -> Optionals.match canonContent (name, ("missing", 0)) (\canon -> Logic.ifElse (Equality.equal ours canon) (name, ("byteEq", 0)) (name, ("differ", (diffLineCount ours canon)))))
+
+-- | Symmetric count of lines present in one content but not the other
+diffLineCount :: String -> String -> Int
+diffLineCount a b =
+
+      let aLines = Strings.splitOn "\n" a
+          bLines = Strings.splitOn "\n" b
+          onlyA = Lists.length (Lists.filter (\x -> Logic.not (Lists.member x bLines)) aLines)
+          onlyB = Lists.length (Lists.filter (\y -> Logic.not (Lists.member y aLines)) bLines)
+      in (Math.add onlyA onlyB)
+
+-- | The .json entries (sorted), with the .json suffix stripped, as module names
+moduleNamesFromEntries :: [String] -> [String]
+moduleNamesFromEntries entries = Lists.map (\e -> stripJsonSuffix e) (Walk.filterByExtension "json" entries)
+
+-- | The formatted per-module lines plus the byte-identical tally line
+renderReport :: ([(String, (String, Int))], (Int, Int)) -> String
+renderReport report =
+
+      let rows = Pairs.first report
+          byteEqCount = Pairs.first (Pairs.second report)
+          total = Pairs.second (Pairs.second report)
+          rowLines = Lists.map (\r -> renderRow r) rows
+          summary =
+                  Strings.concat [
+                    Literals.showInt32 byteEqCount,
+                    "/",
+                    (Literals.showInt32 total),
+                    " byte-identical"]
+      in (Strings.join "\n" (Lists.concat [
+        rowLines,
+        [
+          summary]]))
+
+-- | One report row rendered as a line: name: status[ (n lines differ)]
+renderRow :: (String, (String, Int)) -> String
+renderRow row =
+
+      let name = Pairs.first row
+          status = Pairs.first (Pairs.second row)
+          diffLines = Pairs.second (Pairs.second row)
+      in (Logic.ifElse (Equality.equal status "differ") (Strings.concat [
+        name,
+        ": ",
+        status,
+        " (",
+        (Literals.showInt32 diffLines),
+        " lines differ)"]) (Strings.concat [
+        name,
+        ": ",
+        status]))
+
+-- | Whether every compared module was byte-identical (byteEqCount == total)
+reportPassed :: Eq t1 => ((t0, (t1, t1)) -> Bool)
+reportPassed report = Equality.equal (Pairs.first (Pairs.second report)) (Pairs.second (Pairs.second report))
+
+-- | Strip a trailing .json from an entry name, yielding the module name
+stripJsonSuffix :: String -> String
+stripJsonSuffix entry =
+
+      let parts = Strings.splitOn "." entry
+      in (Logic.ifElse (Ordering.gt (Lists.length parts) 1) (Strings.join "." (Lists.take (Math.sub (Lists.length parts) 1) parts)) entry)
diff --git a/src/main/haskell/Hydra/Build/Format.hs b/src/main/haskell/Hydra/Build/Format.hs
--- a/src/main/haskell/Hydra/Build/Format.hs
+++ b/src/main/haskell/Hydra/Build/Format.hs
@@ -6,7 +6,7 @@
 
 import qualified Hydra.Core as Core
 import qualified Hydra.Packaging as Packaging
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Map as M
 
diff --git a/src/main/haskell/Hydra/Build/Langexpansion.hs b/src/main/haskell/Hydra/Build/Langexpansion.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Langexpansion.hs
@@ -0,0 +1,90 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Pure language/host list-expansion utilities shared by the sync/test/bench drivers
+
+module Hydra.Build.Langexpansion where
+
+import qualified Hydra.Ast as Ast
+import qualified Hydra.Coders as Coders
+import qualified Hydra.Core as Core
+import qualified Hydra.Docs as Docs
+import qualified Hydra.Error.Checking as Checking
+import qualified Hydra.Error.Core as ErrorCore
+import qualified Hydra.Error.File as ErrorFile
+import qualified Hydra.Error.Packaging as ErrorPackaging
+import qualified Hydra.Error.System as ErrorSystem
+import qualified Hydra.Errors as Errors
+import qualified Hydra.File as File
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Json.Model as Model
+import qualified Hydra.Overlay.Haskell.Lib.Equality as Equality
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
+import qualified Hydra.Packaging as Packaging
+import qualified Hydra.Parsing as Parsing
+import qualified Hydra.Paths as Paths
+import qualified Hydra.Query as Query
+import qualified Hydra.Regex as Regex
+import qualified Hydra.Relational as Relational
+import qualified Hydra.Strip as Strip
+import qualified Hydra.System as System
+import qualified Hydra.Tabular as Tabular
+import qualified Hydra.Testing as Testing
+import qualified Hydra.Time as Time
+import qualified Hydra.Topology as Topology
+import qualified Hydra.Typed as Typed
+import qualified Hydra.Typing as Typing
+import qualified Hydra.Util as Util
+import qualified Hydra.Validation as Validation
+import qualified Hydra.Variants as Variants
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | The canonical set of all target languages
+allLanguages :: [String]
+allLanguages =
+    [
+      "haskell",
+      "java",
+      "python",
+      "scala",
+      "go",
+      "typescript",
+      "clojure",
+      "scheme",
+      "common-lisp",
+      "emacs-lisp"]
+
+-- | Expand a single language token: 'all' -> all languages, 'lisp' -> the dialects, else itself
+expandLangAlias :: String -> [String]
+expandLangAlias tok =
+    Logic.ifElse (Equality.equal tok "all") allLanguages (Logic.ifElse (Equality.equal tok "lisp") lispDialects [
+      tok])
+
+-- | Expand a list of language tokens (aliases resolved), preserving order, deduped
+expandLangs :: [String] -> [String]
+expandLangs toks = Lists.distinct (Lists.concat (Lists.map (\tok -> expandLangAlias tok) toks))
+
+-- | Whether a language token is a known target language
+isKnownLang :: String -> Bool
+isKnownLang lang = Lists.member lang allLanguages
+
+-- | The expanded, deduped union of two token lists (hosts + targets)
+langUnion :: [String] -> [String] -> [String]
+langUnion hosts targets =
+    expandLangs (Lists.concat [
+      hosts,
+      targets])
+
+-- | The four Lisp dialects the 'lisp' alias expands to
+lispDialects :: [String]
+lispDialects =
+    [
+      "clojure",
+      "common-lisp",
+      "emacs-lisp",
+      "scheme"]
+
+-- | Validate a token list; return the unknown expanded tokens (empty = all valid)
+validateLangs :: [String] -> [String]
+validateLangs toks = Lists.filter (\lang -> Logic.not (isKnownLang lang)) (expandLangs toks)
diff --git a/src/main/haskell/Hydra/Build/Libraries.hs b/src/main/haskell/Hydra/Build/Libraries.hs
--- a/src/main/haskell/Hydra/Build/Libraries.hs
+++ b/src/main/haskell/Hydra/Build/Libraries.hs
@@ -34,7 +34,7 @@
 import qualified Hydra.Util as Util
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 
 -- | Every hydra.lib.<sub> module name every self-hosting host must register
diff --git a/src/main/haskell/Hydra/Build/ManifestWriter.hs b/src/main/haskell/Hydra/Build/ManifestWriter.hs
--- a/src/main/haskell/Hydra/Build/ManifestWriter.hs
+++ b/src/main/haskell/Hydra/Build/ManifestWriter.hs
@@ -35,7 +35,7 @@
 import qualified Hydra.Util as Util
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 
 -- | The manifest.json contents for one package: field assembly + serialization, given the package name and its main/dsl/encoding/test module lists
diff --git a/src/main/haskell/Hydra/Build/Modules.hs b/src/main/haskell/Hydra/Build/Modules.hs
--- a/src/main/haskell/Hydra/Build/Modules.hs
+++ b/src/main/haskell/Hydra/Build/Modules.hs
@@ -40,7 +40,7 @@
 import qualified Hydra.Util as Util
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 
 -- | Deduplicate a list of strings, preserving first-occurrence order
@@ -54,7 +54,7 @@
       let startsWith =
               \prefix -> \s ->
                 let parts = Strings.splitOn prefix s
-                in (Optionals.cases (Lists.uncons parts) False (\uc -> Logic.and (Strings.null (Pairs.first uc)) (Logic.not (Lists.null (Pairs.second uc)))))
+                in (Optionals.match (Lists.uncons parts) False (\uc -> Logic.and (Strings.null (Pairs.first uc)) (Logic.not (Lists.null (Pairs.second uc)))))
       in (Lists.filter (\m ->
         let name = Packaging.unModuleName (Packaging.moduleName m)
         in (Logic.and (Logic.not (startsWith "hydra." name)) (Logic.not (startsWith "hydra.json.yaml." name)))) mods)
diff --git a/src/main/haskell/Hydra/Build/PackagingProfile.hs b/src/main/haskell/Hydra/Build/PackagingProfile.hs
--- a/src/main/haskell/Hydra/Build/PackagingProfile.hs
+++ b/src/main/haskell/Hydra/Build/PackagingProfile.hs
@@ -36,7 +36,7 @@
 import qualified Hydra.Validate.Packaging as ValidatePackaging
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 
 -- | Whether a package's dist/json is written by a separate native driver, so it is excluded from structural validation
diff --git a/src/main/haskell/Hydra/Build/Publishsets.hs b/src/main/haskell/Hydra/Build/Publishsets.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Publishsets.hs
@@ -0,0 +1,61 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Publish-set dependency-closure guard and leaves-first ordering, shared by the publish drivers
+
+module Hydra.Build.Publishsets where
+
+import qualified Hydra.Ast as Ast
+import qualified Hydra.Coders as Coders
+import qualified Hydra.Core as Core
+import qualified Hydra.Docs as Docs
+import qualified Hydra.Error.Checking as Checking
+import qualified Hydra.Error.Core as ErrorCore
+import qualified Hydra.Error.File as ErrorFile
+import qualified Hydra.Error.Packaging as ErrorPackaging
+import qualified Hydra.Error.System as ErrorSystem
+import qualified Hydra.Errors as Errors
+import qualified Hydra.File as File
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Json.Model as Model
+import qualified Hydra.Overlay.Haskell.Lib.Eithers as Eithers
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
+import qualified Hydra.Packaging as Packaging
+import qualified Hydra.Parsing as Parsing
+import qualified Hydra.Paths as Paths
+import qualified Hydra.Query as Query
+import qualified Hydra.Regex as Regex
+import qualified Hydra.Relational as Relational
+import qualified Hydra.Sorting as Sorting
+import qualified Hydra.Strip as Strip
+import qualified Hydra.System as System
+import qualified Hydra.Tabular as Tabular
+import qualified Hydra.Testing as Testing
+import qualified Hydra.Time as Time
+import qualified Hydra.Topology as Topology
+import qualified Hydra.Typed as Typed
+import qualified Hydra.Typing as Typing
+import qualified Hydra.Util as Util
+import qualified Hydra.Validation as Validation
+import qualified Hydra.Variants as Variants
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | Whether the publish set is dependency-closed given the externally-satisfied set
+isPublishSetClosed :: [Packaging.Package] -> [Packaging.PackageName] -> [Packaging.PackageName] -> Bool
+isPublishSetClosed packages publishSet externallySatisfied =
+    Lists.null (strandedDeps packages publishSet externallySatisfied)
+
+-- | The names of a package's direct dependencies
+packageDepNames :: Packaging.Package -> [Packaging.PackageName]
+packageDepNames pkg = Lists.map (\d -> Packaging.packageDependencyName d) (Packaging.packageDependencies pkg)
+
+-- | The publish set in leaves-first topological order
+publishSetTopoOrder :: [Packaging.Package] -> [Packaging.PackageName] -> [Packaging.PackageName]
+publishSetTopoOrder packages publishSet =
+    Eithers.either (\_cycles -> publishSet) (\sorted -> sorted) (Sorting.topologicalSort (Lists.map (\pkg -> (Packaging.packageName pkg, (Lists.filter (\dep -> Lists.member dep publishSet) (packageDepNames pkg)))) (Lists.filter (\pkg -> Lists.member (Packaging.packageName pkg) publishSet) packages)))
+
+-- | The (member, missingDep) pairs stranded by publishing the set (empty = closed)
+strandedDeps :: [Packaging.Package] -> [Packaging.PackageName] -> [Packaging.PackageName] -> [(Packaging.PackageName, Packaging.PackageName)]
+strandedDeps packages publishSet externallySatisfied =
+    Lists.concat (Lists.map (\pkg -> Lists.map (\dep -> (Packaging.packageName pkg, dep)) (Lists.filter (\dep -> Logic.and (Logic.not (Lists.member dep publishSet)) (Logic.not (Lists.member dep externallySatisfied))) (packageDepNames pkg))) (Lists.filter (\pkg -> Lists.member (Packaging.packageName pkg) publishSet) packages))
diff --git a/src/main/haskell/Hydra/Build/Reconcile.hs b/src/main/haskell/Hydra/Build/Reconcile.hs
--- a/src/main/haskell/Hydra/Build/Reconcile.hs
+++ b/src/main/haskell/Hydra/Build/Reconcile.hs
@@ -41,7 +41,7 @@
 import qualified Hydra.Util as Util
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Set as S
 
@@ -50,7 +50,7 @@
 extensionOf path =
 
       let segs = Strings.splitOn "/" path
-      in (Optionals.cases (Lists.last segs) Nothing (\fileName ->
+      in (Optionals.match (Lists.last segs) Nothing (\fileName ->
         let dotParts = Strings.splitOn "." fileName
         in (Logic.ifElse (Ordering.gt (Lists.length dotParts) 1) (Lists.last dotParts) Nothing)))
 
@@ -73,12 +73,12 @@
 -- | Whether a path's extension satisfies the optional extension restriction
 matchesExts :: Maybe (S.Set String) -> String -> Bool
 matchesExts restrictExts path =
-    Optionals.cases restrictExts True (\exts -> Optionals.cases (extensionOf path) False (\ext -> Sets.member ext exts))
+    Optionals.match restrictExts True (\exts -> Optionals.match (extensionOf path) False (\ext -> Sets.member ext exts))
 
 -- | Whether a path satisfies the optional prefix restriction
 matchesPrefixes :: Maybe (S.Set String) -> String -> Bool
 matchesPrefixes restrictPrefixes path =
-    Optionals.cases restrictPrefixes True (\prefixes -> isUnderAnyPrefix prefixes path)
+    Optionals.match restrictPrefixes True (\prefixes -> isUnderAnyPrefix prefixes path)
 
 -- | The owned second-level prefixes (e.g. hydra/java) derived from written module names
 ownedPrefixes :: [Packaging.ModuleName] -> S.Set String
diff --git a/src/main/haskell/Hydra/Build/Routing.hs b/src/main/haskell/Hydra/Build/Routing.hs
--- a/src/main/haskell/Hydra/Build/Routing.hs
+++ b/src/main/haskell/Hydra/Build/Routing.hs
@@ -43,7 +43,7 @@
 import qualified Hydra.Util as Util
 import qualified Hydra.Validation as Validation
 import qualified Hydra.Variants as Variants
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Map as M
 
@@ -81,7 +81,7 @@
 -- | Map a module name to the package that owns it, failing loudly if unrouted
 namespaceToPackageIn :: M.Map Packaging.ModuleName t0 -> Packaging.ModuleName -> Either Errors.Error t0
 namespaceToPackageIn rm ns =
-    Optionals.cases (Maps.lookup ns rm) (Left (Errors.ErrorOther (Errors.OtherError (Strings.concat [
+    Optionals.match (Maps.lookup ns rm) (Left (Errors.ErrorOther (Errors.OtherError (Strings.concat [
       "unrouted module: ",
       (Packaging.unModuleName ns),
       " is not declared in any package's manifest (RoutingMap). Add it to the owning package's Manifest.mainModules."])))) (\p -> Right p)
@@ -95,6 +95,6 @@
                   Packaging.ModuleName (Strings.concat [
                     "hydra.sources.",
                     (Packaging.unModuleName ns)])
-      in (Optionals.cases (Lists.uncons parts) fallback (\uc -> Packaging.ModuleName (Strings.concat [
+      in (Optionals.match (Lists.uncons parts) fallback (\uc -> Packaging.ModuleName (Strings.concat [
         "hydra.sources.",
         (Strings.join "." (Pairs.second uc))])))
diff --git a/src/main/haskell/Hydra/Build/Syncmatrix.hs b/src/main/haskell/Hydra/Build/Syncmatrix.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Syncmatrix.hs
@@ -0,0 +1,72 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Pure sync-matrix (package, target) planning core shared by the sync driver
+
+module Hydra.Build.Syncmatrix where
+
+import qualified Hydra.Ast as Ast
+import qualified Hydra.Build.Langexpansion as Langexpansion
+import qualified Hydra.Coders as Coders
+import qualified Hydra.Core as Core
+import qualified Hydra.Docs as Docs
+import qualified Hydra.Error.Checking as Checking
+import qualified Hydra.Error.Core as ErrorCore
+import qualified Hydra.Error.File as ErrorFile
+import qualified Hydra.Error.Packaging as ErrorPackaging
+import qualified Hydra.Error.System as ErrorSystem
+import qualified Hydra.Errors as Errors
+import qualified Hydra.File as File
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Json.Model as Model
+import qualified Hydra.Overlay.Haskell.Lib.Equality as Equality
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
+import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
+import qualified Hydra.Packaging as Packaging
+import qualified Hydra.Parsing as Parsing
+import qualified Hydra.Paths as Paths
+import qualified Hydra.Query as Query
+import qualified Hydra.Regex as Regex
+import qualified Hydra.Relational as Relational
+import qualified Hydra.Strip as Strip
+import qualified Hydra.System as System
+import qualified Hydra.Tabular as Tabular
+import qualified Hydra.Testing as Testing
+import qualified Hydra.Time as Time
+import qualified Hydra.Topology as Topology
+import qualified Hydra.Typed as Typed
+import qualified Hydra.Typing as Typing
+import qualified Hydra.Util as Util
+import qualified Hydra.Validation as Validation
+import qualified Hydra.Variants as Variants
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | Rule 3: (hydra-target, host) for every (host, target) with host /= haskell
+crossHostCells :: [String] -> [String] -> [(String, String)]
+crossHostCells hosts targets =
+    Lists.concat (Lists.map (\host -> Lists.map (\target -> (packageForLanguage target, host)) targets) (Lists.filter (\host -> Logic.not (Equality.equal host "haskell")) hosts))
+
+-- | Rule 1: (hydra-kernel, L) for every L in (hosts union targets)
+kernelCells :: [t0] -> [(String, t0)]
+kernelCells langUnion = Lists.map (\lang -> ("hydra-kernel", lang)) langUnion
+
+-- | The distribution package name for a language: hydra-<language>
+packageForLanguage :: String -> String
+packageForLanguage lang = Strings.concat2 "hydra-" lang
+
+-- | Rule 2: (hydra-L, haskell) for every L in (hosts union targets)
+rootCoderCells :: [String] -> [(String, String)]
+rootCoderCells langUnion = Lists.map (\lang -> (packageForLanguage lang, "haskell")) langUnion
+
+-- | The full (package, target) sync matrix for a (hosts, targets) request
+syncMatrix :: [String] -> [String] -> [(String, String)]
+syncMatrix hosts targets =
+
+      let expandedHosts = Langexpansion.expandLangs hosts
+          expandedTargets = Langexpansion.expandLangs targets
+          union = Langexpansion.langUnion hosts targets
+      in (Lists.distinct (Lists.concat [
+        kernelCells union,
+        (rootCoderCells union),
+        (crossHostCells expandedHosts expandedTargets)]))
diff --git a/src/main/haskell/Hydra/Build/Versionconsistency.hs b/src/main/haskell/Hydra/Build/Versionconsistency.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Versionconsistency.hs
@@ -0,0 +1,59 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Version-consistency pure logic (file/format manifest + per-format version extraction) shared by the release/bump drivers
+
+module Hydra.Build.Versionconsistency where
+
+import qualified Hydra.Ast as Ast
+import qualified Hydra.Coders as Coders
+import qualified Hydra.Core as Core
+import qualified Hydra.Docs as Docs
+import qualified Hydra.Error.Checking as Checking
+import qualified Hydra.Error.Core as ErrorCore
+import qualified Hydra.Error.File as ErrorFile
+import qualified Hydra.Error.Packaging as ErrorPackaging
+import qualified Hydra.Error.System as ErrorSystem
+import qualified Hydra.Errors as Errors
+import qualified Hydra.File as File
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Json.Model as Model
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
+import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
+import qualified Hydra.Overlay.Haskell.Lib.Ordering as Ordering
+import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
+import qualified Hydra.Packaging as Packaging
+import qualified Hydra.Parsing as Parsing
+import qualified Hydra.Paths as Paths
+import qualified Hydra.Query as Query
+import qualified Hydra.Regex as Regex
+import qualified Hydra.Relational as Relational
+import qualified Hydra.Strip as Strip
+import qualified Hydra.System as System
+import qualified Hydra.Tabular as Tabular
+import qualified Hydra.Testing as Testing
+import qualified Hydra.Time as Time
+import qualified Hydra.Topology as Topology
+import qualified Hydra.Typed as Typed
+import qualified Hydra.Typing as Typing
+import qualified Hydra.Util as Util
+import qualified Hydra.Validation as Validation
+import qualified Hydra.Variants as Variants
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | The substring between the first open delimiter and the next close delimiter
+betweenDelimiters :: String -> String -> String -> Maybe String
+betweenDelimiters open close s =
+
+      let afterParts = Strings.splitOn open s
+      in (Logic.ifElse (Ordering.lt (Lists.length afterParts) 2) Nothing (Optionals.bind (Lists.at 1 afterParts) (\after ->
+        let closeParts = Strings.splitOn close after
+        in (Lists.at 0 closeParts))))
+
+-- | The version token following a bare marker prefix on a line
+versionAfterMarker :: String -> String -> Maybe String
+versionAfterMarker marker s =
+
+      let parts = Strings.splitOn marker s
+      in (Logic.ifElse (Ordering.lt (Lists.length parts) 2) Nothing (Optionals.bind (Lists.at 1 parts) (\rest -> Lists.at 0 (Strings.splitOn " " rest))))
diff --git a/src/main/haskell/Hydra/Build/Walk.hs b/src/main/haskell/Hydra/Build/Walk.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Build/Walk.hs
@@ -0,0 +1,74 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Pure directory-traversal decision helpers: deterministic ordering and basename matching over observed paths
+
+module Hydra.Build.Walk where
+
+import qualified Hydra.Ast as Ast
+import qualified Hydra.Coders as Coders
+import qualified Hydra.Core as Core
+import qualified Hydra.Docs as Docs
+import qualified Hydra.Error.Checking as Checking
+import qualified Hydra.Error.Core as ErrorCore
+import qualified Hydra.Error.File as ErrorFile
+import qualified Hydra.Error.Packaging as ErrorPackaging
+import qualified Hydra.Error.System as ErrorSystem
+import qualified Hydra.Errors as Errors
+import qualified Hydra.File as File
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Json.Model as Model
+import qualified Hydra.Overlay.Haskell.Lib.Equality as Equality
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
+import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
+import qualified Hydra.Overlay.Haskell.Lib.Ordering as Ordering
+import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
+import qualified Hydra.Packaging as Packaging
+import qualified Hydra.Parsing as Parsing
+import qualified Hydra.Paths as Paths
+import qualified Hydra.Query as Query
+import qualified Hydra.Regex as Regex
+import qualified Hydra.Relational as Relational
+import qualified Hydra.System as System
+import qualified Hydra.Tabular as Tabular
+import qualified Hydra.Testing as Testing
+import qualified Hydra.Time as Time
+import qualified Hydra.Topology as Topology
+import qualified Hydra.Typed as Typed
+import qualified Hydra.Typing as Typing
+import qualified Hydra.Util as Util
+import qualified Hydra.Validation as Validation
+import qualified Hydra.Variants as Variants
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | The final /-separated segment of a path (its file name)
+baseName :: String -> String
+baseName path = Optionals.match (Lists.last (Strings.splitOn "/" path)) path (\seg -> seg)
+
+-- | The extension of a path (after the final . in its file name), or empty if none
+extensionOf :: String -> String
+extensionOf path =
+
+      let dotParts = Strings.splitOn "." (baseName path)
+      in (Logic.ifElse (Ordering.gt (Lists.length dotParts) 1) (Optionals.match (Lists.last dotParts) "" (\ext -> ext)) "")
+
+-- | Paths whose file name equals the given name, sorted deterministically
+filterByBaseName :: String -> [String] -> [String]
+filterByBaseName name paths = sortPaths (Lists.filter (\path -> matchesBaseName name path) paths)
+
+-- | Paths whose extension equals the given extension, sorted deterministically
+filterByExtension :: String -> [String] -> [String]
+filterByExtension ext paths = sortPaths (Lists.filter (\path -> matchesExtension ext path) paths)
+
+-- | Whether a path's file name equals the given name
+matchesBaseName :: String -> String -> Bool
+matchesBaseName name path = Equality.equal (baseName path) name
+
+-- | Whether a path's extension equals the given extension
+matchesExtension :: String -> String -> Bool
+matchesExtension ext path = Equality.equal (extensionOf path) ext
+
+-- | Sort a list of paths into a deterministic ascending order
+sortPaths :: Ord t0 => ([t0] -> [t0])
+sortPaths paths = Lists.sort paths
diff --git a/src/main/haskell/Hydra/Decode/Build/Assembly.hs b/src/main/haskell/Hydra/Decode/Build/Assembly.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Decode/Build/Assembly.hs
@@ -0,0 +1,101 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Term decoders for hydra.build.assembly
+
+module Hydra.Decode.Build.Assembly where
+
+import qualified Hydra.Build.Assembly as Assembly
+import qualified Hydra.Core as Core
+import qualified Hydra.Errors as Errors
+import qualified Hydra.Extract.Core as ExtractCore
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Lexical as Lexical
+import qualified Hydra.Overlay.Haskell.Lib.Eithers as Eithers
+import qualified Hydra.Overlay.Haskell.Lib.Maps as Maps
+import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
+import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
+import qualified Hydra.Rewriting as Rewriting
+import qualified Hydra.Util as Util
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | Decoder for hydra.build.assembly.AssemblyEntry
+assemblyEntry :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Assembly.AssemblyEntry
+assemblyEntry cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "sourceTree" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_sourceTree -> Eithers.bind (ExtractCore.requireField "destTree" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_destTree -> Eithers.bind (ExtractCore.requireField "kind" assemblyEntryKind fieldMap cx) (\field_kind -> Eithers.bind (ExtractCore.requireField "exclude" (ExtractCore.decodeList (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2))) fieldMap cx) (\field_exclude -> Right (Assembly.AssemblyEntry {
+          Assembly.assemblyEntrySourceTree = field_sourceTree,
+          Assembly.assemblyEntryDestTree = field_destTree,
+          Assembly.assemblyEntryKind = field_kind,
+          Assembly.assemblyEntryExclude = field_exclude}))))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.assembly.AssemblyEntry")) (ExtractCore.stripWithDecodingError cx raw)
+
+-- | Decoder for hydra.build.assembly.AssemblyEntryKind
+assemblyEntryKind :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Assembly.AssemblyEntryKind
+assemblyEntryKind cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermInject v0 ->
+        let field = Core.injectionField v0
+            fname = Core.fieldName field
+            fterm = Core.fieldTerm field
+            variantMap =
+                    Maps.fromList [
+                      (Core.Name "merge", (\input -> Eithers.map (\t -> Assembly.AssemblyEntryKindMerge) (ExtractCore.decodeUnit cx input))),
+                      (
+                        Core.Name "wipeThenCopy",
+                        (\input -> Eithers.map (\t -> Assembly.AssemblyEntryKindWipeThenCopy) (ExtractCore.decodeUnit cx input))),
+                      (
+                        Core.Name "symlinkTree",
+                        (\input -> Eithers.map (\t -> Assembly.AssemblyEntryKindSymlinkTree) (ExtractCore.decodeUnit cx input))),
+                      (
+                        Core.Name "symlinkDir",
+                        (\input -> Eithers.map (\t -> Assembly.AssemblyEntryKindSymlinkDir) (ExtractCore.decodeUnit cx input)))]
+        in (Optionals.match (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
+          "no such field ",
+          (Core.unName fname),
+          " in union"]))) (\f -> f fterm))
+      _ -> Left (Errors.DecodingError "expected union")) (ExtractCore.stripWithDecodingError cx raw)
+
+-- | Decoder for hydra.build.assembly.AssemblyPlan
+assemblyPlan :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Assembly.AssemblyPlan
+assemblyPlan cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "entries" (ExtractCore.decodeList assemblyEntry) fieldMap cx) (\field_entries -> Eithers.bind (ExtractCore.requireField "keepPaths" (ExtractCore.decodeList keepPathEntry) fieldMap cx) (\field_keepPaths -> Right (Assembly.AssemblyPlan {
+          Assembly.assemblyPlanEntries = field_entries,
+          Assembly.assemblyPlanKeepPaths = field_keepPaths}))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.assembly.AssemblyPlan")) (ExtractCore.stripWithDecodingError cx raw)
+
+-- | Decoder for hydra.build.assembly.KeepPathEntry
+keepPathEntry :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Assembly.KeepPathEntry
+keepPathEntry cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "sourceSetDir" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_sourceSetDir -> Eithers.bind (ExtractCore.requireField "relPath" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_relPath -> Right (Assembly.KeepPathEntry {
+          Assembly.keepPathEntrySourceSetDir = field_sourceSetDir,
+          Assembly.keepPathEntryRelPath = field_relPath}))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.assembly.KeepPathEntry")) (ExtractCore.stripWithDecodingError cx raw)
diff --git a/src/main/haskell/Hydra/Decode/Build/Benchresult.hs b/src/main/haskell/Hydra/Decode/Build/Benchresult.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Decode/Build/Benchresult.hs
@@ -0,0 +1,122 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Term decoders for hydra.build.benchresult
+
+module Hydra.Decode.Build.Benchresult where
+
+import qualified Hydra.Build.Benchresult as Benchresult
+import qualified Hydra.Core as Core
+import qualified Hydra.Errors as Errors
+import qualified Hydra.Extract.Core as ExtractCore
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Lexical as Lexical
+import qualified Hydra.Overlay.Haskell.Lib.Eithers as Eithers
+import qualified Hydra.Rewriting as Rewriting
+import qualified Hydra.Util as Util
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | Decoder for hydra.build.benchresult.BenchMetadata
+benchMetadata :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Benchresult.BenchMetadata
+benchMetadata cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "timestamp" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_timestamp -> Eithers.bind (ExtractCore.requireField "language" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_language -> Eithers.bind (ExtractCore.requireField "branch" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_branch -> Eithers.bind (ExtractCore.requireField "commit" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_commit -> Eithers.bind (ExtractCore.requireField "commitMessage" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_commitMessage -> Right (Benchresult.BenchMetadata {
+          Benchresult.benchMetadataTimestamp = field_timestamp,
+          Benchresult.benchMetadataLanguage = field_language,
+          Benchresult.benchMetadataBranch = field_branch,
+          Benchresult.benchMetadataCommit = field_commit,
+          Benchresult.benchMetadataCommitMessage = field_commitMessage})))))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.benchresult.BenchMetadata")) (ExtractCore.stripWithDecodingError cx raw)
+
+-- | Decoder for hydra.build.benchresult.GenBenchResult
+genBenchResult :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Benchresult.GenBenchResult
+genBenchResult cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "target" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_target -> Eithers.bind (ExtractCore.requireField "runs" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_runs -> Eithers.bind (ExtractCore.requireField "hosts" (ExtractCore.decodeMap (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) hostResult) fieldMap cx) (\field_hosts -> Eithers.bind (ExtractCore.requireField "metadata" (ExtractCore.decodeMaybe benchMetadata) fieldMap cx) (\field_metadata -> Right (Benchresult.GenBenchResult {
+          Benchresult.genBenchResultTarget = field_target,
+          Benchresult.genBenchResultRuns = field_runs,
+          Benchresult.genBenchResultHosts = field_hosts,
+          Benchresult.genBenchResultMetadata = field_metadata}))))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.benchresult.GenBenchResult")) (ExtractCore.stripWithDecodingError cx raw)
+
+-- | Decoder for hydra.build.benchresult.HostResult
+hostResult :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Benchresult.HostResult
+hostResult cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "setupMs" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_setupMs -> Eithers.bind (ExtractCore.requireField "packages" (ExtractCore.decodeMap (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) runStats) fieldMap cx) (\field_packages -> Right (Benchresult.HostResult {
+          Benchresult.hostResultSetupMs = field_setupMs,
+          Benchresult.hostResultPackages = field_packages}))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.benchresult.HostResult")) (ExtractCore.stripWithDecodingError cx raw)
+
+-- | Decoder for hydra.build.benchresult.RunStats
+runStats :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Benchresult.RunStats
+runStats cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "runsMs" (ExtractCore.decodeList (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2))) fieldMap cx) (\field_runsMs -> Eithers.bind (ExtractCore.requireField "medianMs" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_medianMs -> Right (Benchresult.RunStats {
+          Benchresult.runStatsRunsMs = field_runsMs,
+          Benchresult.runStatsMedianMs = field_medianMs}))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.benchresult.RunStats")) (ExtractCore.stripWithDecodingError cx raw)
diff --git a/src/main/haskell/Hydra/Decode/Build/Comparereport.hs b/src/main/haskell/Hydra/Decode/Build/Comparereport.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Decode/Build/Comparereport.hs
@@ -0,0 +1,101 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Term decoders for hydra.build.comparereport
+
+module Hydra.Decode.Build.Comparereport where
+
+import qualified Hydra.Build.Comparereport as Comparereport
+import qualified Hydra.Core as Core
+import qualified Hydra.Errors as Errors
+import qualified Hydra.Extract.Core as ExtractCore
+import qualified Hydra.Graph as Graph
+import qualified Hydra.Lexical as Lexical
+import qualified Hydra.Overlay.Haskell.Lib.Eithers as Eithers
+import qualified Hydra.Overlay.Haskell.Lib.Maps as Maps
+import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
+import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
+import qualified Hydra.Rewriting as Rewriting
+import qualified Hydra.Util as Util
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | Decoder for hydra.build.comparereport.CompareReport
+compareReport :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Comparereport.CompareReport
+compareReport cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "rows" (ExtractCore.decodeList moduleCompare) fieldMap cx) (\field_rows -> Eithers.bind (ExtractCore.requireField "byteEqCount" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_byteEqCount -> Eithers.bind (ExtractCore.requireField "total" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_total -> Right (Comparereport.CompareReport {
+          Comparereport.compareReportRows = field_rows,
+          Comparereport.compareReportByteEqCount = field_byteEqCount,
+          Comparereport.compareReportTotal = field_total})))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.comparereport.CompareReport")) (ExtractCore.stripWithDecodingError cx raw)
+
+-- | Decoder for hydra.build.comparereport.CompareStatus
+compareStatus :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Comparereport.CompareStatus
+compareStatus cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermInject v0 ->
+        let field = Core.injectionField v0
+            fname = Core.fieldName field
+            fterm = Core.fieldTerm field
+            variantMap =
+                    Maps.fromList [
+                      (Core.Name "byteEq", (\input -> Eithers.map (\t -> Comparereport.CompareStatusByteEq) (ExtractCore.decodeUnit cx input))),
+                      (Core.Name "differ", (\input -> Eithers.map (\t -> Comparereport.CompareStatusDiffer) (ExtractCore.decodeUnit cx input))),
+                      (
+                        Core.Name "missing",
+                        (\input -> Eithers.map (\t -> Comparereport.CompareStatusMissing) (ExtractCore.decodeUnit cx input)))]
+        in (Optionals.match (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
+          "no such field ",
+          (Core.unName fname),
+          " in union"]))) (\f -> f fterm))
+      _ -> Left (Errors.DecodingError "expected union")) (ExtractCore.stripWithDecodingError cx raw)
+
+-- | Decoder for hydra.build.comparereport.ModuleCompare
+moduleCompare :: Graph.Graph -> Core.Term -> Either Errors.DecodingError Comparereport.ModuleCompare
+moduleCompare cx raw =
+    Eithers.either (\err -> Left err) (\stripped -> case stripped of
+      Core.TermRecord v0 ->
+        let fieldMap = ExtractCore.toFieldMap v0
+        in (Eithers.bind (ExtractCore.requireField "module" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralString v2 -> Right v2
+            _ -> Left (Errors.DecodingError "expected string literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_module -> Eithers.bind (ExtractCore.requireField "status" compareStatus fieldMap cx) (\field_status -> Eithers.bind (ExtractCore.requireField "ourSize" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_ourSize -> Eithers.bind (ExtractCore.requireField "canonSize" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_canonSize -> Eithers.bind (ExtractCore.requireField "diffLines" (\cx2 -> \raw2 -> Eithers.either (\err -> Left err) (\stripped2 -> case stripped2 of
+          Core.TermLiteral v1 -> case v1 of
+            Core.LiteralInteger v2 -> case v2 of
+              Core.IntegerValueInt32 v3 -> Right v3
+              _ -> Left (Errors.DecodingError "expected int32 value")
+            _ -> Left (Errors.DecodingError "expected int32 literal")
+          _ -> Left (Errors.DecodingError "expected literal")) (ExtractCore.stripWithDecodingError cx2 raw2)) fieldMap cx) (\field_diffLines -> Right (Comparereport.ModuleCompare {
+          Comparereport.moduleCompareModule = field_module,
+          Comparereport.moduleCompareStatus = field_status,
+          Comparereport.moduleCompareOurSize = field_ourSize,
+          Comparereport.moduleCompareCanonSize = field_canonSize,
+          Comparereport.moduleCompareDiffLines = field_diffLines})))))))
+      _ -> Left (Errors.DecodingError "expected a record of type hydra.build.comparereport.ModuleCompare")) (ExtractCore.stripWithDecodingError cx raw)
diff --git a/src/main/haskell/Hydra/Decode/Build/Format.hs b/src/main/haskell/Hydra/Decode/Build/Format.hs
--- a/src/main/haskell/Hydra/Decode/Build/Format.hs
+++ b/src/main/haskell/Hydra/Decode/Build/Format.hs
@@ -17,7 +17,7 @@
 import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
 import qualified Hydra.Rewriting as Rewriting
 import qualified Hydra.Util as Util
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 
 -- | Decoder for hydra.build.format.DefinitionNameConventionProfile
@@ -75,7 +75,7 @@
                       (Core.Name "targetFile", (\input -> Eithers.map (\t -> Format.DigestKindTargetFile) (ExtractCore.decodeUnit cx input))),
                       (Core.Name "runtimeFile", (\input -> Eithers.map (\t -> Format.DigestKindRuntimeFile) (ExtractCore.decodeUnit cx input))),
                       (Core.Name "other", (\input -> Eithers.map (\t -> Format.DigestKindOther) (ExtractCore.decodeUnit cx input)))]
-        in (Optionals.cases (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
+        in (Optionals.match (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
           "no such field ",
           (Core.unName fname),
           " in union"]))) (\f -> f fterm))
@@ -135,7 +135,7 @@
                     Maps.fromList [
                       (Core.Name "published", (\input -> Eithers.map (\t -> Format.GenerationModePublished) (ExtractCore.decodeUnit cx input))),
                       (Core.Name "shim", (\input -> Eithers.map (\t -> Format.GenerationModeShim) (ExtractCore.decodeUnit cx input)))]
-        in (Optionals.cases (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
+        in (Optionals.match (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
           "no such field ",
           (Core.unName fname),
           " in union"]))) (\f -> f fterm))
@@ -153,7 +153,7 @@
                     Maps.fromList [
                       (Core.Name "local", (\input -> Eithers.map (\t -> Format.HostOverrideLocal) (ExtractCore.decodeUnit cx input))),
                       (Core.Name "version", (\input -> Eithers.map (\t -> Format.HostOverrideVersion t) (Packaging.version cx input)))]
-        in (Optionals.cases (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
+        in (Optionals.match (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
           "no such field ",
           (Core.unName fname),
           " in union"]))) (\f -> f fterm))
@@ -373,7 +373,7 @@
                     Maps.fromList [
                       (Core.Name "error", (\input -> Eithers.map (\t -> Format.SeverityError) (ExtractCore.decodeUnit cx input))),
                       (Core.Name "warning", (\input -> Eithers.map (\t -> Format.SeverityWarning) (ExtractCore.decodeUnit cx input)))]
-        in (Optionals.cases (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
+        in (Optionals.match (Maps.lookup fname variantMap) (Left (Errors.DecodingError (Strings.concat [
           "no such field ",
           (Core.unName fname),
           " in union"]))) (\f -> f fterm))
diff --git a/src/main/haskell/Hydra/Dsl/Build/Assembly.hs b/src/main/haskell/Hydra/Dsl/Build/Assembly.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Dsl/Build/Assembly.hs
@@ -0,0 +1,374 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | DSL functions for hydra.build.assembly
+
+module Hydra.Dsl.Build.Assembly where
+
+import qualified Hydra.Build.Assembly as Assembly
+import qualified Hydra.Core as Core
+import qualified Hydra.Decode.Build.Assembly as DecodeBuildAssembly
+import qualified Hydra.Encode.Build.Assembly as EncodeBuildAssembly
+import qualified Hydra.Typed as Typed
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | DSL constructor for hydra.build.assembly.AssemblyEntry
+assemblyEntry :: Typed.TypedTerm String -> Typed.TypedTerm String -> Typed.TypedTerm Assembly.AssemblyEntryKind -> Typed.TypedTerm [String] -> Typed.TypedTerm Assembly.AssemblyEntry
+assemblyEntry sourceTree destTree kind exclude =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceTree"),
+          Core.fieldTerm = (Typed.unTypedTerm sourceTree)},
+        Core.Field {
+          Core.fieldName = (Core.Name "destTree"),
+          Core.fieldTerm = (Typed.unTypedTerm destTree)},
+        Core.Field {
+          Core.fieldName = (Core.Name "kind"),
+          Core.fieldTerm = (Typed.unTypedTerm kind)},
+        Core.Field {
+          Core.fieldName = (Core.Name "exclude"),
+          Core.fieldTerm = (Typed.unTypedTerm exclude)}]}))
+
+-- | DSL name token for hydra.build.assembly.AssemblyEntry
+assemblyEntryAssemblyEntry :: Typed.TypedName Assembly.AssemblyEntry
+assemblyEntryAssemblyEntry = Typed.TypedName (Core.Name "hydra.build.assembly.AssemblyEntry")
+
+-- | DSL accessor for the destTree field of hydra.build.assembly.AssemblyEntry
+assemblyEntryDestTree :: Typed.TypedTerm Assembly.AssemblyEntry -> Typed.TypedTerm String
+assemblyEntryDestTree x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+        Core.projectionFieldName = (Core.Name "destTree")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the exclude field of hydra.build.assembly.AssemblyEntry
+assemblyEntryExclude :: Typed.TypedTerm Assembly.AssemblyEntry -> Typed.TypedTerm [String]
+assemblyEntryExclude x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+        Core.projectionFieldName = (Core.Name "exclude")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the kind field of hydra.build.assembly.AssemblyEntry
+assemblyEntryKind :: Typed.TypedTerm Assembly.AssemblyEntry -> Typed.TypedTerm Assembly.AssemblyEntryKind
+assemblyEntryKind x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+        Core.projectionFieldName = (Core.Name "kind")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL name token for hydra.build.assembly.AssemblyEntryKind
+assemblyEntryKindAssemblyEntryKind :: Typed.TypedName Assembly.AssemblyEntryKind
+assemblyEntryKindAssemblyEntryKind = Typed.TypedName (Core.Name "hydra.build.assembly.AssemblyEntryKind")
+
+-- | DSL injection for the merge variant of hydra.build.assembly.AssemblyEntryKind
+assemblyEntryKindMerge :: Typed.TypedTerm Assembly.AssemblyEntryKind
+assemblyEntryKindMerge =
+    Typed.TypedTerm (Core.TermInject (Core.Injection {
+      Core.injectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntryKind"),
+      Core.injectionField = Core.Field {
+        Core.fieldName = (Core.Name "merge"),
+        Core.fieldTerm = Core.TermUnit}}))
+
+-- | DSL injection for the symlinkDir variant of hydra.build.assembly.AssemblyEntryKind
+assemblyEntryKindSymlinkDir :: Typed.TypedTerm Assembly.AssemblyEntryKind
+assemblyEntryKindSymlinkDir =
+    Typed.TypedTerm (Core.TermInject (Core.Injection {
+      Core.injectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntryKind"),
+      Core.injectionField = Core.Field {
+        Core.fieldName = (Core.Name "symlinkDir"),
+        Core.fieldTerm = Core.TermUnit}}))
+
+-- | DSL injection for the symlinkTree variant of hydra.build.assembly.AssemblyEntryKind
+assemblyEntryKindSymlinkTree :: Typed.TypedTerm Assembly.AssemblyEntryKind
+assemblyEntryKindSymlinkTree =
+    Typed.TypedTerm (Core.TermInject (Core.Injection {
+      Core.injectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntryKind"),
+      Core.injectionField = Core.Field {
+        Core.fieldName = (Core.Name "symlinkTree"),
+        Core.fieldTerm = Core.TermUnit}}))
+
+-- | DSL injection for the wipeThenCopy variant of hydra.build.assembly.AssemblyEntryKind
+assemblyEntryKindWipeThenCopy :: Typed.TypedTerm Assembly.AssemblyEntryKind
+assemblyEntryKindWipeThenCopy =
+    Typed.TypedTerm (Core.TermInject (Core.Injection {
+      Core.injectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntryKind"),
+      Core.injectionField = Core.Field {
+        Core.fieldName = (Core.Name "wipeThenCopy"),
+        Core.fieldTerm = Core.TermUnit}}))
+
+-- | DSL accessor for the sourceTree field of hydra.build.assembly.AssemblyEntry
+assemblyEntrySourceTree :: Typed.TypedTerm Assembly.AssemblyEntry -> Typed.TypedTerm String
+assemblyEntrySourceTree x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+        Core.projectionFieldName = (Core.Name "sourceTree")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the destTree field of hydra.build.assembly.AssemblyEntry
+assemblyEntryWithDestTree :: Typed.TypedTerm Assembly.AssemblyEntry -> Typed.TypedTerm String -> Typed.TypedTerm Assembly.AssemblyEntry
+assemblyEntryWithDestTree original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceTree"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "sourceTree")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "destTree"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "kind"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "kind")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "exclude"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "exclude")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the exclude field of hydra.build.assembly.AssemblyEntry
+assemblyEntryWithExclude :: Typed.TypedTerm Assembly.AssemblyEntry -> Typed.TypedTerm [String] -> Typed.TypedTerm Assembly.AssemblyEntry
+assemblyEntryWithExclude original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceTree"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "sourceTree")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "destTree"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "destTree")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "kind"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "kind")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "exclude"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL updater for the kind field of hydra.build.assembly.AssemblyEntry
+assemblyEntryWithKind :: Typed.TypedTerm Assembly.AssemblyEntry -> Typed.TypedTerm Assembly.AssemblyEntryKind -> Typed.TypedTerm Assembly.AssemblyEntry
+assemblyEntryWithKind original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceTree"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "sourceTree")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "destTree"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "destTree")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "kind"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "exclude"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "exclude")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the sourceTree field of hydra.build.assembly.AssemblyEntry
+assemblyEntryWithSourceTree :: Typed.TypedTerm Assembly.AssemblyEntry -> Typed.TypedTerm String -> Typed.TypedTerm Assembly.AssemblyEntry
+assemblyEntryWithSourceTree original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceTree"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "destTree"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "destTree")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "kind"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "kind")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "exclude"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+              Core.projectionFieldName = (Core.Name "exclude")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL constructor for hydra.build.assembly.AssemblyPlan
+assemblyPlan :: Typed.TypedTerm [Assembly.AssemblyEntry] -> Typed.TypedTerm [Assembly.KeepPathEntry] -> Typed.TypedTerm Assembly.AssemblyPlan
+assemblyPlan entries keepPaths =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyPlan"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "entries"),
+          Core.fieldTerm = (Typed.unTypedTerm entries)},
+        Core.Field {
+          Core.fieldName = (Core.Name "keepPaths"),
+          Core.fieldTerm = (Typed.unTypedTerm keepPaths)}]}))
+
+-- | DSL name token for hydra.build.assembly.AssemblyPlan
+assemblyPlanAssemblyPlan :: Typed.TypedName Assembly.AssemblyPlan
+assemblyPlanAssemblyPlan = Typed.TypedName (Core.Name "hydra.build.assembly.AssemblyPlan")
+
+-- | DSL accessor for the entries field of hydra.build.assembly.AssemblyPlan
+assemblyPlanEntries :: Typed.TypedTerm Assembly.AssemblyPlan -> Typed.TypedTerm [Assembly.AssemblyEntry]
+assemblyPlanEntries x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyPlan"),
+        Core.projectionFieldName = (Core.Name "entries")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the keepPaths field of hydra.build.assembly.AssemblyPlan
+assemblyPlanKeepPaths :: Typed.TypedTerm Assembly.AssemblyPlan -> Typed.TypedTerm [Assembly.KeepPathEntry]
+assemblyPlanKeepPaths x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyPlan"),
+        Core.projectionFieldName = (Core.Name "keepPaths")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the entries field of hydra.build.assembly.AssemblyPlan
+assemblyPlanWithEntries :: Typed.TypedTerm Assembly.AssemblyPlan -> Typed.TypedTerm [Assembly.AssemblyEntry] -> Typed.TypedTerm Assembly.AssemblyPlan
+assemblyPlanWithEntries original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyPlan"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "entries"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "keepPaths"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyPlan"),
+              Core.projectionFieldName = (Core.Name "keepPaths")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the keepPaths field of hydra.build.assembly.AssemblyPlan
+assemblyPlanWithKeepPaths :: Typed.TypedTerm Assembly.AssemblyPlan -> Typed.TypedTerm [Assembly.KeepPathEntry] -> Typed.TypedTerm Assembly.AssemblyPlan
+assemblyPlanWithKeepPaths original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyPlan"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "entries"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.AssemblyPlan"),
+              Core.projectionFieldName = (Core.Name "entries")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "keepPaths"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL constructor for hydra.build.assembly.KeepPathEntry
+keepPathEntry :: Typed.TypedTerm String -> Typed.TypedTerm String -> Typed.TypedTerm Assembly.KeepPathEntry
+keepPathEntry sourceSetDir relPath =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.KeepPathEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceSetDir"),
+          Core.fieldTerm = (Typed.unTypedTerm sourceSetDir)},
+        Core.Field {
+          Core.fieldName = (Core.Name "relPath"),
+          Core.fieldTerm = (Typed.unTypedTerm relPath)}]}))
+
+-- | DSL name token for hydra.build.assembly.KeepPathEntry
+keepPathEntryKeepPathEntry :: Typed.TypedName Assembly.KeepPathEntry
+keepPathEntryKeepPathEntry = Typed.TypedName (Core.Name "hydra.build.assembly.KeepPathEntry")
+
+-- | DSL accessor for the relPath field of hydra.build.assembly.KeepPathEntry
+keepPathEntryRelPath :: Typed.TypedTerm Assembly.KeepPathEntry -> Typed.TypedTerm String
+keepPathEntryRelPath x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.assembly.KeepPathEntry"),
+        Core.projectionFieldName = (Core.Name "relPath")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the sourceSetDir field of hydra.build.assembly.KeepPathEntry
+keepPathEntrySourceSetDir :: Typed.TypedTerm Assembly.KeepPathEntry -> Typed.TypedTerm String
+keepPathEntrySourceSetDir x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.assembly.KeepPathEntry"),
+        Core.projectionFieldName = (Core.Name "sourceSetDir")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the relPath field of hydra.build.assembly.KeepPathEntry
+keepPathEntryWithRelPath :: Typed.TypedTerm Assembly.KeepPathEntry -> Typed.TypedTerm String -> Typed.TypedTerm Assembly.KeepPathEntry
+keepPathEntryWithRelPath original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.KeepPathEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceSetDir"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.KeepPathEntry"),
+              Core.projectionFieldName = (Core.Name "sourceSetDir")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "relPath"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL updater for the sourceSetDir field of hydra.build.assembly.KeepPathEntry
+keepPathEntryWithSourceSetDir :: Typed.TypedTerm Assembly.KeepPathEntry -> Typed.TypedTerm String -> Typed.TypedTerm Assembly.KeepPathEntry
+keepPathEntryWithSourceSetDir original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.KeepPathEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceSetDir"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "relPath"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.assembly.KeepPathEntry"),
+              Core.projectionFieldName = (Core.Name "relPath")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
diff --git a/src/main/haskell/Hydra/Dsl/Build/Benchresult.hs b/src/main/haskell/Hydra/Dsl/Build/Benchresult.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Dsl/Build/Benchresult.hs
@@ -0,0 +1,596 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | DSL functions for hydra.build.benchresult
+
+module Hydra.Dsl.Build.Benchresult where
+
+import qualified Hydra.Build.Benchresult as Benchresult
+import qualified Hydra.Core as Core
+import qualified Hydra.Decode.Build.Benchresult as DecodeBuildBenchresult
+import qualified Hydra.Encode.Build.Benchresult as EncodeBuildBenchresult
+import qualified Hydra.Typed as Typed
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+import qualified Data.Map as M
+
+-- | DSL constructor for hydra.build.benchresult.BenchMetadata
+benchMetadata :: Typed.TypedTerm String -> Typed.TypedTerm String -> Typed.TypedTerm String -> Typed.TypedTerm String -> Typed.TypedTerm String -> Typed.TypedTerm Benchresult.BenchMetadata
+benchMetadata timestamp language branch commit commitMessage =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "timestamp"),
+          Core.fieldTerm = (Typed.unTypedTerm timestamp)},
+        Core.Field {
+          Core.fieldName = (Core.Name "language"),
+          Core.fieldTerm = (Typed.unTypedTerm language)},
+        Core.Field {
+          Core.fieldName = (Core.Name "branch"),
+          Core.fieldTerm = (Typed.unTypedTerm branch)},
+        Core.Field {
+          Core.fieldName = (Core.Name "commit"),
+          Core.fieldTerm = (Typed.unTypedTerm commit)},
+        Core.Field {
+          Core.fieldName = (Core.Name "commitMessage"),
+          Core.fieldTerm = (Typed.unTypedTerm commitMessage)}]}))
+
+-- | DSL name token for hydra.build.benchresult.BenchMetadata
+benchMetadataBenchMetadata :: Typed.TypedName Benchresult.BenchMetadata
+benchMetadataBenchMetadata = Typed.TypedName (Core.Name "hydra.build.benchresult.BenchMetadata")
+
+-- | DSL accessor for the branch field of hydra.build.benchresult.BenchMetadata
+benchMetadataBranch :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String
+benchMetadataBranch x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+        Core.projectionFieldName = (Core.Name "branch")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the commit field of hydra.build.benchresult.BenchMetadata
+benchMetadataCommit :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String
+benchMetadataCommit x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+        Core.projectionFieldName = (Core.Name "commit")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the commitMessage field of hydra.build.benchresult.BenchMetadata
+benchMetadataCommitMessage :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String
+benchMetadataCommitMessage x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+        Core.projectionFieldName = (Core.Name "commitMessage")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the language field of hydra.build.benchresult.BenchMetadata
+benchMetadataLanguage :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String
+benchMetadataLanguage x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+        Core.projectionFieldName = (Core.Name "language")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the timestamp field of hydra.build.benchresult.BenchMetadata
+benchMetadataTimestamp :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String
+benchMetadataTimestamp x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+        Core.projectionFieldName = (Core.Name "timestamp")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the branch field of hydra.build.benchresult.BenchMetadata
+benchMetadataWithBranch :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String -> Typed.TypedTerm Benchresult.BenchMetadata
+benchMetadataWithBranch original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "timestamp"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "timestamp")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "language"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "language")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "branch"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "commit"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "commit")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commitMessage"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "commitMessage")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the commit field of hydra.build.benchresult.BenchMetadata
+benchMetadataWithCommit :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String -> Typed.TypedTerm Benchresult.BenchMetadata
+benchMetadataWithCommit original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "timestamp"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "timestamp")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "language"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "language")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "branch"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "branch")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commit"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "commitMessage"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "commitMessage")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the commitMessage field of hydra.build.benchresult.BenchMetadata
+benchMetadataWithCommitMessage :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String -> Typed.TypedTerm Benchresult.BenchMetadata
+benchMetadataWithCommitMessage original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "timestamp"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "timestamp")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "language"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "language")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "branch"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "branch")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commit"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "commit")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commitMessage"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL updater for the language field of hydra.build.benchresult.BenchMetadata
+benchMetadataWithLanguage :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String -> Typed.TypedTerm Benchresult.BenchMetadata
+benchMetadataWithLanguage original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "timestamp"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "timestamp")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "language"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "branch"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "branch")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commit"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "commit")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commitMessage"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "commitMessage")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the timestamp field of hydra.build.benchresult.BenchMetadata
+benchMetadataWithTimestamp :: Typed.TypedTerm Benchresult.BenchMetadata -> Typed.TypedTerm String -> Typed.TypedTerm Benchresult.BenchMetadata
+benchMetadataWithTimestamp original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "timestamp"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "language"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "language")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "branch"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "branch")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commit"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "commit")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commitMessage"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+              Core.projectionFieldName = (Core.Name "commitMessage")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL constructor for hydra.build.benchresult.GenBenchResult
+genBenchResult :: Typed.TypedTerm String -> Typed.TypedTerm Int -> Typed.TypedTerm (M.Map String Benchresult.HostResult) -> Typed.TypedTerm (Maybe Benchresult.BenchMetadata) -> Typed.TypedTerm Benchresult.GenBenchResult
+genBenchResult target runs hosts metadata =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "target"),
+          Core.fieldTerm = (Typed.unTypedTerm target)},
+        Core.Field {
+          Core.fieldName = (Core.Name "runs"),
+          Core.fieldTerm = (Typed.unTypedTerm runs)},
+        Core.Field {
+          Core.fieldName = (Core.Name "hosts"),
+          Core.fieldTerm = (Typed.unTypedTerm hosts)},
+        Core.Field {
+          Core.fieldName = (Core.Name "metadata"),
+          Core.fieldTerm = (Typed.unTypedTerm metadata)}]}))
+
+-- | DSL name token for hydra.build.benchresult.GenBenchResult
+genBenchResultGenBenchResult :: Typed.TypedName Benchresult.GenBenchResult
+genBenchResultGenBenchResult = Typed.TypedName (Core.Name "hydra.build.benchresult.GenBenchResult")
+
+-- | DSL accessor for the hosts field of hydra.build.benchresult.GenBenchResult
+genBenchResultHosts :: Typed.TypedTerm Benchresult.GenBenchResult -> Typed.TypedTerm (M.Map String Benchresult.HostResult)
+genBenchResultHosts x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+        Core.projectionFieldName = (Core.Name "hosts")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the metadata field of hydra.build.benchresult.GenBenchResult
+genBenchResultMetadata :: Typed.TypedTerm Benchresult.GenBenchResult -> Typed.TypedTerm (Maybe Benchresult.BenchMetadata)
+genBenchResultMetadata x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+        Core.projectionFieldName = (Core.Name "metadata")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the runs field of hydra.build.benchresult.GenBenchResult
+genBenchResultRuns :: Typed.TypedTerm Benchresult.GenBenchResult -> Typed.TypedTerm Int
+genBenchResultRuns x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+        Core.projectionFieldName = (Core.Name "runs")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the target field of hydra.build.benchresult.GenBenchResult
+genBenchResultTarget :: Typed.TypedTerm Benchresult.GenBenchResult -> Typed.TypedTerm String
+genBenchResultTarget x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+        Core.projectionFieldName = (Core.Name "target")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the hosts field of hydra.build.benchresult.GenBenchResult
+genBenchResultWithHosts :: Typed.TypedTerm Benchresult.GenBenchResult -> Typed.TypedTerm (M.Map String Benchresult.HostResult) -> Typed.TypedTerm Benchresult.GenBenchResult
+genBenchResultWithHosts original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "target"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "target")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "runs"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "runs")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "hosts"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "metadata"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "metadata")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the metadata field of hydra.build.benchresult.GenBenchResult
+genBenchResultWithMetadata :: Typed.TypedTerm Benchresult.GenBenchResult -> Typed.TypedTerm (Maybe Benchresult.BenchMetadata) -> Typed.TypedTerm Benchresult.GenBenchResult
+genBenchResultWithMetadata original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "target"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "target")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "runs"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "runs")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "hosts"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "hosts")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "metadata"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL updater for the runs field of hydra.build.benchresult.GenBenchResult
+genBenchResultWithRuns :: Typed.TypedTerm Benchresult.GenBenchResult -> Typed.TypedTerm Int -> Typed.TypedTerm Benchresult.GenBenchResult
+genBenchResultWithRuns original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "target"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "target")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "runs"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "hosts"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "hosts")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "metadata"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "metadata")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the target field of hydra.build.benchresult.GenBenchResult
+genBenchResultWithTarget :: Typed.TypedTerm Benchresult.GenBenchResult -> Typed.TypedTerm String -> Typed.TypedTerm Benchresult.GenBenchResult
+genBenchResultWithTarget original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "target"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "runs"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "runs")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "hosts"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "hosts")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "metadata"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+              Core.projectionFieldName = (Core.Name "metadata")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL constructor for hydra.build.benchresult.HostResult
+hostResult :: Typed.TypedTerm Int -> Typed.TypedTerm (M.Map String Benchresult.RunStats) -> Typed.TypedTerm Benchresult.HostResult
+hostResult setupMs packages =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.HostResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "setupMs"),
+          Core.fieldTerm = (Typed.unTypedTerm setupMs)},
+        Core.Field {
+          Core.fieldName = (Core.Name "packages"),
+          Core.fieldTerm = (Typed.unTypedTerm packages)}]}))
+
+-- | DSL name token for hydra.build.benchresult.HostResult
+hostResultHostResult :: Typed.TypedName Benchresult.HostResult
+hostResultHostResult = Typed.TypedName (Core.Name "hydra.build.benchresult.HostResult")
+
+-- | DSL accessor for the packages field of hydra.build.benchresult.HostResult
+hostResultPackages :: Typed.TypedTerm Benchresult.HostResult -> Typed.TypedTerm (M.Map String Benchresult.RunStats)
+hostResultPackages x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.HostResult"),
+        Core.projectionFieldName = (Core.Name "packages")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the setupMs field of hydra.build.benchresult.HostResult
+hostResultSetupMs :: Typed.TypedTerm Benchresult.HostResult -> Typed.TypedTerm Int
+hostResultSetupMs x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.HostResult"),
+        Core.projectionFieldName = (Core.Name "setupMs")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the packages field of hydra.build.benchresult.HostResult
+hostResultWithPackages :: Typed.TypedTerm Benchresult.HostResult -> Typed.TypedTerm (M.Map String Benchresult.RunStats) -> Typed.TypedTerm Benchresult.HostResult
+hostResultWithPackages original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.HostResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "setupMs"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.HostResult"),
+              Core.projectionFieldName = (Core.Name "setupMs")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "packages"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL updater for the setupMs field of hydra.build.benchresult.HostResult
+hostResultWithSetupMs :: Typed.TypedTerm Benchresult.HostResult -> Typed.TypedTerm Int -> Typed.TypedTerm Benchresult.HostResult
+hostResultWithSetupMs original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.HostResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "setupMs"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "packages"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.HostResult"),
+              Core.projectionFieldName = (Core.Name "packages")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL constructor for hydra.build.benchresult.RunStats
+runStats :: Typed.TypedTerm [Int] -> Typed.TypedTerm Int -> Typed.TypedTerm Benchresult.RunStats
+runStats runsMs medianMs =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.RunStats"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "runsMs"),
+          Core.fieldTerm = (Typed.unTypedTerm runsMs)},
+        Core.Field {
+          Core.fieldName = (Core.Name "medianMs"),
+          Core.fieldTerm = (Typed.unTypedTerm medianMs)}]}))
+
+-- | DSL accessor for the medianMs field of hydra.build.benchresult.RunStats
+runStatsMedianMs :: Typed.TypedTerm Benchresult.RunStats -> Typed.TypedTerm Int
+runStatsMedianMs x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.RunStats"),
+        Core.projectionFieldName = (Core.Name "medianMs")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL name token for hydra.build.benchresult.RunStats
+runStatsRunStats :: Typed.TypedName Benchresult.RunStats
+runStatsRunStats = Typed.TypedName (Core.Name "hydra.build.benchresult.RunStats")
+
+-- | DSL accessor for the runsMs field of hydra.build.benchresult.RunStats
+runStatsRunsMs :: Typed.TypedTerm Benchresult.RunStats -> Typed.TypedTerm [Int]
+runStatsRunsMs x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.benchresult.RunStats"),
+        Core.projectionFieldName = (Core.Name "runsMs")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the medianMs field of hydra.build.benchresult.RunStats
+runStatsWithMedianMs :: Typed.TypedTerm Benchresult.RunStats -> Typed.TypedTerm Int -> Typed.TypedTerm Benchresult.RunStats
+runStatsWithMedianMs original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.RunStats"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "runsMs"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.RunStats"),
+              Core.projectionFieldName = (Core.Name "runsMs")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "medianMs"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL updater for the runsMs field of hydra.build.benchresult.RunStats
+runStatsWithRunsMs :: Typed.TypedTerm Benchresult.RunStats -> Typed.TypedTerm [Int] -> Typed.TypedTerm Benchresult.RunStats
+runStatsWithRunsMs original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.RunStats"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "runsMs"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "medianMs"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.benchresult.RunStats"),
+              Core.projectionFieldName = (Core.Name "medianMs")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
diff --git a/src/main/haskell/Hydra/Dsl/Build/Comparereport.hs b/src/main/haskell/Hydra/Dsl/Build/Comparereport.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Dsl/Build/Comparereport.hs
@@ -0,0 +1,424 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | DSL functions for hydra.build.comparereport
+
+module Hydra.Dsl.Build.Comparereport where
+
+import qualified Hydra.Build.Comparereport as Comparereport
+import qualified Hydra.Core as Core
+import qualified Hydra.Decode.Build.Comparereport as DecodeBuildComparereport
+import qualified Hydra.Encode.Build.Comparereport as EncodeBuildComparereport
+import qualified Hydra.Typed as Typed
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | DSL constructor for hydra.build.comparereport.CompareReport
+compareReport :: Typed.TypedTerm [Comparereport.ModuleCompare] -> Typed.TypedTerm Int -> Typed.TypedTerm Int -> Typed.TypedTerm Comparereport.CompareReport
+compareReport rows byteEqCount total =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "rows"),
+          Core.fieldTerm = (Typed.unTypedTerm rows)},
+        Core.Field {
+          Core.fieldName = (Core.Name "byteEqCount"),
+          Core.fieldTerm = (Typed.unTypedTerm byteEqCount)},
+        Core.Field {
+          Core.fieldName = (Core.Name "total"),
+          Core.fieldTerm = (Typed.unTypedTerm total)}]}))
+
+-- | DSL accessor for the byteEqCount field of hydra.build.comparereport.CompareReport
+compareReportByteEqCount :: Typed.TypedTerm Comparereport.CompareReport -> Typed.TypedTerm Int
+compareReportByteEqCount x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+        Core.projectionFieldName = (Core.Name "byteEqCount")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL name token for hydra.build.comparereport.CompareReport
+compareReportCompareReport :: Typed.TypedName Comparereport.CompareReport
+compareReportCompareReport = Typed.TypedName (Core.Name "hydra.build.comparereport.CompareReport")
+
+-- | DSL accessor for the rows field of hydra.build.comparereport.CompareReport
+compareReportRows :: Typed.TypedTerm Comparereport.CompareReport -> Typed.TypedTerm [Comparereport.ModuleCompare]
+compareReportRows x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+        Core.projectionFieldName = (Core.Name "rows")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the total field of hydra.build.comparereport.CompareReport
+compareReportTotal :: Typed.TypedTerm Comparereport.CompareReport -> Typed.TypedTerm Int
+compareReportTotal x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+        Core.projectionFieldName = (Core.Name "total")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the byteEqCount field of hydra.build.comparereport.CompareReport
+compareReportWithByteEqCount :: Typed.TypedTerm Comparereport.CompareReport -> Typed.TypedTerm Int -> Typed.TypedTerm Comparereport.CompareReport
+compareReportWithByteEqCount original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "rows"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+              Core.projectionFieldName = (Core.Name "rows")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "byteEqCount"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "total"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+              Core.projectionFieldName = (Core.Name "total")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the rows field of hydra.build.comparereport.CompareReport
+compareReportWithRows :: Typed.TypedTerm Comparereport.CompareReport -> Typed.TypedTerm [Comparereport.ModuleCompare] -> Typed.TypedTerm Comparereport.CompareReport
+compareReportWithRows original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "rows"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "byteEqCount"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+              Core.projectionFieldName = (Core.Name "byteEqCount")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "total"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+              Core.projectionFieldName = (Core.Name "total")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the total field of hydra.build.comparereport.CompareReport
+compareReportWithTotal :: Typed.TypedTerm Comparereport.CompareReport -> Typed.TypedTerm Int -> Typed.TypedTerm Comparereport.CompareReport
+compareReportWithTotal original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "rows"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+              Core.projectionFieldName = (Core.Name "rows")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "byteEqCount"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+              Core.projectionFieldName = (Core.Name "byteEqCount")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "total"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL injection for the byteEq variant of hydra.build.comparereport.CompareStatus
+compareStatusByteEq :: Typed.TypedTerm Comparereport.CompareStatus
+compareStatusByteEq =
+    Typed.TypedTerm (Core.TermInject (Core.Injection {
+      Core.injectionTypeName = (Core.Name "hydra.build.comparereport.CompareStatus"),
+      Core.injectionField = Core.Field {
+        Core.fieldName = (Core.Name "byteEq"),
+        Core.fieldTerm = Core.TermUnit}}))
+
+-- | DSL name token for hydra.build.comparereport.CompareStatus
+compareStatusCompareStatus :: Typed.TypedName Comparereport.CompareStatus
+compareStatusCompareStatus = Typed.TypedName (Core.Name "hydra.build.comparereport.CompareStatus")
+
+-- | DSL injection for the differ variant of hydra.build.comparereport.CompareStatus
+compareStatusDiffer :: Typed.TypedTerm Comparereport.CompareStatus
+compareStatusDiffer =
+    Typed.TypedTerm (Core.TermInject (Core.Injection {
+      Core.injectionTypeName = (Core.Name "hydra.build.comparereport.CompareStatus"),
+      Core.injectionField = Core.Field {
+        Core.fieldName = (Core.Name "differ"),
+        Core.fieldTerm = Core.TermUnit}}))
+
+-- | DSL injection for the missing variant of hydra.build.comparereport.CompareStatus
+compareStatusMissing :: Typed.TypedTerm Comparereport.CompareStatus
+compareStatusMissing =
+    Typed.TypedTerm (Core.TermInject (Core.Injection {
+      Core.injectionTypeName = (Core.Name "hydra.build.comparereport.CompareStatus"),
+      Core.injectionField = Core.Field {
+        Core.fieldName = (Core.Name "missing"),
+        Core.fieldTerm = Core.TermUnit}}))
+
+-- | DSL constructor for hydra.build.comparereport.ModuleCompare
+moduleCompare :: Typed.TypedTerm String -> Typed.TypedTerm Comparereport.CompareStatus -> Typed.TypedTerm Int -> Typed.TypedTerm Int -> Typed.TypedTerm Int -> Typed.TypedTerm Comparereport.ModuleCompare
+moduleCompare module_ status ourSize canonSize diffLines =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "module"),
+          Core.fieldTerm = (Typed.unTypedTerm module_)},
+        Core.Field {
+          Core.fieldName = (Core.Name "status"),
+          Core.fieldTerm = (Typed.unTypedTerm status)},
+        Core.Field {
+          Core.fieldName = (Core.Name "ourSize"),
+          Core.fieldTerm = (Typed.unTypedTerm ourSize)},
+        Core.Field {
+          Core.fieldName = (Core.Name "canonSize"),
+          Core.fieldTerm = (Typed.unTypedTerm canonSize)},
+        Core.Field {
+          Core.fieldName = (Core.Name "diffLines"),
+          Core.fieldTerm = (Typed.unTypedTerm diffLines)}]}))
+
+-- | DSL accessor for the canonSize field of hydra.build.comparereport.ModuleCompare
+moduleCompareCanonSize :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm Int
+moduleCompareCanonSize x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+        Core.projectionFieldName = (Core.Name "canonSize")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the diffLines field of hydra.build.comparereport.ModuleCompare
+moduleCompareDiffLines :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm Int
+moduleCompareDiffLines x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+        Core.projectionFieldName = (Core.Name "diffLines")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the module field of hydra.build.comparereport.ModuleCompare
+moduleCompareModule :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm String
+moduleCompareModule x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+        Core.projectionFieldName = (Core.Name "module")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL name token for hydra.build.comparereport.ModuleCompare
+moduleCompareModuleCompare :: Typed.TypedName Comparereport.ModuleCompare
+moduleCompareModuleCompare = Typed.TypedName (Core.Name "hydra.build.comparereport.ModuleCompare")
+
+-- | DSL accessor for the ourSize field of hydra.build.comparereport.ModuleCompare
+moduleCompareOurSize :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm Int
+moduleCompareOurSize x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+        Core.projectionFieldName = (Core.Name "ourSize")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL accessor for the status field of hydra.build.comparereport.ModuleCompare
+moduleCompareStatus :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm Comparereport.CompareStatus
+moduleCompareStatus x =
+    Typed.TypedTerm (Core.TermApplication (Core.Application {
+      Core.applicationFunction = (Core.TermProject (Core.Projection {
+        Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+        Core.projectionFieldName = (Core.Name "status")})),
+      Core.applicationArgument = (Typed.unTypedTerm x)}))
+
+-- | DSL updater for the canonSize field of hydra.build.comparereport.ModuleCompare
+moduleCompareWithCanonSize :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm Int -> Typed.TypedTerm Comparereport.ModuleCompare
+moduleCompareWithCanonSize original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "module"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "module")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "status"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "status")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "ourSize"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "ourSize")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "canonSize"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "diffLines"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "diffLines")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the diffLines field of hydra.build.comparereport.ModuleCompare
+moduleCompareWithDiffLines :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm Int -> Typed.TypedTerm Comparereport.ModuleCompare
+moduleCompareWithDiffLines original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "module"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "module")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "status"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "status")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "ourSize"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "ourSize")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "canonSize"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "canonSize")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "diffLines"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))
+
+-- | DSL updater for the module field of hydra.build.comparereport.ModuleCompare
+moduleCompareWithModule :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm String -> Typed.TypedTerm Comparereport.ModuleCompare
+moduleCompareWithModule original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "module"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "status"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "status")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "ourSize"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "ourSize")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "canonSize"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "canonSize")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "diffLines"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "diffLines")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the ourSize field of hydra.build.comparereport.ModuleCompare
+moduleCompareWithOurSize :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm Int -> Typed.TypedTerm Comparereport.ModuleCompare
+moduleCompareWithOurSize original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "module"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "module")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "status"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "status")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "ourSize"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "canonSize"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "canonSize")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "diffLines"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "diffLines")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
+
+-- | DSL updater for the status field of hydra.build.comparereport.ModuleCompare
+moduleCompareWithStatus :: Typed.TypedTerm Comparereport.ModuleCompare -> Typed.TypedTerm Comparereport.CompareStatus -> Typed.TypedTerm Comparereport.ModuleCompare
+moduleCompareWithStatus original newVal =
+    Typed.TypedTerm (Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "module"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "module")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "status"),
+          Core.fieldTerm = (Typed.unTypedTerm newVal)},
+        Core.Field {
+          Core.fieldName = (Core.Name "ourSize"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "ourSize")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "canonSize"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "canonSize")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))},
+        Core.Field {
+          Core.fieldName = (Core.Name "diffLines"),
+          Core.fieldTerm = (Core.TermApplication (Core.Application {
+            Core.applicationFunction = (Core.TermProject (Core.Projection {
+              Core.projectionTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+              Core.projectionFieldName = (Core.Name "diffLines")})),
+            Core.applicationArgument = (Typed.unTypedTerm original)}))}]}))
diff --git a/src/main/haskell/Hydra/Dsl/Build/Format.hs b/src/main/haskell/Hydra/Dsl/Build/Format.hs
--- a/src/main/haskell/Hydra/Dsl/Build/Format.hs
+++ b/src/main/haskell/Hydra/Dsl/Build/Format.hs
@@ -11,7 +11,7 @@
 import qualified Hydra.Encode.Build.Format as EncodeBuildFormat
 import qualified Hydra.Packaging as Packaging
 import qualified Hydra.Typed as Typed
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 import qualified Data.Map as M
 
diff --git a/src/main/haskell/Hydra/Encode/Build/Assembly.hs b/src/main/haskell/Hydra/Encode/Build/Assembly.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Encode/Build/Assembly.hs
@@ -0,0 +1,81 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Term encoders for hydra.build.assembly
+
+module Hydra.Encode.Build.Assembly where
+
+import qualified Hydra.Build.Assembly as Assembly
+import qualified Hydra.Core as Core
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | Encoder for hydra.build.assembly.AssemblyEntry
+assemblyEntry :: Assembly.AssemblyEntry -> Core.Term
+assemblyEntry x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceTree"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Assembly.assemblyEntrySourceTree x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "destTree"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Assembly.assemblyEntryDestTree x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "kind"),
+          Core.fieldTerm = (assemblyEntryKind (Assembly.assemblyEntryKind x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "exclude"),
+          Core.fieldTerm = ((\xs -> Core.TermList (Lists.map (\x2 -> Core.TermLiteral (Core.LiteralString x2)) xs)) (Assembly.assemblyEntryExclude x))}]})
+
+-- | Encoder for hydra.build.assembly.AssemblyEntryKind
+assemblyEntryKind :: Assembly.AssemblyEntryKind -> Core.Term
+assemblyEntryKind x =
+    case x of
+      Assembly.AssemblyEntryKindMerge -> Core.TermInject (Core.Injection {
+        Core.injectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntryKind"),
+        Core.injectionField = Core.Field {
+          Core.fieldName = (Core.Name "merge"),
+          Core.fieldTerm = Core.TermUnit}})
+      Assembly.AssemblyEntryKindWipeThenCopy -> Core.TermInject (Core.Injection {
+        Core.injectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntryKind"),
+        Core.injectionField = Core.Field {
+          Core.fieldName = (Core.Name "wipeThenCopy"),
+          Core.fieldTerm = Core.TermUnit}})
+      Assembly.AssemblyEntryKindSymlinkTree -> Core.TermInject (Core.Injection {
+        Core.injectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntryKind"),
+        Core.injectionField = Core.Field {
+          Core.fieldName = (Core.Name "symlinkTree"),
+          Core.fieldTerm = Core.TermUnit}})
+      Assembly.AssemblyEntryKindSymlinkDir -> Core.TermInject (Core.Injection {
+        Core.injectionTypeName = (Core.Name "hydra.build.assembly.AssemblyEntryKind"),
+        Core.injectionField = Core.Field {
+          Core.fieldName = (Core.Name "symlinkDir"),
+          Core.fieldTerm = Core.TermUnit}})
+
+-- | Encoder for hydra.build.assembly.AssemblyPlan
+assemblyPlan :: Assembly.AssemblyPlan -> Core.Term
+assemblyPlan x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.AssemblyPlan"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "entries"),
+          Core.fieldTerm = ((\xs -> Core.TermList (Lists.map assemblyEntry xs)) (Assembly.assemblyPlanEntries x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "keepPaths"),
+          Core.fieldTerm = ((\xs -> Core.TermList (Lists.map keepPathEntry xs)) (Assembly.assemblyPlanKeepPaths x))}]})
+
+-- | Encoder for hydra.build.assembly.KeepPathEntry
+keepPathEntry :: Assembly.KeepPathEntry -> Core.Term
+keepPathEntry x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.assembly.KeepPathEntry"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "sourceSetDir"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Assembly.keepPathEntrySourceSetDir x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "relPath"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Assembly.keepPathEntryRelPath x))}]})
diff --git a/src/main/haskell/Hydra/Encode/Build/Benchresult.hs b/src/main/haskell/Hydra/Encode/Build/Benchresult.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Encode/Build/Benchresult.hs
@@ -0,0 +1,80 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Term encoders for hydra.build.benchresult
+
+module Hydra.Encode.Build.Benchresult where
+
+import qualified Hydra.Build.Benchresult as Benchresult
+import qualified Hydra.Core as Core
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import qualified Hydra.Overlay.Haskell.Lib.Maps as Maps
+import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | Encoder for hydra.build.benchresult.BenchMetadata
+benchMetadata :: Benchresult.BenchMetadata -> Core.Term
+benchMetadata x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.BenchMetadata"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "timestamp"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Benchresult.benchMetadataTimestamp x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "language"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Benchresult.benchMetadataLanguage x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "branch"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Benchresult.benchMetadataBranch x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commit"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Benchresult.benchMetadataCommit x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "commitMessage"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Benchresult.benchMetadataCommitMessage x))}]})
+
+-- | Encoder for hydra.build.benchresult.GenBenchResult
+genBenchResult :: Benchresult.GenBenchResult -> Core.Term
+genBenchResult x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.GenBenchResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "target"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Benchresult.genBenchResultTarget x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "runs"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) (Benchresult.genBenchResultRuns x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "hosts"),
+          Core.fieldTerm = ((\m -> Core.TermMap (Maps.bimap (\x2 -> Core.TermLiteral (Core.LiteralString x2)) hostResult m)) (Benchresult.genBenchResultHosts x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "metadata"),
+          Core.fieldTerm = ((\opt -> Core.TermOptional (Optionals.map benchMetadata opt)) (Benchresult.genBenchResultMetadata x))}]})
+
+-- | Encoder for hydra.build.benchresult.HostResult
+hostResult :: Benchresult.HostResult -> Core.Term
+hostResult x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.HostResult"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "setupMs"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) (Benchresult.hostResultSetupMs x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "packages"),
+          Core.fieldTerm = ((\m -> Core.TermMap (Maps.bimap (\x2 -> Core.TermLiteral (Core.LiteralString x2)) runStats m)) (Benchresult.hostResultPackages x))}]})
+
+-- | Encoder for hydra.build.benchresult.RunStats
+runStats :: Benchresult.RunStats -> Core.Term
+runStats x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.benchresult.RunStats"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "runsMs"),
+          Core.fieldTerm = ((\xs -> Core.TermList (Lists.map (\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) xs)) (Benchresult.runStatsRunsMs x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "medianMs"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) (Benchresult.runStatsMedianMs x))}]})
diff --git a/src/main/haskell/Hydra/Encode/Build/Comparereport.hs b/src/main/haskell/Hydra/Encode/Build/Comparereport.hs
new file mode 100644
--- /dev/null
+++ b/src/main/haskell/Hydra/Encode/Build/Comparereport.hs
@@ -0,0 +1,69 @@
+-- Note: this is an automatically generated file. Do not edit.
+
+-- | Term encoders for hydra.build.comparereport
+
+module Hydra.Encode.Build.Comparereport where
+
+import qualified Hydra.Build.Comparereport as Comparereport
+import qualified Hydra.Core as Core
+import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
+import qualified Data.Scientific as Sci
+
+-- | Encoder for hydra.build.comparereport.CompareReport
+compareReport :: Comparereport.CompareReport -> Core.Term
+compareReport x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.CompareReport"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "rows"),
+          Core.fieldTerm = ((\xs -> Core.TermList (Lists.map moduleCompare xs)) (Comparereport.compareReportRows x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "byteEqCount"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) (Comparereport.compareReportByteEqCount x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "total"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) (Comparereport.compareReportTotal x))}]})
+
+-- | Encoder for hydra.build.comparereport.CompareStatus
+compareStatus :: Comparereport.CompareStatus -> Core.Term
+compareStatus x =
+    case x of
+      Comparereport.CompareStatusByteEq -> Core.TermInject (Core.Injection {
+        Core.injectionTypeName = (Core.Name "hydra.build.comparereport.CompareStatus"),
+        Core.injectionField = Core.Field {
+          Core.fieldName = (Core.Name "byteEq"),
+          Core.fieldTerm = Core.TermUnit}})
+      Comparereport.CompareStatusDiffer -> Core.TermInject (Core.Injection {
+        Core.injectionTypeName = (Core.Name "hydra.build.comparereport.CompareStatus"),
+        Core.injectionField = Core.Field {
+          Core.fieldName = (Core.Name "differ"),
+          Core.fieldTerm = Core.TermUnit}})
+      Comparereport.CompareStatusMissing -> Core.TermInject (Core.Injection {
+        Core.injectionTypeName = (Core.Name "hydra.build.comparereport.CompareStatus"),
+        Core.injectionField = Core.Field {
+          Core.fieldName = (Core.Name "missing"),
+          Core.fieldTerm = Core.TermUnit}})
+
+-- | Encoder for hydra.build.comparereport.ModuleCompare
+moduleCompare :: Comparereport.ModuleCompare -> Core.Term
+moduleCompare x =
+    Core.TermRecord (Core.Record {
+      Core.recordTypeName = (Core.Name "hydra.build.comparereport.ModuleCompare"),
+      Core.recordFields = [
+        Core.Field {
+          Core.fieldName = (Core.Name "module"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralString x2)) (Comparereport.moduleCompareModule x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "status"),
+          Core.fieldTerm = (compareStatus (Comparereport.moduleCompareStatus x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "ourSize"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) (Comparereport.moduleCompareOurSize x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "canonSize"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) (Comparereport.moduleCompareCanonSize x))},
+        Core.Field {
+          Core.fieldName = (Core.Name "diffLines"),
+          Core.fieldTerm = ((\x2 -> Core.TermLiteral (Core.LiteralInteger (Core.IntegerValueInt32 x2))) (Comparereport.moduleCompareDiffLines x))}]})
diff --git a/src/main/haskell/Hydra/Encode/Build/Format.hs b/src/main/haskell/Hydra/Encode/Build/Format.hs
--- a/src/main/haskell/Hydra/Encode/Build/Format.hs
+++ b/src/main/haskell/Hydra/Encode/Build/Format.hs
@@ -10,7 +10,7 @@
 import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
 import qualified Hydra.Overlay.Haskell.Lib.Maps as Maps
 import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
-import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
+import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines)
 import qualified Data.Scientific as Sci
 
 -- | Encoder for hydra.build.format.DefinitionNameConventionProfile
