From d1aaa7a094175db68d6ce1406d6f6cc3bdebb84c Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Wed, 29 Jul 2026 16:56:22 -0400 Subject: [PATCH] docs(agents): capture the fork's upstream sync workflow as a skill The sync workflow existed only as git history patterns, so every sync re-derived the same guardrails from scratch. Encoding them as a skill makes each sync repeatable and protects the fork's divergences, migration id blocks, and merge-based history from being regressed by an uninformed merge. Signed-off-by: Yordis Prieto --- .../skills/trogonstack-sync-upstream/SKILL.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 .agents/skills/trogonstack-sync-upstream/SKILL.md diff --git a/.agents/skills/trogonstack-sync-upstream/SKILL.md b/.agents/skills/trogonstack-sync-upstream/SKILL.md new file mode 100644 index 00000000000..6b2a3abc771 --- /dev/null +++ b/.agents/skills/trogonstack-sync-upstream/SKILL.md @@ -0,0 +1,65 @@ +--- +name: trogonstack-sync-upstream +description: Merge the latest pingdotgg/t3code upstream main into this TrogonStack fork while preserving the fork's tracked divergences, fork-only migrations, and merge-based sync history. Use when asked to sync, upgrade, update, or catch up the fork with upstream, or to pull in the latest upstream changes. +--- + +# Sync with upstream + +This fork tracks [pingdotgg/t3code](https://github.com/pingdotgg/t3code) as the `upstream` remote and carries a small set of intentional divergences. Syncing is always a **merge**, never a rebase: rebasing would rewrite fork history and break the shared migration tracker and published PR references. + +## 1. Prepare + +1. Start from a clean working tree on `main` with `origin/main` up to date. +2. Fetch upstream: `git fetch upstream`. +3. If `git log --oneline main..upstream/main` is empty, the fork is already current; stop and report that. +4. Load the divergence context before touching any conflict: + - Read `docs/fork/README.md` and every active ledger entry in `docs/fork/`. These are the features the merge must not regress. + - List fork-only commits: `git log --oneline upstream/main..main`. + +## 2. Create the sync branch + +``` +git switch -c yordis/chore-sync-upstream-{YYYYMMDD}-{NUM} main +git merge upstream/main +``` + +Use today's date for `{YYYYMMDD}` and a sequence number for `{NUM}`, starting at `1` and incrementing for each additional sync the same day (e.g. `yordis/chore-sync-upstream-20260729-1`). Check `git branch --list --all 'yordis/chore-sync-upstream-*'` to pick the next free number. + +## 3. Resolve conflicts + +Default to upstream's shape and re-apply the fork's intent on top of it. Concretely: + +- If the conflicting area belongs to a ledger divergence, keep the fork behavior and adapt it to upstream's new structure. Do not silently drop a divergence. +- If the fork's version of something is a superset of what upstream added, keep the fork's version and skip the redundant upstream piece (this happened in PR #9 with bootstrap-dispatch logic already covered by the fork's `ThreadBootstrapService`). +- If upstream merged an equivalent of a fork divergence, take upstream's version and delete the corresponding ledger entry outright (numbers are never reused; git history is the record). +- Everything else: take upstream. +- For conflicts under `.repos/` (vendored subtrees), do not hand-merge; take either side to complete the merge, then regenerate with `vpr sync:repos` (or `vpr sync:repos --repo `) so `.repos/` matches the installed dependency versions. + +Record every nontrivial resolution decision as you go; each one becomes a PR body bullet. + +### Migration rules (apps/server/src/persistence) + +- Fork-only migrations live in `apps/server/src/persistence/Migrations/fork/` and use ids >= 1000, a block upstream never grows into. Id `33` (ProjectionThreadParent) predates this convention and is grandfathered. +- Never renumber a migration id that has already shipped on this fork, even if upstream independently reuses that id. The migrator only remembers the highest id that ran, so reassigning a shipped id makes installs silently skip it. Slot incoming upstream migrations around what already shipped instead. +- After resolving `Migrations.ts`, run the fail-fast guard: `vp test run apps/server/src/persistence/Migrations.test.ts`. It rejects fork migrations outside their reserved id block. + +## 4. Verify + +A sync's blast radius is the whole repo, so this is the one workflow where full-suite local verification is expected (matching prior sync PRs): + +``` +vp run -r --concurrency-limit 2 typecheck +vp run -r test +vp lint --report-unused-disable-directives +``` + +Fix fallout on the sync branch before opening the PR. If upstream bumped a dependency that has a vendored subtree, confirm `.repos/` was synced in the same change. + +## 5. Open and merge the PR + +1. Commit with DCO sign-off (`git commit -s`). Conflict resolutions belong in the merge commit; follow-up fixes go in separate conventional commits on the branch. +2. Push the branch and open a PR against `main`: + - Title: `chore: sync with upstream pingdotgg/t3code main` + - Body: bullets only, each explaining the why of a nontrivial resolution decision (what was kept, dropped, or renumbered, and why). No file lists, no test plan section. +3. Merge the PR with a **merge commit**, never squash. Squashing would drop the `upstream/main` merge parent, so the next sync would re-conflict on everything already resolved. +4. Share the PR link, then delete the sync branch.