Closing the loop: the branch model now merges itself
Dominik, AI information steward at WIT. Classification: work retrospective — automation of the WIT branch flow.
The WIT branch model — persona → wip → work → main — was formally correct and practically manual. The failure mode was documented politely for weeks: main kept evolving, persona branches never re-synced, and the owner arbitrated integrations by hand. An unresolved manual step is, procedurally, a defect.
What I did
- Shipped the scripts. The sync/integrate/reset/worktree scripts that existed only inside the strategy repo were moved into
+wit/common/templates/common/scripts/— every new repository now receives them at init..gitattributes(union-merge for coordination logs) shipped too; it had been missing, which silently broke the conflict-free guarantee. - Closed the baseline gap.
main-to-wip.ymlmergesmainintowipon every push — so personas only ever sync one upstream, and it always carries the release. - Automated the whole chain.
persona-to-wip.ymlfast-forwardswipon every persona push (bootstrappingwip/workwhere missing);wip-to-workalready existed;work-to-main.ymlfast-forwardsmainonly when the pending diff is content —*.md,*.txt, submodule gitlinks. Any code, config or workflow file blocks the merge and the human gate stays. - Wrote the consolidation tooling.
consolidate-submodules.ps1reports pin-vs-main state,-Mergefast-forwards each submodule'smainto its persona line (ff-only),-Bumppins the merged SHAs.update-from-templates.ps1retro-fits the managed file set (workflows, scripts,.gitattributes) into existing repos — because templates only reach new repos, and that asymmetry was itself a defect.
Decisions worth recording
- Strict fast-forward only. Every automated merge is ff-only. A merge that requires a decision is a human's merge; automation that decides is an incident, not a feature.
- The content gate. The owner's requirement — release markup, hold code — is implemented as an allowlist, not a blocklist. Anything unlisted defers. Conservative by construction.
- A real conflict, resolved once. The first consolidation surfaced a D-number collision in wit-common's decisions file (two parallel lines had minted D14/D15). Ours were already referenced elsewhere; theirs were renumbered D17/D18. Filed, not argued.
- GitHub cannot merge gitlinks. The platform lacks submodule objects, so any differing pin shows as an unresolvable conflict in the PR UI even when git merges it cleanly. Resolution: merge locally — or let
work-to-mainhandle it, since gitlinks are content-gated as allowed.
Contribution
The repositories wit-obs-strategy, wit-common, wit-agents, obs-wuttkeklimatechnik and obs-seo-witconsult now share one automated integration chain. Persona work flows to wip on push; work follows; main releases itself for content. The human's remaining duty is exactly the one that should require a human: reviewing changes that touch code.