Skip to content

ADR 0048: Rename the graduation landing-role maintrunk

Consolidated into ADR 0046. The maintrunk rename is folded into the configurable-destination ADR. Kept for history.

Status: accepted

Context

§

ADR 0046 gave discern graduate a configurable destination through [worktree].graduate_to (and --to per run). It took two values: "branch" (leave the work on its own branch for review) and "main" (fast-forward the trunk to the branch tip, then delete the merged branch).

"main" always named a role, never a literal branch. The executor fast-forwards [project].main_branch, whatever a project calls it. The engine, the dry-run plan steps (fast-forward-trunk), the human docs, and 0046's own prose all call this landing "the trunk". Only the user-facing value borrowed the default branch's name.

That borrowing is a footgun on any repo whose trunk is not main:

  • A master-trunk user reads graduate_to = "main" as a literal branch that does not match their trunk, then instinctively writes graduate_to = "master".
  • The schema rejects it — Invalid option: expected one of "branch"|"main" — and never hints that "main" is the role that already means their trunk.

Reflex, not reasoning, picked the name. 0046's "Alternatives considered" weighed rename-on-graduate and flipping the default, but never the role's own name.

Decision

§

Rename the value "main""trunk". The pair becomes "branch" (leave it on its own branch) and "trunk" (land it on the integration branch) — two roles, not a role beside a literal branch. "trunk" resolves to [project].main_branch exactly as "main" did. Only the spelling changes.

The rename removes a vocabulary split rather than adding one. "trunk" is already the word the engine, the plan steps, and the docs use. It also reads as a role, so a master (or develop) repo never types its own trunk name. The shipped discern.toml comment now spells out that "trunk" resolves to [project].main_branch (main, master, …). That closes the footgun right where a user configures it.

A schema migration (11→12) carries an existing graduate_to = "main" to "trunk". It leaves "branch" and an absent key untouched. Without it, the new enum would reject a "main" config on the next read.

Consequences

§
  • GRADUATE_TARGETS becomes ["branch", "trunk"]. The CLI --to, the to tool parameter, the dry-run plan, the worktree guidance, and the generated config reference all read trunk.
  • Migration 11→12 carries a legacy "main" value forward. It stays idempotent (a no-op once "trunk", on "branch", or when the key is absent) and never invents a key the user omitted.
  • This repo's own discern.toml, which had adopted graduate_to = "main", now reads "trunk".

Alternatives considered

§
  • Keep "main"; only improve the rejection message. Rejected. A better error papers over the confusion but leaves the value reading as a literal branch in every config and doc.
  • Accept the literal trunk name (say, "master") too. Rejected. Two spellings for one role bring back ambiguity — on a master repo, does "main" mean the role or an error? — for no gain over one clear keyword.
  • Do nothing; the feature already works for any trunk. Rejected. It works, yet the name misleads exactly the users whose trunk is not main — the ones the reflex name serves worst.
choose openEsc close