Forking
View as markdownIn the forking workflow contributors don't push to the canonical repository at all. They fork it, work on their own copy, and open a pull request from the fork. The maintainer's job is a review gate: triage what comes in, run it through checks, and merge only what clears sign-off. It's the model most open-source projects run.
Shelbi models the maintainer's side. Because the branch lives on
someone else's fork, Shelbi doesn't cut branches or push here. Each task
carries the fork's PR branch in branch:,
and the workflow is mostly about the gate: a handoff sign-off status
that's owner: user so nothing reaches main without a human (or a
Zen-authorized reviewer agent) accepting it.
The board
A fork PR lands in Incoming, the orchestrator triages it into scope,
the reviewer agent runs it through checks in In Review, and it waits
in Sign-off for a maintainer to accept before it's Merged.
The statuses
The forking flow relabels the whole board, so declare its statuses (id
name+category) in the project's status catalog first (workflows/statuses.yaml), then reference them byidfrom the workflow:
# workflows/statuses.yaml — the forking project's status catalog.
statuses:
- { id: incoming, name: Incoming, category: backlog }
- { id: triage, name: Triage, category: ready }
- { id: in-review, name: In Review, category: active }
- { id: sign-off, name: Sign-off, category: handoff }
- { id: merged, name: Merged, category: done }
- { id: declined, name: Declined, category: archived }The workflow
# workflows/contribution.yaml — reference-only; identity lives in statuses.yaml
name: contribution
description: Forking flow — review gate for pull requests from forks.
git:
base_branch: main
merge_strategy: squash # squash external contributions into one commit
statuses:
- { id: incoming, owner: user }
- { id: triage, owner: agent, agent: orchestrator }
- { id: in-review, owner: agent, agent: reviewer }
- { id: sign-off, owner: user }
- { id: merged, owner: user }
- { id: declined, owner: user }
initial_status: incoming
transitions:
- from: in-review
to: sign-off
actions: [push_branch] # push the fork branch to a review ref; no PR to open
- from: sign-off
to: merged
actions: [merge] # squash-merge the existing fork PR into main
- from: in-review
to: declined
actions: [close_pr] # close the PR without merging; the fork keeps its branchTwo side-effects that the feature-branch model uses are deliberately absent here:
- No
open_pr. The contributor already opened the PR from their fork. The task just tracks it. Pre-fillbranch:with the PR's head ref somergeandclose_pract on the right PR. - No
delete_branch. Shelbi can't delete a branch it doesn't own. The fork keeps its branch whether the PR merges or is declined.
The in-review status names an agent: reviewer
role, an agent you author to run the untrusted contribution through the
project's checks and summarize risk before a human ever looks. The
sign-off status stays owner: user: the gate is the whole point.
Orchestrator adjustments
The review gate needs the orchestrator to treat incoming forks as untrusted and never to auto-accept. Encode a triage rule and a hard stop at sign-off:
## Routing rules — forking
- **Incoming fork PRs** are untrusted. Never dispatch a contribution to a
workspace that holds credentials or can reach production. Route `Triage`
cards only to sandboxed hub workspaces.
- In `Triage`, decline anything out of scope (wrong direction, duplicate,
no linked issue) into `Declined` with a one-line reason. Promote the
rest to `InReview` for the `reviewer` agent.
## Zen Mode — forking
The `SignOff → Merged` edge is `owner: user` and must stay a human
decision. Do **not** auto-merge contributions even when checks are green:
report "`<PR>` passed review and is ready to sign off" and wait. A green
check is necessary but not sufficient for merging someone else's code.That last rule is the difference between forking and trunk-based: trunk-based leans into auto-merge for your own green work; forking deliberately keeps a human at the gate for code that arrived from outside.
See also
- Agents — how to author the
reviewerrole theInReviewstatus dispatches to. - Workflows: the
branch:task field — pointing a task at an existing fork PR branch instead of cutting one. - Trunk-based — the opposite end of the auto-merge spectrum, for work you trust.