Skip to content

Commit 92b09c0

Browse files
author
Zeph Gillen
committed
docs(fork): add FORK.md upstream-merge friction map
Capture the fork's divergence from upstream in one reference so the conflict-prone code paths are clear on every sync. - FORK.md: divergence-at-a-glance + per-feature friction tables keyed by the actual fork file changes (git log --no-merges upstream/main.. local/daily-driver), with a conflict-risk column grounded in real upstream churn (6-month commit counts per file), fork-only vs modified split, recurring release-mechanics conflicts, a post-merge checklist, and the commands to regenerate the map. - AGENTS.md: trim "Local fork status" to a pointer at FORK.md; relocate the operational nuggets (pnpm vsix --force rebuild, 22-failure test baseline, per-provider reasoning guards) into FORK.md so nothing is lost. FORK.md is a file upstream doesn't have, so it never conflicts on merge — unlike AGENTS.md, which upstream actively edits.
1 parent 151590f commit 92b09c0

2 files changed

Lines changed: 143 additions & 26 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,9 @@ This file provides guidance to agents when working with code in this repository.
44

55
## Local fork status
66

7-
This repo is a long-running fork of [`Zoo-Code-Org/Zoo-Code`](https://github.com/Zoo-Code-Org/Zoo-Code) (git remote `upstream`). Day-to-day work happens on `local/daily-driver`; upstream tags are merged in on `local/merge-upstream-vX.Y.Z` branches and then fast-forwarded into `local/daily-driver`. The local-only architectural changes below are intentional and must be preserved across upstream merges.
7+
This repo is a long-running fork of [`Zoo-Code-Org/Zoo-Code`](https://github.com/Zoo-Code-Org/Zoo-Code) (git remote `upstream`). Day-to-day work happens on `local/daily-driver`; upstream tags are merged in on `local/merge-upstream-vX.Y.Z` branches and then fast-forwarded into `local/daily-driver`.
88

9-
After bumping the version in `src/package.json` (e.g. during an upstream merge), rebuild with `pnpm vsix --force` — turbo's cache does not track `src/package.json` as an input for the webview build, so the webview bundle will otherwise keep the old version inlined.
10-
11-
### Effort-based Anthropic reasoning (local-only architecture)
12-
13-
Anthropic Opus 4.6 / 4.7 / 4.8 use Anthropic's adaptive-thinking API with `output_config.effort`, not the legacy `budget_tokens` / binary toggle. The fork's static registry shape for these models is the contract that drives the request payload:
14-
15-
- `packages/types/src/providers/anthropic.ts` — Opus 4.6 / 4.7 / 4.8 declare `supportsReasoningEffort: [...]` (with `xhigh` only on 4.7 and 4.8 per Anthropic docs), `requiredReasoningEffort: true`, and `supportsTemperature: false`. They do NOT declare `supportsReasoningBudget`.
16-
- `src/api/transform/reasoning.ts``getAnthropicReasoning` branches on `supportsReasoningEffort && !supportsReasoningBudget` and emits `{ thinking: { type: "adaptive" }, output_config: { effort } }`. Anything that re-declares `supportsReasoningBudget` on these models drops them onto the legacy budget path, which Opus 4.7+ rejects with a 400.
17-
- `src/api/providers/anthropic.ts` and `src/api/providers/anthropic-vertex.ts` — destructure `reasoning?.thinking` and `reasoning?.output_config` from `getModel()` and spread both into the request. `getModelParams({ format: "anthropic" })` already wires reasoning; do NOT add a redundant `getAnthropicProviderReasoning` call.
18-
19-
Provider-specific notes:
20-
21-
- **Vertex** has no provider-side adaptive-thinking guard. The registry shape alone decides the payload. Opus 4.8 has been converted to the effort shape; **Opus 4.7 / 4.6 still declare `supportsReasoningBudget` and will 400 on the live API for 4.7 — known follow-up from `fd93c5bde`.** Do not "fix" the Bedrock-style mismatch by reintroducing the budget shape on Vertex 4.8.
22-
- **Bedrock** has its own `isAdaptiveThinkingModel(modelId)` guard in `src/api/providers/bedrock.ts` that overrides the request payload regardless of the registry shape (matches `opus-4-7`, `opus-4-8`, `sonnet-4-7`, `sonnet-4-8` after `parseBaseModelId`). The bedrock registry entries declare the upstream-style `supportsReasoningBudget` shape — that is intentional and correct here.
23-
- **OpenRouter** uses a dynamic model fetcher that reports `supportsReasoningEffort` as a boolean. The fetcher (`src/api/providers/fetchers/openrouter.ts`) patches known IDs (`anthropic/claude-opus-4.7`, `anthropic/claude-opus-4.8`, OpenAI gpt-5.5 family) to mirror the static effort arrays so `xhigh` / `max` remain reachable from the UI.
24-
25-
When adding a new effort-capable model, mirror the existing 4.7 / 4.8 entries and add a parametrized test in `src/api/providers/__tests__/anthropic.spec.ts` (effort assertion, `requiredReasoningEffort` always-on, user-chosen effort) rather than the upstream-style budget/binary assertions.
26-
27-
### Workspace-scoped code-index config (local-only)
28-
29-
`src/services/code-index/` has been extended with a two-scope config model: global (extension settings) plus a per-project `.roo/codebase-index.json` dotfile. Project scope overrides global; secrets are reconciled through `config-resolver.ts` and a file watcher reloads on dotfile changes. The published JSON Schema is at `packages/types/schemas/codebase-index.schema.json`; the UI surfaces the active scope and a "pinned-by-dotfile" badge. Keep the schema, the resolver tests, and the dotfile loader in sync when changing the shape.
30-
31-
### Known pre-existing test failures
32-
33-
`pnpm -w test` reports 22 failures on `local/daily-driver` from fixture drift introduced by `fd93c5bde`, all in `src/api/transform/__tests__/reasoning.spec.ts` and `src/api/transform/__tests__/model-params.spec.ts`. They predate every recent upstream merge. A clean validation pass on this fork = exactly those 22 failures and nothing else; a 23rd is the regression to investigate.
9+
**Before an upstream sync, read [`FORK.md`](FORK.md).** It is the single record of the local-only changes — they are intentional and must be preserved across merges — and maps each one to the files it touches, rates upstream-merge conflict risk (grounded in real upstream churn), and carries the post-merge checklist: the `pnpm vsix --force` rebuild after a version bump, the known 22-failure test baseline (fixture drift from `fd93c5bde`), the effort-based Anthropic reasoning contract, and the per-provider (Vertex / Bedrock / OpenRouter) reasoning guards.
3410

3511
## Conventions
3612

FORK.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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

Comments
 (0)