|
| 1 | +# Move Plinth source tree to a separate repository |
| 2 | + |
| 3 | +- Status: accepted |
| 4 | +- Deciders: Yuriy Lazaryev (Unisay) |
| 5 | +- Date: 2026-05-20 |
| 6 | +- Tags: plinth, repository-structure, submissions, evaluator |
| 7 | + |
| 8 | +Technical Story: <https://github.com/IntersectMBO/UPLC-CAPE/issues/193> |
| 9 | + |
| 10 | +## Context and Problem Statement |
| 11 | + |
| 12 | +UPLC-CAPE played two roles for Plinth that no other compiler in the benchmark |
| 13 | +suite (Scalus, Aiken, Plutarch, …) imposed: it stored compiled `.uplc` |
| 14 | +artefacts and measurements *and* it hosted the Haskell source tree, |
| 15 | +plutus-tx-plugin pragmas, and `cabal.project` machinery that produced those |
| 16 | +artefacts. Two unrelated axes were conflated in the build matrix here: |
| 17 | + |
| 18 | +- target evaluator surface (mainnet `plutus-core` vs an upcoming-HF |
| 19 | + `plutus-core`); |
| 20 | +- compiler version used to emit UPLC (Plinth 1.45 vs Plinth 1.61, with 1.64 |
| 21 | + pending). |
| 22 | + |
| 23 | +`cabal.project` and `cabal.project.preview` mixed both axes, and every new |
| 24 | +Plinth release multiplied the build surface here even though the only durable |
| 25 | +output is the `.uplc` plus its measurements. Other compiler submissions |
| 26 | +(`Scalus_*_Unisay`, `Aiken_*_*`) already follow a thinner pattern: each |
| 27 | +submission's `source/README.md` points at an external repository at a |
| 28 | +specific commit, and the only files committed in UPLC-CAPE are the artefact, |
| 29 | +metrics, and a short README. |
| 30 | + |
| 31 | +## Decision Drivers |
| 32 | + |
| 33 | +- Lower the build / onboarding cost for non-Plinth contributors to UPLC-CAPE. |
| 34 | +- Allow the Plinth source to follow its own release cadence (1.64 is current; |
| 35 | + more bumps expected as `plutus-tx-plugin` releases continue). |
| 36 | +- Align Plinth with the Scalus / Aiken layout so the framework treats every |
| 37 | + compiler symmetrically. |
| 38 | +- Keep the .uplc artefacts exactly reproducible from a single named commit |
| 39 | + per archive line. |
| 40 | + |
| 41 | +## Considered Options |
| 42 | + |
| 43 | +- Keep Plinth source in-tree and continue maintaining one |
| 44 | + `cabal.project.<line>` file per Plinth release. |
| 45 | +- Move Plinth source to a separate repository with archive branches frozen at |
| 46 | + the commit that produced each `Plinth_<ver>_Unisay/*.uplc` currently in |
| 47 | + UPLC-CAPE, and a `main` branch that collapses the preview axis into a |
| 48 | + cabal flag. |
| 49 | + |
| 50 | +## Decision Outcome |
| 51 | + |
| 52 | +Chosen option: **separate repository with archive branches**, hosted at |
| 53 | +<https://github.com/Unisay/plinth-cape-submissions>. UPLC-CAPE keeps the |
| 54 | +evaluator (`measure`, `measure-preview`, `pretty-uplc`), the measurement |
| 55 | +library, the test suite, the `cape` CLI, and the published `.uplc` / |
| 56 | +`metrics.json` / `metadata.json` / `source/README.md` files per submission. |
| 57 | + |
| 58 | +The Plinth submission repository has three branches: |
| 59 | + |
| 60 | +- `main` — current production line (Plinth 1.64.0.0). The preview axis |
| 61 | + (`BuiltinCasing`) is now a cabal flag (`--flags=preview`) that only changes |
| 62 | + GHC options and the destination subdirectory; there is no parallel |
| 63 | + `lib/Preview/` tree on `main`. |
| 64 | +- `plinth-1.45` — frozen snapshot that reproduces byte-identical UPLC for |
| 65 | + every `submissions/<sc>/Plinth_1.45.0.0_Unisay/<sc>.uplc` in this repo. |
| 66 | +- `plinth-1.61` — same shape for `Plinth_1.61.0.0_Unisay/*.uplc`. |
| 67 | + |
| 68 | +Each Plinth submission's `source/README.md` here points at the relevant |
| 69 | +branch + commit SHA + module path, matching the existing Scalus / Aiken |
| 70 | +pattern. |
| 71 | + |
| 72 | +UPLC-CAPE no longer depends on `plutus-tx-plugin`. `flag preview`, |
| 73 | +`executable measure-preview`, and `cabal.project.preview` are intentionally |
| 74 | +kept: `measure-preview` is the evaluator used to score |
| 75 | +`Plinth_1.61.0.0_Unisay/*.uplc` (and any other ≥1.46 UPLC) against a newer |
| 76 | +`plutus-core` baseline. That dual-resolver setup is orthogonal to where the |
| 77 | +Plinth source lives. |
| 78 | + |
| 79 | +### Positive Consequences |
| 80 | + |
| 81 | +- Adding or measuring a non-Plinth submission no longer pulls in |
| 82 | + `plutus-tx-plugin`, `plutus-metatheory`, or the rest of the Plinth build |
| 83 | + surface. |
| 84 | +- The Plinth repo tracks the latest released Plinth on its own cadence; this |
| 85 | + repo does not need to be touched for every Plinth bump. |
| 86 | +- The repository layout is symmetric across all compilers; there is no |
| 87 | + privileged in-tree compiler. |
| 88 | +- Reproducibility of historical Plinth measurements is anchored to immutable |
| 89 | + branch SHAs rather than to the current state of `lib/`. |
| 90 | + |
| 91 | +### Negative Consequences |
| 92 | + |
| 93 | +- Editing a Plinth validator now requires two checkouts side-by-side |
| 94 | + (`UPLC-CAPE/` and `plinth-cape-submissions/`) and an explicit `CAPE_REPO` |
| 95 | + env var when running the generator. |
| 96 | +- Cross-repo PRs (source change in the Plinth repo, `.uplc` + `metrics.json` |
| 97 | + update here) are now a two-step workflow. Re-measuring existing `.uplc` |
| 98 | + remains a UPLC-CAPE-only operation. |
| 99 | + |
| 100 | +## Pros and Cons of the Options |
| 101 | + |
| 102 | +### Keep Plinth source in-tree |
| 103 | + |
| 104 | +- Good, because a single checkout produces and measures Plinth submissions. |
| 105 | +- Bad, because every Plinth release multiplies the in-tree build matrix. |
| 106 | +- Bad, because non-Plinth contributors still pay the |
| 107 | + `plutus-tx-plugin` / `plutus-metatheory` build cost. |
| 108 | +- Bad, because the layout is asymmetric: Plinth is privileged, every other |
| 109 | + compiler (Scalus, Aiken, Plutarch) is external. |
| 110 | + |
| 111 | +### Separate repository with archive branches (chosen) |
| 112 | + |
| 113 | +- Good, because it matches the existing Scalus / Aiken pattern. |
| 114 | +- Good, because immutable archive branches encode "this is exactly the |
| 115 | + source state that produced the committed UPLC". |
| 116 | +- Good, because the cabal-flag preview collapse on `main` removes the |
| 117 | + parallel `lib/Preview/` source tree (was a mechanical re-compile only). |
| 118 | +- Good, because the .uplc → repository contract is now identical across |
| 119 | + compilers, simplifying the framework's domain model. |
| 120 | +- Bad, because the developer workflow needs two checkouts side by side. |
| 121 | + |
| 122 | +## Links |
| 123 | + |
| 124 | +- Implementation issue: <https://github.com/IntersectMBO/UPLC-CAPE/issues/193> |
| 125 | +- Plinth submission repository: |
| 126 | + <https://github.com/Unisay/plinth-cape-submissions> |
| 127 | +- Scalus submission repository (existing precedent): |
| 128 | + <https://github.com/Unisay/scalus-cape-submissions> |
0 commit comments