How General Translation work moves from a worktree to main.
node scripts/install-skills.mjs gt-ship --project <dir>Run it from a Prototemplate checkout. It links skills/gt-ship into the project’s .claude/skills and .agents/skills; --copy vendors the folder instead, and --dry-run prints each step first.
Kevin Liu (GitHub Kevin-Liu-01) lands General Translation (GT) work through two repositories with different rules. github.com/generaltranslation/gt-cloud is the private monorepo of the product and the website; it squash-merges, requires three checks, is reviewed by three bots, and takes small PRs from k/<topic> worktrees. github.com/Kevin-Liu-01/Prototemplate is public and Kevin's own; it takes commits on main after he has reviewed the work on localhost.
$GT_CLOUD is a gt-cloud checkout (~/gt/gt-cloud on Kevin's machine) and $PROTOTEMPLATE a Prototemplate checkout (~/repos/Prototemplate). The PR body and its screenshots are detailed in references/pr-body.md; the bots, the checks and Linear in references/review-loop.md; the work around a PR (approval, grouping, release hygiene, closing, teammates, upstream, cleanup) in references/beyond-the-pr.md. Two read-only scripts sit in scripts/: pr-size.mjs groups a branch's diff, and pr-bots.mjs reads a PR's review state. The commands below call them at $PROTOTEMPLATE/skills/gt-ship/scripts/; an installed copy of this skill carries the same files in its own scripts/ folder.
motion/ belongs to the Videos session and is untracked in the shared checkout: never stage, edit or delete it. The onboarding and dashboard session works in deck/, src/components/plate, src/app/craft and public/brand/mood, and pushes main from its own worktree. The prototemplate skill (section 8) keeps the full lane map.git -C $GT_CLOUD fetch origin, then git -C $GT_CLOUD worktree add -b k/<topic> <path> origin/main and pnpm install --frozen-lockfile --prefer-offline in the new worktree. Kevin's branches are named k/<topic>. On Kevin's machine the primary gt-cloud checkout sits on codex/website-redesign with old uncommitted work; leave it as it is and never switch its branch. Read gt-cloud facts from origin/main or a fresh worktree, never from that checkout.git branch --show-current before every commit. Before reporting a push, compare gh pr view <n> --json headRefName,headRefOid with the current branch and git rev-parse HEAD. When HEAD descends from the PR head, repair with git branch -f <pr-branch> HEAD && git switch <pr-branch> && git push origin <pr-branch>.gt-cloud-wt-docs and gt-cloud-wt-docs-main hold stale local copies of k/docs-locale-switch-rewrite and k/docs-perf.node_modules. On 2026-10-05 a session's scratchpad held 259 GB, most of it 48 leftover gt-cloud worktrees, the Mac was down to 27 GB free, and Kevin had to ask for the cleanup. Use one per lane or per stack, and remove it as soon as its work is pushed:git -C <wt> status --short prints nothing. · git -C <wt> branch -r --contains HEAD names a remote branch, or git -C <wt> cherry origin/main shows no + lines. · git worktree remove <wt>, then git worktree prune.For many at once, pass the paths that passed both checks to xargs -P 6 -n 1 git worktree remove --force --force in the background (git worktree remove takes one path per call). apps/admin/src/routeTree.gen.ts rewrites itself during type checks; restore it in your own worktree and never count it as work.
--global: Prototemplate and other repositories keep the global one. Check with git log -1 --format='%an <%ae>' against git config user.email, and fix a wrong author with git commit --amend --reset-author before pushing.require_extra_approval_for_unattributed_changes (read 2026-10-05). A Co-Authored-By trailer for Claude adds an author GitHub cannot attribute, and the PR then needs a second human approval. The October 2026 branches carry the trailer. When Kevin wants a PR merged on one approval, reword the commits without it and push with a lease; standing approvals survive because dismiss_stale_reviews_on_push is off (Kevin, #4795, 2026-09-11). The squash commit on main is the PR title with its number, plus a Co-authored-by line for each co-author on the branch's commits.git commit publishes all of it (their half-done deletions rode into a landing commit on 2026-08-07):sh git status --short git add src/app/skills/page.tsx skills/gt-ship git commit -F <scratch>/msg.txt -- src/app/skills/page.tsx skills/gt-ship git status --short
Never run git add -A or git add . in a shared tree: Prototemplate's b56e64c swept 229 files (92 MB) of motion/ onto main (2026-10-01). Never run git checkout <commit> -- <file> or git restore on a file another live session may be editing.
git ls-tree origin/main -- <path> and test -f <path>, and never cut the listing with head. On #4703 a write to apps/landing/__tests__/proxy.test.ts replaced seven attribution tests because a truncated listing hid the file; Greptile caught it. Extend an existing file.style(landing): hero buttons side by side on phones, perf(docs): turn off sidebar prefetch and warm rows on intent. Write the message to a file and pass -F. zsh feeds heredocs on one && chain in operator order, and once put a script into a pushed message (#4689).git fetch first and read git log --oneline HEAD..origin/<branch> for a collaborator's commits. Then push with an explicit lease, git push --force-with-lease=<branch>:<expected sha> origin HEAD:<branch>. A lease against a stale tracking ref erased a collaborator's five commits on 2026-08-26. gt-cloud main refuses force pushes.pnpm lint ends in oxfmt --check ., which the app lint scripts skip, so run pnpm exec oxfmt <changed files>. The lint rules themselves are in gt-lints.Kevin reads a PR's line count first, and so do the reviewers: "why are there dashboard css additions in 5063? and why is it so many lines?" (Kevin, 2026-10-01), then "why is 5063 39.5k lines? fix this." (Kevin, 2026-10-02).
sh git fetch origin node $PROTOTEMPLATE/skills/gt-ship/scripts/pr-size.mjs # origin/main...HEAD node $PROTOTEMPLATE/skills/gt-ship/scripts/pr-size.mjs --base origin/<branch below> # in a stack
It runs git diff --numstat over the range, groups the files as product, tests, fixtures, scripts, assets, docs, lockfile and generated, and prints the comment share of added product code, the test lines per product line, the largest files and a note per group a reviewer will ask about. Justify every large group in the body, or cut it.
k/onboarding-parity-suite) or in the scratchpad. #5063 carried 24k lines of parity suite, 18k of them pretty-printed recorded JSON. A review gallery Kevin asks for lives outside the PR: the sign-in and onboarding states run in Prototemplate at /d/production/signin?state=<id>.check-planning-files check fails on a new Markdown file that reads as a plan; specs and context files stay in the scratchpad. Run node scripts/check-plan-files.mjs --base origin/main.type(scope): sentence, with the app as scope (landing, dashboard, docs, blog). The allowed types are build, chore, ci, docs, feat, fix, perf, refactor, revert, style and test. A feat PR needs a linked Linear issue; the other types pass without one. The title becomes the squash commit's subject on main.references/beyond-the-pr.md).Full rules, an example and the upload commands are in references/pr-body.md.
gt-voice.| Before (main) | After (this branch) | table with one bold caption line. Both themes where the change has a theme.pr-assets orphan branch under screenshots/pr-<n>/ and are linked with blob/pr-assets/...?raw=true., or ), through gh pr view <n> --json body and gh pr edit <n> --body-file. A body can hold markers of its own above them, such as `.Commands and the full check list are in references/review-loop.md.
@greptile review the first time and @greptile review again after; it takes about five minutes. The target is 5/5 on the head commit with every Greptile thread resolved.bugbot run re-triggers it. Devin and the Cursor Approval Agent comment on open; the Approval Agent's risk label needs no reply.addPullRequestReviewThreadReply, then call resolveReviewThread. A thread resolved without a reply still reads as unanswered.sh node $PROTOTEMPLATE/skills/gt-ship/scripts/pr-bots.mjs <n>
It prints the title type, each bot summary with the commit it reviewed against the head, the unresolved and unanswered threads with their ids, and the standing run of each required check. It exits 0 only when Greptile reads 5/5 on the head, no bot thread is open, the branch has no conflict with its base and the three required checks are present and green.
Validate PR title and Linear issue, check-planning-files and run-tests. run-tests aggregates lint, build, the four unit_tests shards, validate, integration, e2e and db (ci.yml on main, 2026-10-05). mergeStateStatus: BLOCKED with every check green means the code-owner review is missing; DIRTY means the branch conflicts with its base.gh run list --branch <branch> --workflow "CI - Run Tests".generaltranslation/content) has no Greptile and no Bugbot; a score there cannot be reached.gh pr edit <n> --add-reviewer <login>) so Linear notifies them through its Slack app; review requests in Slack stopped with the team announcement of 2026-09-08. Kevin chooses who reviews, so ask him first; APPROVAL_POLICY.md is the routing table.Stack PRs that share files, so the same conflicts are resolved once: the 2026-10-05 dashboard PRs shared up to 37 files with each other.
Stacked on #<n>. Merge that first.github/gh-stack extension from any checkout whose origin is gt-cloud:sh gh stack link --base main <bottom> <next> <top> # PR numbers, bottom first gh stack link <stack-number> <pr> # adds a PR to the top of a stack gh stack merge <stack-number | pr-number> # merges every PR up to that one, all or nothing
Pass PR numbers for PRs that exist: a branch argument is pushed first and gets a new PR if it has none. A native stack merges atomically, so it needs no restack between merges. gh stack merge asks for confirmation only in an interactive terminal; from an agent's shell it merges at once, so run it only when Kevin says to merge (section 5).
git log --oneline <old base>..<branch>), move them with git rebase --onto <branch below> <old base point> <branch>, or merge the branch below when the branch holds someone else's commits. On a conflict, keep everything the lower PR has and re-apply the upper PR's intent; record each conflict in the commit or merge message. Then check git range-diff <old base>..<old head> <new base>..<new head> and that gh pr diff <n> --name-only lists only the PR's own files. Push with a lease and set the base with gh pr edit <n> --base <branch below>.git rebase --onto origin/main <old bottom head> <branch> and push with a lease. Where a branch has others' commits, merge origin/main into it instead (conflicts land in files the stack changed; keep the branch's version when it is the base's final tree plus additions), then merge it down the rest of the stack in order. When main brought a lockfile change, run pnpm install and build the dependencies before type checking.bugbot run."i also really really want to emphasize that we need the new onboarding to keep all the tracking and backend stuff that the old onboarding did" (Kevin, 2026-10-02). Parity with production is a release gate for any onboarding or auth redesign.
origin/main worktree, replay the same scenarios on the release, and diff the two ledgers. Re-run the diff after every fix: the first audit of #5063 called the organization audit event preserved, and a later fix dropped projectId from its scope. A reviewer's list of intended changes is not evidence.k/onboarding-parity-suite and in the scratchpad (section 3).$PROTOTEMPLATE is shared by several sessions. The dev server runs at http://localhost:3005 (launch config prototemplate-dev) with hot reload; reuse it and never stop it.git fetch origin main and git log --oneline HEAD..origin/main. Other sessions push main from their own worktrees; bring their commits in first. Sweep for conflict markers and stop on any hit: grep -rln '^<<<<<<< ' src docs deck scripts skills. Kevin's own GitHub Desktop operations left markers in a shared tree mid-round on 2026-08-07.prototemplate section 9 (tsc, pnpm lint:all, check:pages on the touched pages, both themes at 1440 and 390, the build). What each gate checks is in gt-lints..next, so never build there:sh git -C $PROTOTEMPLATE worktree add --detach <scratch>/proto-build HEAD # copy in the uncommitted files the change needs, path by path cd <scratch>/proto-build pnpm install --frozen-lockfile --prefer-offline pnpm build > <scratch>/proto-build.log 2>&1 && echo BUILD_OK || tail -40 <scratch>/proto-build.log
pnpm build runs the picture lint before next build. The gate is &&: a ; pushed a broken build to main on 2026-08-07, and pnpm build | tail did it again on 2026-08-11, because a pipeline's exit status is the last command's. next start can serve a stale .next after a rebuild; delete .next in the scratch tree before diagnosing. Remove the scratch worktree afterwards. gt-lints section 5 holds the same gate hygiene for every gated command.
src/, public/, docs/, deck/, scripts/, skills/) and a pathspec. motion/ is never staged.general-translation/prototemplate (www.prototemplate.com) and Kevin's personal project (prototemplate.vercel.app), each with a Production deployment for main and a Preview for any other branch. A red "push failed" can come from any of the four. GitHub shows one deployment per commit with one status per project: the team's URL ends in -general-translation.vercel.app, the personal one's in -kl01s-projects.vercel.app.sh sha=$(git rev-parse HEAD) gh api "repos/Kevin-Liu-01/Prototemplate/deployments?sha=$sha" --jq '.[] | "\(.id) \(.environment)"' gh api repos/Kevin-Liu-01/Prototemplate/deployments/<id>/statuses --jq '.[] | "\(.state) \(.environment_url)"' curl -s https://www.prototemplate.com/ | grep -oE 'dpl_[A-Za-z0-9]+' | sort -u vercel inspect <the -general-translation.vercel.app url> --scope general-translation
The chunk URLs on www carry ?dpl=<deployment id>. The longest id the grep prints must equal the id that vercel inspect prints for the team deployment of your commit, and that deployment's Aliases list https://www.prototemplate.com. vercel inspect has kept running after printing; stop it once the id is out. Check www.prototemplate.com itself: the personal alias belongs to the other project and can serve a different build.
vercel ls, and vercel api /v13/deployments/<id> --scope general-translation gives readyStateReason and errorMessage. Retry a flaky preview with vercel redeploy <failed url> --scope general-translation, which posts fresh statuses. An empty commit is never the retry. Google faces are self hosted under public/fonts/google because Turbopack's Google loader failed builds at random (vercel/next.js#99114); a new face goes into the WANT table of scripts/fetch-google-faces.py and loads through next/font/local. If a team build reports "Only repositories in github.com/generaltranslation are allowed", the git-source policy that froze the site from 2026-09-01 to mid-September is back; tell Kevin.vercel --prod on the team scope unless Kevin says so.motion/ in Prototemplate).git branch --show-current equals the PR's headRefName, and after the push headRefOid equals HEAD.git status read before and after.origin/main.pr-size.mjs read and every large group justified; no fixtures, harnesses, galleries or planning Markdown in the diff.feat PR is linked to a Linear issue.pr-assets, Checks with counts, bot blocks byte for byte.pr-bots.mjs exits 0 (Greptile 5/5 on the head, no open bot thread, no conflict, required checks green) and lists no unanswered bot thread; the cancelled CI runs on the branch were read.references/beyond-the-pr.md).lint:all and check:pages pass; the build gate passed with && in a scratch worktree; deployment statuses green; www's dpl stamp equals the team deployment.Prototemplate: gt-voice (commit and PR prose), gt-lints (the gates in both repositories), gt-graphics (capture recipes for PR screenshots), gt-reporting (the PR slate), gt-verify (done means deployed), prototemplate (the repository and its viewer). Wiki: agent-iteration-loop (the general implement, verify, review loop), agent-browser, linear, split-to-prs, resolving-merge-conflicts, gh-address-comments. gt-cloud: pr-desc, gt-testing.
lint); .github/CODEOWNERS; APPROVAL_POLICY.md.pr-assets branch; PRs #4703, #4707, #4815, #5021, #5029, #5054, #5063, #5095 and #5133 (bodies, commit authors, check runs); the github/gh-stack v0.2.0 help for link and merge.build, lint:all, check:pages); scripts/lint-lines.mjs and scripts/pagecheck/pagecheck.mjs (the 3005 default); public/fonts/google/README.md; GitHub deployments of Kevin-Liu-01/Prototemplate, vercel inspect of the team deployment and www.prototemplate.com, read 2026-10-05.~/repos/Kevin-Wiki, live copy ~/repos/Kevin-Wiki-v3): skills/productivity/agent-iteration-loop/SKILL.md.The folder skills/gt-ship as agents fetch it. Each file opens raw.
SKILL.mdreferences/beyond-the-pr.mdreferences/pr-body.mdreferences/review-loop.mdscripts/pr-bots.mjsscripts/pr-size.mjs