|
| 1 | +# FORK.md — local divergence & upstream-merge friction map |
| 2 | + |
| 3 | +This repo is a long-running fork of [`Zoo-Code-Org/Zoo-Code`](https://github.com/Zoo-Code-Org/Zoo-Code) |
| 4 | +(git remote `upstream`). Day-to-day work happens on `local/daily-driver`; upstream tags are |
| 5 | +merged in on `local/merge-upstream-vX.Y.Z` branches and then fast-forwarded into |
| 6 | +`local/daily-driver`. |
| 7 | + |
| 8 | +This document is the single reference for **what we changed and where it will rub against |
| 9 | +upstream on the next sync**. The local-only changes below are intentional and must be preserved |
| 10 | +across merges. `AGENTS.md` only points here. |
| 11 | + |
| 12 | +## How to use this during an upstream sync |
| 13 | + |
| 14 | +1. Merge the upstream tag onto a `local/merge-upstream-vX.Y.Z` branch. |
| 15 | +2. Resolve conflicts feature-by-feature using the tables below — the **conflict-prone** files are |
| 16 | + where merge markers land; the **fork-only** files won't conflict textually but may need |
| 17 | + re-wiring if upstream restructured the surrounding code. |
| 18 | +3. Run the [post-merge checklist](#post-merge-checklist). |
| 19 | +4. Fast-forward `local/daily-driver`. |
| 20 | + |
| 21 | +> **Limitation:** the file lists here come from our fork's *non-merge* commits |
| 22 | +> (`git log --no-merges upstream/main..local/daily-driver`). Conflicts that were already resolved |
| 23 | +> *inside* past merge commits are not captured. When a new area starts conflicting, add a row. |
| 24 | +
|
| 25 | +## Divergence at a glance |
| 26 | + |
| 27 | +| # | Local feature | Origin commit(s) | Nature | |
| 28 | +|---|---|---|---| |
| 29 | +| 1 | Effort-based Anthropic reasoning (Opus 4.6/4.7/4.8) | `fd93c5bde`, `64fc5fc98` | modifies shared provider logic | |
| 30 | +| 2 | OpenRouter effort-array mirroring + gpt-5.5 defs | `062657a7d`, `64fc5fc98` | modifies shared fetcher/registry | |
| 31 | +| 3 | Claude Fable 5 + safety-refusal handling | `811b5ca55` | modifies shared provider logic | |
| 32 | +| 4 | `"max"` reasoningEffort i18n label | `dd675fd3b` | mechanical i18n | |
| 33 | +| 5 | Workspace-scoped code-index config (`.roo/codebase-index.json`) | `3efa0728e`→`8f54e2274` (phases 1–5) | mostly new files + isolated wiring | |
| 34 | + |
| 35 | +## Conflict-prone code paths (shared files we modified) |
| 36 | + |
| 37 | +Risk = **upstream churn** (commits touching the file on `upstream/main` in the last 6 months) × |
| 38 | +**change nature** (isolated additive wiring merges cleanly; changes to shared *logic* conflict |
| 39 | +hard). High churn with an isolated add is usually a clean 3-way merge; low churn on keystone logic |
| 40 | +can still be the ugliest conflict. |
| 41 | + |
| 42 | +### Feature 1+3 — Anthropic reasoning + Fable |
| 43 | + |
| 44 | +| File | Upstream churn (6mo) | Our change | Change nature | Risk | |
| 45 | +|---|---:|---|---|---| |
| 46 | +| `packages/types/src/providers/anthropic.ts` | 10 | Effort-shape model entries (Opus 4.6/4.7/4.8, Fable 5): `supportsReasoningEffort`, `requiredReasoningEffort`, `supportsTemperature:false`, **no** `supportsReasoningBudget` | modifies contract registry | **HIGH** (this shape drives the request payload) | |
| 47 | +| `src/api/transform/reasoning.ts` | 5 | `getAnthropicReasoning` branch on `supportsReasoningEffort && !supportsReasoningBudget` → `{ thinking:{type:"adaptive"}, output_config:{effort} }` | keystone logic | **HIGH** (low churn but ugliest if upstream refactors reasoning extraction) | |
| 48 | +| `src/api/providers/anthropic.ts` | 23 | Spread `reasoning.thinking` + `reasoning.output_config` into request; Fable `stop_reason:"refusal"` → category-aware text chunk | modifies shared logic | **HIGH** | |
| 49 | +| `src/api/providers/anthropic-vertex.ts` | 17 | Destructure + spread `reasoning.thinking`/`output_config`; no provider-side adaptive guard (registry shape alone decides payload) | modifies shared logic | **MED** | |
| 50 | +| `packages/types/src/provider-settings.ts` | 17 | Effort field/enum plumbing | modifies shared types | **MED** | |
| 51 | +| `src/shared/api.ts` | 12 | Effort plumbing | modifies shared types | **MED** | |
| 52 | +| `packages/types/src/model.ts` | 4 | Effort type support | modifies shared types | **LOW–MED** | |
| 53 | + |
| 54 | +**Provider guards to preserve (semantic, easy to break on merge):** |
| 55 | +- **Vertex** has *no* provider-side adaptive-thinking guard — the registry shape alone decides the |
| 56 | + payload. Opus 4.8 is on the effort shape; **Opus 4.7/4.6 still declare `supportsReasoningBudget` |
| 57 | + and will 400 on the live API for 4.7 — known follow-up from `fd93c5bde`.** Do not "fix" this by |
| 58 | + reintroducing the budget shape on Vertex 4.8. |
| 59 | +- **Bedrock** has its own `isAdaptiveThinkingModel(modelId)` guard in |
| 60 | + `src/api/providers/bedrock.ts` (matches `opus-4-7`, `opus-4-8`, `sonnet-4-7`, `sonnet-4-8` after |
| 61 | + `parseBaseModelId`) that overrides the payload regardless of registry shape. Bedrock registry |
| 62 | + entries keep the upstream-style `supportsReasoningBudget` shape — intentional and correct there. |
| 63 | +- Anything that re-declares `supportsReasoningBudget` on the effort models drops them onto the |
| 64 | + legacy budget path, which Opus 4.7+ rejects with a 400. |
| 65 | + |
| 66 | +When adding a new effort-capable model, mirror the existing 4.7/4.8 entries and add a parametrized |
| 67 | +test in `src/api/providers/__tests__/anthropic.spec.ts` (effort assertion, `requiredReasoningEffort` |
| 68 | +always-on, user-chosen effort) rather than upstream-style budget/binary assertions. |
| 69 | + |
| 70 | +### Feature 2 — OpenRouter / OpenAI effort |
| 71 | + |
| 72 | +| File | Upstream churn (6mo) | Our change | Change nature | Risk | |
| 73 | +|---|---:|---|---|---| |
| 74 | +| `packages/types/src/providers/openai.ts` | 8 | gpt-5.5 defs + static effort arrays | modifies registry | **MED** | |
| 75 | +| `src/api/providers/fetchers/openrouter.ts` | 6 | Dynamic fetcher patches known IDs (`anthropic/claude-opus-4.7`, `anthropic/claude-opus-4.8`, gpt-5.5 family) to mirror the static effort arrays so `xhigh`/`max` stay reachable from the UI | modifies shared fetcher | **MED** | |
| 76 | + |
| 77 | +### Feature 5 — Workspace-scoped code-index (modified shared files) |
| 78 | + |
| 79 | +| File | Upstream churn (6mo) | Our change | Change nature | Risk | |
| 80 | +|---|---:|---|---|---| |
| 81 | +| `src/core/webview/ClineProvider.ts` | 81 | Wire code-index scope | isolated additive | **MED** (high churn, but additive — usually clean 3-way) | |
| 82 | +| `src/core/webview/webviewMessageHandler.ts` | 59 | Code-index scope message handlers | isolated additive | **MED** | |
| 83 | +| `packages/types/src/vscode-extension-host.ts` | 52 | Code-index host type | isolated additive | **MED** | |
| 84 | +| `webview-ui/src/components/chat/CodeIndexPopover.tsx` | 2 | Scope switcher + pinned-by-dotfile badge | UI additive | **LOW–MED** | |
| 85 | +| `src/services/code-index/manager.ts` | 2 | Two-scope wiring | our changes dominate | **LOW–MED** | |
| 86 | +| `src/services/code-index/config-manager.ts` | 1 | Two-scope config model | our changes dominate | **LOW** | |
| 87 | +| `packages/types/src/codebase-index.ts` | 1 | Config shape/types | our changes dominate | **LOW** | |
| 88 | + |
| 89 | +### i18n |
| 90 | + |
| 91 | +| Files | Our change | Risk | |
| 92 | +|---|---|---| |
| 93 | +| `webview-ui/src/i18n/locales/*/settings.json` (18 locales) | `"max"` reasoningEffort label + code-index scope strings | **MED** — frequent but mechanical; resolve by taking both sides / regenerating | |
| 94 | + |
| 95 | +## Fork-only files (added — no textual conflict, watch for semantic drift) |
| 96 | + |
| 97 | +These don't exist upstream, so they never produce merge markers. The risk is *drift*: if upstream |
| 98 | +restructures the code-index service or the types package, these need re-wiring, not merging. |
| 99 | + |
| 100 | +- `packages/types/schemas/codebase-index.schema.json` — published JSON Schema for the dotfile |
| 101 | +- `packages/types/src/__tests__/codebase-index.test.ts` |
| 102 | +- `src/services/code-index/config-resolver.ts` (+ `__tests__/config-resolver.spec.ts`) — reconciles |
| 103 | + global (extension settings) vs project (`.roo/codebase-index.json`) scope; secrets resolved here |
| 104 | +- `src/services/code-index/dotfile-loader.ts` (+ `__tests__/dotfile-loader.spec.ts`) — loads the |
| 105 | + dotfile and watches it for reloads |
| 106 | + |
| 107 | +Keep the schema, the resolver tests, and the dotfile loader in sync when the config shape changes. |
| 108 | + |
| 109 | +## Recurring / expected conflicts (release mechanics) |
| 110 | + |
| 111 | +These conflict on essentially **every** upstream merge and are expected — resolve mechanically, |
| 112 | +don't investigate them as regressions. |
| 113 | + |
| 114 | +- `src/package.json` — version string → re-bump (see checklist re: VSIX) |
| 115 | +- `CHANGELOG.md` — take the union; keep our fork entries |
| 116 | +- `README.md`, `locales/*/README.md`, `webview-ui/src/i18n/locales/*/chat.json` — release/marketing churn |
| 117 | +- `AGENTS.md` — now just a pointer paragraph, so the footprint is small |
| 118 | + |
| 119 | +## Post-merge checklist |
| 120 | + |
| 121 | +- [ ] **Rebuild VSIX after any `src/package.json` version bump:** `pnpm vsix --force`. Turbo's cache |
| 122 | + does not track `src/package.json` as an input for the webview build, so the webview bundle |
| 123 | + otherwise keeps the old version inlined. |
| 124 | +- [ ] **Test baseline:** `pnpm -w test` reports **exactly 22 failures** on `local/daily-driver`, |
| 125 | + all in `src/api/transform/__tests__/reasoning.spec.ts` and |
| 126 | + `src/api/transform/__tests__/model-params.spec.ts` (fixture drift from `fd93c5bde`, predates |
| 127 | + every recent merge). A clean run = those 22 and nothing else; a 23rd is the regression to |
| 128 | + investigate. |
| 129 | +- [ ] Verify the Anthropic effort payload still emits `output_config.effort` (not `budget_tokens`) |
| 130 | + for Opus 4.7/4.8 — see the provider guards above. |
| 131 | + |
| 132 | +## Regenerate this map |
| 133 | + |
| 134 | +```bash |
| 135 | +# Files our fork's non-merge commits touch (the divergence set): |
| 136 | +git log --no-merges --name-status \ |
| 137 | + --pretty=format:'>>> %h | %an | %s' upstream/main..local/daily-driver |
| 138 | + |
| 139 | +# Upstream churn (6mo) for a given file — feeds the risk column: |
| 140 | +git log --oneline --since='6 months ago' upstream/main -- <path> | wc -l |
| 141 | +``` |
0 commit comments