forgejo: squash unless curation is claimed, and name the curated style #22

Merged
larandar merged 1 commit from tango/squash-unless-curated into main 2026-08-11 20:14:12 +00:00
Owner

The Ting half of lar.ad/flake-ops#79 — owner ruling of 2026-08-11, that a merge with no claim attached should squash.

Stacked on #20 (base is tango/curated-and-standing) because it moves a value #20 explicitly declared out of scope. Merge #20 first and this retargets to main.

In scope

  • instance."repository.pull-request".DEFAULT_MERGE_STYLE is squash. This file declares the instance defaults; lar.ad/flake-ops's modules/impls/forge/forgejo.nix is where they are applied, and flake-ops#79 moves that one. They move together because the check in flake.nix compares the two halves and would otherwise say so — which is the check working, not the check being in the way.
  • curatedStyle is now its own name. nix/policy.nix read merge_style_curated from mergeStyles.default_merge_style, and that was correct only for as long as the default happened to be rebase.

The trap, since it is the reason this is more than one word

Changing the default alone would have made the curated path squash as well. The label would have gone on being read, applied, and reported — while meaning nothing, because both branches of the rule would have declared the same style. Nothing would have failed. The merge rule's own tests would have passed, because they assert Do == "rebase" for a curated PR against a fixture policy that spells its styles out rather than deriving them.

Two decisions had one name. They now have two: curatedStyle is what a claim buys, default_merge_style is what applies without one. Both are still validated against the repos' allow-set by the existing eval assertion, so neither can name a style the forge refuses.

Out of scope

  • What the steward declares. Unchanged: rebase when the label is present, squash when it is not.
  • The allow-set. rebase, squash and fast-forward-only stay allowed; merge commits and rebase-merge stay off. This moves which style is offered first, not which are possible.
  • Existing repositories. A DEFAULT_* only reaches repos created after it is set — every repo here still reports default_merge_style: merge. This ruling reaches them through per-repo conformance, which this file already declares, not through app.ini.

Boundary

nix/forgejo.nix (the instance default, and curatedStyle), nix/policy.nix (reads it), flake.nix (the literal the check pins). No Rust, no policy parameters' values, no module.

Acceptance

Verified locally:

  • nix flake check passes, including repos-declare-what-must-hold — which pins the instance/per-repo agreement and now pins it at squash.
  • nix build .#policy renders merge_style_curated: "rebase", merge_style_uncurated: "squash" — unchanged, which is exactly the point: the values stayed put while what determines them stopped being one value wearing two hats. policy/ting.json needs no edit and the drift check stays quiet.

(As with #20, the check run uses --override-input jostoph-rs path:… against lar.ad/jostoph-rs#5; see #20 for why.)

Authored as agent.odin.

The Ting half of [lar.ad/flake-ops#79](https://jo.et0.pw/lar.ad/flake-ops/issues/79) — owner ruling of 2026-08-11, that a merge with no claim attached should squash. **Stacked on #20** (base is `tango/curated-and-standing`) because it moves a value #20 explicitly declared out of scope. Merge #20 first and this retargets to `main`. ## In scope - **`instance."repository.pull-request".DEFAULT_MERGE_STYLE` is `squash`.** This file *declares* the instance defaults; `lar.ad/flake-ops`'s `modules/impls/forge/forgejo.nix` is where they are applied, and flake-ops#79 moves that one. They move together because the check in `flake.nix` compares the two halves and would otherwise say so — which is the check working, not the check being in the way. - **`curatedStyle` is now its own name.** `nix/policy.nix` read `merge_style_curated` from `mergeStyles.default_merge_style`, and that was correct only for as long as the default happened to be `rebase`. ## The trap, since it is the reason this is more than one word Changing the default alone would have made the **curated** path squash as well. The label would have gone on being read, applied, and reported — while meaning nothing, because both branches of the rule would have declared the same style. Nothing would have failed. The merge rule's own tests would have passed, because they assert `Do == "rebase"` for a curated PR against a fixture policy that spells its styles out rather than deriving them. Two decisions had one name. They now have two: `curatedStyle` is what a claim buys, `default_merge_style` is what applies without one. Both are still validated against the repos' allow-set by the existing eval assertion, so neither can name a style the forge refuses. ## Out of scope - **What the steward declares.** Unchanged: `rebase` when the label is present, `squash` when it is not. - **The allow-set.** `rebase`, `squash` and fast-forward-only stay allowed; merge commits and rebase-merge stay off. This moves which style is *offered first*, not which are possible. - **Existing repositories.** A `DEFAULT_*` only reaches repos created after it is set — every repo here still reports `default_merge_style: merge`. This ruling reaches them through per-repo conformance, which this file already declares, not through app.ini. ## Boundary `nix/forgejo.nix` (the instance default, and `curatedStyle`), `nix/policy.nix` (reads it), `flake.nix` (the literal the check pins). No Rust, no policy parameters' *values*, no module. ## Acceptance Verified locally: - **`nix flake check` passes**, including `repos-declare-what-must-hold` — which pins the instance/per-repo agreement and now pins it at `squash`. - **`nix build .#policy` renders `merge_style_curated: "rebase"`, `merge_style_uncurated: "squash"`** — unchanged, which is exactly the point: the values stayed put while what determines them stopped being one value wearing two hats. `policy/ting.json` needs no edit and the drift check stays quiet. (As with #20, the check run uses `--override-input jostoph-rs path:…` against lar.ad/jostoph-rs#5; see #20 for why.) Authored as `agent.odin`.
agent.odin force-pushed tango/squash-unless-curated from bbf6a80707 to 6a0bca7149 2026-08-11 08:09:41 +00:00 Compare
larandar changed target branch from tango/curated-and-standing to main 2026-08-11 20:13:36 +00:00
larandar approved these changes 2026-08-11 20:14:04 +00:00
larandar deleted branch tango/squash-unless-curated 2026-08-11 20:14:12 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
Ting/Jostoph!22
No description provided.