ADR 0048: Rename the graduation landing-role main → trunk
Consolidated into ADR 0046. The
main→trunkrename 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 readsgraduate_to = "main"as a literal branch that does not match their trunk, then instinctively writesgraduate_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_TARGETSbecomes["branch", "trunk"]. The CLI--to, thetotool parameter, the dry-run plan, the worktree guidance, and the generated config reference all readtrunk.- 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 adoptedgraduate_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 amasterrepo, 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.