This repository separates upstream history, private changes, temporary review branches, and the runnable build:
pingdotgg/t3code:main
└── fork/tim selected Tim Smart PRs
└── fork/candidates selected open upstream PRs
└── fork/changes our private changes
├── feature PRs
└── fork/integration tested and deployed tip
main mirrors pingdotgg/t3code:main. fork/tim is a linear provenance layer with one commit per
selected Tim Smart PR and a permanently open PR against main. fork/candidates is a temporary
upstream-provenance layer with one commit per selected open upstream PR and a permanently open PR
against fork/tim. fork/changes is the GitHub default branch and canonical private layer, with a
permanently open PR against fork/candidates.
fork/integration is generated from both reviewed layers and is used by running instances.
Do not use GitHub's Sync fork button, create a PR into this repository's main, or push main
manually. A GitHub PR merge would rewrite upstream commits, while an ordinary push is correctly
blocked by the Protect upstream main ruleset.
The Rebase fork PR stack workflow is the sole synchronization path. It runs every six hours and
can also be started with:
gh workflow run rebase-pr-stack.yml --repo patroza/t3code --ref fork/changesThe workflow fetches pingdotgg/t3code:main, verifies that the existing mirror has not diverged,
and atomically updates main, fork/tim, fork/candidates, fork/changes, and
fork/integration with
force-with-lease. A repository-scoped write deploy key stored as FORK_STACK_DEPLOY_KEY is the only
automation actor allowed to bypass main's PR and status-check requirements. It cannot access other
repositories. Never expose or reuse it.
Upstream's .github/workflows/ci.yml and .github/workflows/deploy-relay.yml remain present on the
exact main mirror but are disabled in this repository. Fork PR and integration checks use
.github/workflows/fork-ci.yml; the stack workflow dispatches that workflow for the exact generated
integration SHA. This avoids redundant CI and prevents an upstream-mirror update from being treated
as a fork product or relay deployment.
The helper starts an independent branch from fork/changes:
pnpm fork:stack start feature/my-changeCommit and push normally, then open the PR against fork/changes. Updating that branch updates the
same PR and reruns PR CI. Ordinary feature and import PRs are deliberately not registered in the
stack manifest, so multiple independent PRs may be open concurrently without editing central
metadata.
After review, merge the PR into fork/changes. That push automatically runs the stack synchronizer:
feature PR merged into fork/changes
→ rebase-pr-stack workflow
→ fork/integration updated atomically
→ CI dispatched for the exact integration SHA
→ successful CI classifies the tree diff
→ runtime-affecting changes trigger fleet deployment
→ test, documentation, and automation-only changes stop after CIDeployment classification compares complete tested integration trees rather than only the latest commit. Unknown paths are runtime-affecting by default. This preserves safe deployment when a PR contains mixed changes or a new source directory appears, while avoiding fleet rebuilds and mobile OTA updates for tests, snapshots, documentation, agent instructions, and GitHub-only metadata.
The manifest contains the permanent fork/tim, fork/candidates, and fork/changes PRs. The
synchronizer rebases that provenance chain onto the latest upstream main and rebuilds
fork/integration. Other open repository PRs are ignored. Temporary state is retained after a
conflict and can be resumed with the command printed in the error.
register is used during the one-time cutover and only when intentionally building an advanced,
dependent integration chain:
pnpm fork:stack register 201The permanent fork/tim, fork/candidates, and fork/changes PRs are never merged while this
model is active.
Independent changes use parallel branches and PRs, all based on fork/changes. They can be reviewed
and merged in any order; rebase a remaining branch if an earlier merge overlaps it.
Related changes may use one cohesive PR. If separate review is valuable, chain only those PRs by
basing the dependent PR on the preceding feature branch. Merge the chain from bottom to top into
fork/changes. Do not place unrelated features in one dependency chain.
Use the PR title, branch name, affected-area field in the PR template, and GitHub's open/merged PR
history to find prior work. Agents must check gh pr status and verify a PR's state before deciding
whether to update its branch or create a new PR.
Search by feature words instead of remembering PR numbers:
pnpm fork:stack find "board pagination"
pnpm fork:stack find-upstream "worktree cleanup"External forks are source remotes, not branches to merge wholesale. For Tim Smart, start an import
branch from fork/tim, port only the wanted source PR, and open it against fork/tim:
git fetch tim
git switch -c import/tim-pr-17 origin/fork/tim
git cherry-pick <unchanged-commit>
git cherry-pick --no-commit <commit-to-adapt>
# keep Tim's imported behavior in one commit; test and open against fork/timDo not merge an external branch wholesale. For every import PR, document:
- imported unchanged;
- adapted to local behavior;
- intentionally excluded;
- provenance using fully qualified links such as
tim-smart/t3code#17.
Merge the import with squash so fork/tim gains exactly one provenance commit. Adjustments for our
environment use a separate normal PR against fork/changes; never hide private policy inside the
Tim layer. A later Tim update is compared against both the prior provenance commit and our
adjustment, and automation never overwrites local decisions.
An upstream PR may be production-worthy before pingdotgg/t3code accepts it. Import it from
fork/candidates, never from main, fork/tim, or fork/changes:
git fetch origin fork/candidates
git fetch upstream refs/pull/<number>/head:refs/remotes/upstream/pr/<number>
git switch -c import/upstream-pr-<number> origin/fork/candidates
git cherry-pick --no-commit upstream/pr/<number>
# retain only the reviewed source PR behavior, update .github/upstream-candidates.json,
# test, commit once, push, and open against fork/candidatesEach candidate PR must become exactly one provenance commit and document the upstream PR URL,
source SHA, imported behavior, local adaptations, and exclusions. The registry
.github/upstream-candidates.json records the same source SHA and lifecycle state. Product-specific
follow-ups belong in fork/changes, not in the candidate commit.
Before updating the upstream mirror, inspect every active candidate:
- unchanged and open: retain it;
- updated upstream: review and replace its provenance commit through a new candidate PR;
- merged with equivalent behavior: remove the candidate commit while rebasing the layer;
- merged differently or closed: stop automatic synchronization and reconcile deliberately.
After reconciliation, compare the old and rebuilt fork/integration trees. Removing an accepted
candidate must not remove adaptations that belong to fork/changes.
Every feature lands in fork/changes; upstreamability is a clean projection, not an alternative
home. Closing or rejecting an upstream PR therefore never removes the private implementation.
After the private PR merges, promote it onto real upstream history:
pnpm fork:stack promote <private-pr-number> upstream/portable-feature
# remove private assumptions from the staged extraction, test, and commitThe command creates a branch from upstream main and stages the private PR's commits without
committing, allowing the projection to be simplified before opening it to pingdotgg/t3code:main:
gh pr create \
--repo pingdotgg/t3code \
--base main \
--head patroza:upstream/portable-featureFor work that began upstream-first, adopt its clean branch into the private fork:
pnpm fork:stack adopt upstream/portable-feature adopt/portable-feature
# push and open adopt/portable-feature against fork/changesIf the upstream proposal is withdrawn, demotion closes only the projection and cross-links the private source:
pnpm fork:stack demote <upstream-pr-number> <private-pr-number>Never rebase the private branch onto main. Promotion creates an independently reviewable upstream
implementation while fork/changes remains canonical. Select main in T3, or use
start-upstream, only for deliberately upstream-first work.
The registered chain is ordered from upstream toward deployment. Its final PR must always use
fork/changes; earlier permanent layers describe provenance such as fork/tim and
fork/candidates. Add another layer only when it has durable ownership and update the manifest, PR
bases, and documentation together.
The pre-provenance woven graph is preserved locally and remotely at:
archive/fork-changes-woven-2026-07-24archive/fork-integration-woven-2026-07-24- matching annotated tags prefixed with
archive-
The clean rebuild preserves the exact archived fork/changes tree while replacing its ancestry
with main → fork/tim → fork/candidates → fork/changes. Never delete or force-update the archive
refs.