Status: Accepted
A recurring strategic question: should iterion couple itself to an open-source forge (Forgejo) — by embedding it, forking it, building its own forge derived from its code, or by remaining an interfaceable layer over a forge and deepening the integration?
The codebase already draws a clean line:
pkg/dispatcher/native/ (issues, board,
labels, comments, custom fields, saved views, swimlanes, events.jsonl), with
no forge dependency for local workflows.pkg/git/
shallow-clones + worktrees (read-only status/diff/log); bots commit/push from
inside their sandbox with a sealed OAuth token. There is no git-hosting
primitive (no git http/ssh server, no hosted PR/review/branch).forge.Admin,
forge.IssueClient/forge.PullClient,
tracker.Tracker, and the inbound
webhook parsers in pkg/webhooks/ — with GitHub,
GitLab and Forgejo at near-parity, plus the event-driven trigger spine
(ADR-046).So iterion already owns “work orchestration + tracking” and delegates the heavy, commoditized part (git + PR + review + CI) to the forge. The boundary exists and is healthy.
iterion remains an AI-native layer over an interchangeable forge. We close the gaps inside the existing abstraction; we do not fork a forge and we do not build one.
Rationale:
forge.Admin / tracker.Tracker abstraction is the asset to
protect.forgejo adapter, zero code coupling), to revisit only if a
“batteries-included self-hosted” story becomes a priority. Forgejo would stay a
black box behind forge.Admin.The integration is deepened by filling these gaps within the existing interfaces (this ADR’s accompanying change implements them):
PullClient gains CreatePull / UpdatePull
/ MergePull (was read-only) across all three providers, surfaced as card
actions (pkg/server/board_forge.go) so a
run ties its PR back to the source card.Tracker adapter
(pkg/dispatcher/tracker/gitlab.go)
so GitLab Issues are dispatchable (previously GitLab was reachable only via MR
webhooks).IssueClient.CommentIssue lets a bot reply on the
source issue/PR (was inbound-only).Admin.ListHooks + a per-integration hooks
endpoint, to audit orphaned/divergent forge-side hooks.syncOneIntegration), with the periodic worker kept as the
reconciliation net.The capabilities stay optional (type-asserted, ErrNotSupported) so a
provider/auth-kind that lacks one (e.g. a GitHub-App connection without
issue/PR scope) degrades gracefully.
Reconsider the heavier options only if either holds:
The AI-native collaboration experience (“a forge where agents are first-class collaborators”) is delivered as an overlay via the forge API + the studio (linked-PR/CI panels, board sync) — it does not require owning the git substrate.