TILLFORGE · PULL REQUESTS

Reviews, a real merge gate, crash correlation.

GA

Open a PR, get it reviewed, and merge behind a gate that enforces required approvals of the current head and required status checks — no green-then-sneak-a-push. External CI gates merges through the checks API, CODEOWNERS routes reviewers, and every shipped release is correlated with the crashes it caused.

01Pull requests

Open, review, merge

A PR proposes merging a source ref into a target. Review states are approved, changes_requested, and commented. Merge with merge, squash, or rebase.

bash
# Open a PR, review it, merge behind the gate.
tilldev forge pr create acme-api --title "Add rate limiter" \
  --source feat/rate-limit --target main
tilldev forge pr ls acme-api --state open
tilldev forge pr get acme-api 42
tilldev forge pr comment acme-api 42 --file src/limit.ts --line 18 --body "Off by one?"
tilldev forge pr review acme-api 42 --state approved   # or changes_requested | commented
tilldev forge pr merge acme-api 42 --strategy squash   # merge | squash | rebase

A line comment stays with its line as the PR changes: push more commits or rebase, and it moves with the line it was left on; if that line itself changes, the comment is marked outdated, never lost. Every push re-runs the PR’s checks at the new head. You can also review from VS Code with the TillForge extension: the PR’s files open as diffs, and you comment on lines and submit your verdict without leaving the editor.

The merge itself is performed without a server-side working tree — the node computes the merged tree and commit directly, and a conflict is reported without mutating anything. Nothing is auto-checked-out on the server, which is also why a malicious tree can’t escape a checkout (there isn’t one).

02The gate

The merge gate enforces the branch policy

Merge is not a rubber stamp. The control plane re-checks the branch policy at merge time and refuses if it isn’t satisfied:

RequirementWhat it enforces
Required approvalsEnough approving reviews of the current head — an approval is invalidated by a new push, so you can’t approve then quietly change the diff.
Required checksEvery named status check on the head commit is green. Through the merge queue, they must also pass on the merge result itself.
Push rulesMerging moves the branch, so its push rules apply to whoever merges: only named members can merge into a restricted branch, and a branch that requires MFA to push needs the merger to have signed in with MFA.
Signed / linearIf the branch requires signed commits, every commit the pull request brings must meet the rule, whatever the strategy, and the commit the merge writes is signed by TillForge. If it requires linear history, the pull request merges by squash or rebase; the merge strategy is refused.
03Merge queue

The queue tests what will land

When a branch’s rule turns on the merge queue, pull requests join a line instead of merging. At its turn each entry is checked again: the branch’s push rules as whoever queued it, approvals of the current head, required checks on the head and CODEOWNERS.

If the branch requires checks, a passing head isn’t enough. TillForge merges the pull request onto the branch’s current tip as a test commit and runs the required checks on that commit: TillForge CI starts the jobs itself, and a merge_queue webhook tells any other CI which commit to test. The branch moves to that exact commit once every required check passes on it, and only if nothing else landed in the meantime. If something did, the test commit is built again on the new tip and tested again.

bash
# Join the queue; the branch's rule must have --merge-queue on.
tilldev forge pr queue acme-api 42 --strategy squash
tilldev forge queue acme-api        # testing = checks running on the merge result

# Any other CI: on a merge_queue webhook with action "testing",
# fetch trial_ref, test it, and report on trial_sha.
git fetch origin refs/forge/queue/<entry>
tilldev forge check acme-api --sha <trial_sha> --context ci --state success

A failing check on the test commit takes the entry out of the queue with the check named, and so do checks that haven’t all reported within six hours. A pull request that merges as a fast-forward is its own merge result, so it lands on the checks its head already passed.

04Checks API

External CI gates merges

TillForge ships the checks / status API so your existing CI can gate merges today. Post a state for a commit and context; the merge gate reads it. Reports are idempotent per repo + commit + context, and the --url back-link is SSRF-validated — it is stored and shown, never fetched by us.

bash
# Report a status check from your CI (idempotent per repo+sha+context).
tilldev forge check acme-api --sha <commit-sha> \
  --context ci --state success --url https://ci.example.com/run/123
tilldev forge checks acme-api --sha <commit-sha>       # read the status set
Where CI runs
Run CI on your own machines with TillForge runners, or report results from any other CI through the checks API. Either way, required checks gate the merge.
05CODEOWNERS

CODEOWNERS routes reviewers

A CODEOWNERS file (gitignore-style globs, last match wins) maps paths to owners. TillForge diffs a PR, finds the owners of the changed files, and routes the review request to them — so the right people see the change without anyone remembering to add them.

bash
# Who owns the files a PR changes → reviewer routing.
tilldev forge codeowners acme-api --rev main           # the CODEOWNERS map
06Correlation

Which change caused which crash

Because the commit and PR graph lives here, TillForge lines up the code you ship with the crashes it causes, with no external webhook. A TillPulse release that records the commit it was built from (--commit) is joined to this repository’s history, with its crash-free rate and A–F grade.

bash
tilldev forge correlation acme-api --rev main

For one release, --release compares it with the release before it in the same project and environment, then ranks the pull requests and commits in between by how closely their changed files match the stack frames of crashes that are new or regressed in it. Frames nearer the crash site and crashes with more events weigh more; a change touching hundreds of files counts for less. The same view is the repository’s Crashes tab.

bash
tilldev forge correlation acme-api --release v2.4.0

release   v2.4.0   crash-free 91.2%   grade C
vs prior  v2.3.1   crash-free 99.6%   Δ -8.4pp

suspects: changes whose files appear in new crash stacks
  #812  checkout: retry on 5xx         ravi  2 crashes · src/checkout/retry.ts
  #809  cart: parallelize price lookups  ada   1 crash · src/cart/prices.ts
A ranking, not a verdict
Suspects tell you which change to read first. A match means the change touched a file the crash runs through, not that it caused the crash.

Route new crashes to their owners

Link the repository to its TillPulse project under Settings → TillPulse project, or with tilldev forge repos update acme-api --pulse-project checkout. Pushes then record their commits in that project. When a new crash group appears, it is routed to the member who most recently changed a file in its stack (last 30 days, starting from the crash site), shown as the issue’s owner, and they are notified in the app and by email. Email can be turned off in notification settings.


The branch policy behind the gate is in Branch protection; every command here is in the CLI reference. Back to the TillForge overview.