Skip to content

Commit 8fb542f

Browse files
anandgupta42claude
andcommitted
feat: add upstream merge automation tooling
Comprehensive automation for merging upstream OpenCode releases into the Altimate Code fork, inspired by Kilo-Org/kilocode's approach. Key scripts: - `merge.ts` — 11-step merge orchestration with auto-conflict resolution, branding transforms, version preservation, and `--continue` support - `analyze.ts` — `altimate_change` marker integrity audit + branding leak detection (CI-friendly exit codes) - `list-versions.ts` — upstream tag listing with merge status indicators - `verify-restructure.ts` — branch comparison verification Transforms (10 files): - Core branding engine with preservation-aware product name handling - `keepOurs` / `skipFiles` / lock file conflict auto-resolution - Specialized transforms for `package.json`, Nix, Tauri, i18n, extensions, web docs, workflows, and build scripts Configuration: - All branding rules in TypeScript (`utils/config.ts`) for type safety - URL, GitHub, registry, email, app ID, social, npm, brew mappings - Preserve patterns protect internal refs (`@opencode-ai/`, `OPENCODE_`) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c4f6a62 commit 8fb542f

25 files changed

Lines changed: 4495 additions & 273 deletions

script/upstream/README.md

Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
# Upstream Merge Automation
2+
3+
Tools for merging upstream [OpenCode](https://github.com/anomalyco/opencode) releases into the Altimate Code fork with automatic conflict resolution, branding transforms, and version management.
4+
5+
## Quick Start
6+
7+
```bash
8+
# 1. See what upstream versions are available
9+
bun run script/upstream/list-versions.ts
10+
11+
# 2. Analyze what would change (dry-run, no modifications)
12+
bun run script/upstream/merge.ts --version v1.2.21 --dry-run
13+
14+
# 3. Run the full merge
15+
bun run script/upstream/merge.ts --version v1.2.21
16+
17+
# 4. If conflicts need manual resolution, fix them, then:
18+
git add <resolved-files>
19+
bun run script/upstream/merge.ts --continue
20+
21+
# 5. Verify no upstream branding leaked through
22+
bun run script/upstream/analyze.ts --branding
23+
```
24+
25+
## Full Merge Process
26+
27+
The merge script automates an 11-step process:
28+
29+
```
30+
Step Description Details
31+
──── ───────────────────────────── ────────────────────────────────────────
32+
1 Validate environment Clean tree, upstream remote, fetch tags
33+
2 Snapshot package versions Save our name/version before merge
34+
3 Create branches Backup branch + merge branch
35+
4 Merge upstream git merge <tag> --no-edit
36+
5 Auto-resolve conflicts keepOurs, skipFiles, lock files, binaries
37+
6 Report remaining conflicts List files needing manual resolution
38+
7 Apply branding transforms URL, GitHub, product name replacements
39+
8 Restore package versions Revert upstream version bumps
40+
9 Commit branding changes Separate commit for traceability
41+
10 Verify branding integrity Scan for upstream branding leaks
42+
11 Push & finalize Push merge branch, print PR command
43+
```
44+
45+
If step 6 finds unresolvable conflicts, the script exits with instructions.
46+
After manual resolution, run `--continue` to resume from step 7.
47+
48+
## Available Scripts
49+
50+
### `merge.ts` — Main Merge Orchestration
51+
52+
The primary entry point for merging upstream releases.
53+
54+
```bash
55+
# Standard merge
56+
bun run script/upstream/merge.ts --version v1.2.21
57+
58+
# Dry-run analysis (no changes to repo)
59+
bun run script/upstream/merge.ts --version v1.2.21 --dry-run
60+
61+
# Merge without pushing to origin
62+
bun run script/upstream/merge.ts --version v1.2.21 --no-push
63+
64+
# Merge a specific commit instead of a tag
65+
bun run script/upstream/merge.ts --commit abc123def
66+
67+
# Resume after resolving conflicts
68+
bun run script/upstream/merge.ts --continue
69+
```
70+
71+
**Options:**
72+
73+
| Flag | Description |
74+
|------|-------------|
75+
| `--version, -v <tag>` | Upstream version tag to merge |
76+
| `--commit, -c <sha>` | Merge a specific commit instead |
77+
| `--base-branch <name>` | Branch to merge into (default: `main`) |
78+
| `--dry-run` | Preview changes without modifying the repo |
79+
| `--no-push` | Skip pushing the merge branch to origin |
80+
| `--continue` | Resume after manual conflict resolution |
81+
| `--author <name>` | Override merge commit author |
82+
| `--help, -h` | Show help |
83+
84+
**Branches created:**
85+
- `backup/<current-branch>-<timestamp>` — safety snapshot
86+
- `upstream/merge-<version>` — the merge working branch
87+
88+
### `analyze.ts` — Analysis & Verification
89+
90+
Two modes: version preview and branding audit.
91+
92+
```bash
93+
# Analyze what would change for a version
94+
bun run script/upstream/analyze.ts --version v1.2.21
95+
96+
# Audit codebase for upstream branding leaks
97+
bun run script/upstream/analyze.ts --branding
98+
99+
# Detailed audit showing all matches
100+
bun run script/upstream/analyze.ts --branding --verbose
101+
102+
# JSON output (for CI pipelines)
103+
bun run script/upstream/analyze.ts --branding --json
104+
105+
# Default: marker integrity analysis
106+
bun run script/upstream/analyze.ts
107+
```
108+
109+
**Exit codes (branding mode):**
110+
- `0` — No leaks found
111+
- `1` — Branding leaks detected (useful for CI gates)
112+
- `2` — Script error
113+
114+
### `list-versions.ts` — List Upstream Versions
115+
116+
Shows available upstream tags with merge status.
117+
118+
```bash
119+
# Show latest 30 versions
120+
bun run script/upstream/list-versions.ts
121+
122+
# Show more
123+
bun run script/upstream/list-versions.ts --limit 50
124+
125+
# Show all versions
126+
bun run script/upstream/list-versions.ts --all
127+
128+
# JSON output
129+
bun run script/upstream/list-versions.ts --json
130+
```
131+
132+
### `verify-restructure.ts` — Branch Verification
133+
134+
Compares custom code between branches to ensure nothing was lost during restructuring.
135+
136+
```bash
137+
bun run script/upstream/verify-restructure.ts
138+
bun run script/upstream/verify-restructure.ts --json
139+
```
140+
141+
## File Organization
142+
143+
```
144+
script/upstream/
145+
├── merge.ts # Main merge orchestration (entry point)
146+
├── analyze.ts # Version analysis & branding audit
147+
├── list-versions.ts # List upstream tags with merge status
148+
├── verify-restructure.ts # Branch comparison verification
149+
├── merge-config.json # Declarative config (legacy, see config.ts)
150+
├── package.json # Dependencies (minimatch)
151+
├── tsconfig.json # TypeScript configuration
152+
├── README.md # This file
153+
├── utils/
154+
│ ├── config.ts # Branding rules, merge config, repoRoot()
155+
│ ├── git.ts # Async git command helpers (Bun $)
156+
│ ├── logger.ts # Colored terminal logging with step counters
157+
│ └── report.ts # Transform report types, printing, JSON export
158+
└── transforms/
159+
├── keep-ours.ts # Resolve conflicts by keeping our version
160+
├── skip-files.ts # Resolve conflicts by accepting upstream
161+
└── lock-files.ts # Lock file resolution & regeneration
162+
```
163+
164+
## Configuration
165+
166+
All configuration lives in `utils/config.ts` as TypeScript for type safety and inline documentation.
167+
168+
### keepOurs — Files We Own
169+
170+
These files are always kept as-is during merges. Conflicts are auto-resolved by checking out our version.
171+
172+
| Pattern | Description |
173+
|---------|-------------|
174+
| `README.md`, `CONTRIBUTING.md`, etc. | Repository documentation |
175+
| `.github/workflows/**` | CI/CD pipelines |
176+
| `packages/altimate-engine/**` | Python engine (our code) |
177+
| `packages/opencode/src/altimate/**` | TypeScript custom code |
178+
| `packages/opencode/src/bridge/**` | Python-TS bridge |
179+
| `script/upstream/**` | This merge tooling |
180+
| `experiments/**`, `docs/**` | Research & documentation |
181+
182+
### Branding Rules
183+
184+
Ordered from most specific to least specific to prevent partial matches:
185+
186+
| Category | Example Transform |
187+
|----------|-------------------|
188+
| URL subdomains | `auth.dev.opencode.ai` -> `auth.dev.altimate.ai` |
189+
| Root domain | `opencode.ai` -> `altimate.ai` |
190+
| Short domain | `opncd.ai` -> `altimate.ai` |
191+
| GitHub repos | `anomalyco/opencode` -> `AltimateAI/altimate-code` |
192+
| Container registry | `ghcr.io/anomalyco` -> `ghcr.io/AltimateAI` |
193+
| Email addresses | `bot@opencode.ai` -> `bot@altimate.ai` |
194+
| App IDs | `ai.opencode.desktop` -> `ai.altimate.code.desktop` |
195+
| Product names | `OpenCode` -> `Altimate Code` |
196+
| Install commands | `npm i -g opencode-ai` -> `npm i -g @altimateai/altimate-code` |
197+
| Homebrew | `anomalyco/tap/opencode` -> `AltimateAI/tap/altimate-code` |
198+
199+
### Preserve Patterns
200+
201+
Lines containing these strings are excluded from branding transforms to prevent breaking internal references:
202+
203+
- `@opencode-ai/` — npm package scope (kept for upstream compatibility)
204+
- `OPENCODE_` — environment variables and feature flags
205+
- `.opencode/` — config directory path
206+
- `packages/opencode` — internal package path
207+
- `opencode.json` / `opencode.jsonc` — config file names
208+
- `window.__OPENCODE__` — runtime globals
209+
- `import { ` — import statements (would break code)
210+
211+
### Change Markers
212+
213+
Files in `packages/opencode/src/` that we've modified (but are not fully custom) use `altimate_change` markers to track our modifications:
214+
215+
```typescript
216+
// altimate_change start — description of what we changed
217+
... our modifications ...
218+
// altimate_change end
219+
```
220+
221+
These markers:
222+
- Help identify our changes during conflict resolution
223+
- Are audited by `analyze.ts` for integrity (unclosed blocks)
224+
- Guide reviewers to focus on our custom logic vs upstream code
225+
226+
## How to Add New Branding Rules
227+
228+
1. Open `utils/config.ts`
229+
2. Add your rule to the appropriate category array (e.g., `urlRules`, `githubRules`)
230+
3. Place more specific patterns BEFORE less specific ones
231+
4. Include a descriptive `description` field
232+
5. Test with: `bun run script/upstream/analyze.ts --branding`
233+
234+
Example:
235+
236+
```typescript
237+
// In the urlRules array:
238+
{
239+
pattern: /newservice\.opencode\.ai/g,
240+
replacement: "newservice.altimate.ai",
241+
description: "New service subdomain",
242+
},
243+
```
244+
245+
## Troubleshooting
246+
247+
### Merge fails with "working tree has uncommitted changes"
248+
249+
```bash
250+
# Option 1: Commit your changes
251+
git add -A && git commit -m "wip: save work before merge"
252+
253+
# Option 2: Stash your changes
254+
git stash
255+
bun run script/upstream/merge.ts --version v1.2.21
256+
git stash pop
257+
```
258+
259+
### Conflicts remain after auto-resolution
260+
261+
The script lists remaining conflicts and exits. Resolve them manually:
262+
263+
```bash
264+
# See what's still conflicted
265+
git diff --name-only --diff-filter=U
266+
267+
# Open a conflicted file, resolve the markers (<<<, ===, >>>)
268+
# Stage the resolved file
269+
git add <file>
270+
271+
# Resume the merge
272+
bun run script/upstream/merge.ts --continue
273+
```
274+
275+
### Branding leaks detected after merge
276+
277+
```bash
278+
# See all leaks with full detail
279+
bun run script/upstream/analyze.ts --branding --verbose
280+
281+
# Some leaks are false positives (preserved patterns in new contexts)
282+
# To fix real leaks: add a new branding rule or preserve pattern in config.ts
283+
```
284+
285+
### Upstream remote not found
286+
287+
```bash
288+
git remote add upstream https://github.com/anomalyco/opencode.git
289+
git fetch upstream --tags
290+
```
291+
292+
The merge script will auto-add the remote if missing.
293+
294+
### Aborting a merge in progress
295+
296+
```bash
297+
# Abort the git merge
298+
git merge --abort
299+
300+
# Switch back to your original branch
301+
git checkout main
302+
303+
# Delete the merge branch
304+
git branch -D upstream/merge-v1.2.21
305+
```
306+
307+
### Recovering from a failed merge
308+
309+
The script creates a backup branch before starting:
310+
311+
```bash
312+
# Find your backup branch
313+
git branch | grep backup/
314+
315+
# Restore from backup
316+
git checkout main
317+
git reset --hard backup/main-2026-03-14T10-30-00
318+
```
319+
320+
### State file left behind
321+
322+
If a merge was interrupted, a `.upstream-merge-state.json` file may remain in the repo root. It is safe to delete:
323+
324+
```bash
325+
rm .upstream-merge-state.json
326+
```
327+
328+
## CI Integration
329+
330+
The branding audit can be used as a CI gate:
331+
332+
```yaml
333+
# .github/workflows/branding-check.yml
334+
- name: Check for branding leaks
335+
run: bun run script/upstream/analyze.ts --branding --json
336+
```
337+
338+
Exit code 1 means leaks were found, which can block the PR.
339+
340+
## Setup
341+
342+
```bash
343+
# 1. Ensure upstream remote exists (auto-added by merge.ts if missing)
344+
git remote add upstream https://github.com/anomalyco/opencode.git
345+
346+
# 2. Install dependencies for the merge tooling
347+
cd script/upstream && bun install
348+
```
349+
350+
## Inspiration
351+
352+
This tooling was inspired by [Kilo-Org/kilocode](https://github.com/Kilo-Org/kilocode)'s upstream merge automation, adapted for Altimate Code's specific branding patterns and fork structure.

0 commit comments

Comments
 (0)