Problem
packages/coding-agent/src/internal-urls/docs-index.generated.ts is a committed generated file that inlines the entire body of each doc onto a single source line:
"models.md": "# Model and Provider Configuration (`models.yml`)\n\nThis document describes how the coding-agent currently loads models, ... <thousands of characters> ...",
Git merges line-by-line. One doc = one line, so two PRs that touch the same doc always produce a whole-line conflict with no usable three-way resolution — the conflict hunk is two multi-thousand-character strings. There is nothing to hand-merge; the only correct resolution is "take neither side, rerun the generator", which nobody can tell from the diff.
Impact (measured against dev @ 1f735b7bc6bb1fc62c782496f2e2ab9b02adec2a, 39 open PRs)
Test-merging every open PR into current dev with git merge-tree --write-tree:
Churn confirms it is not a docs-authoring problem: 31 commits touched this file in the last 30 days, including #3922, #3923, and #3924 — an ACP change and two AI/model changes. It is on the hot path of nearly every merge, so it re-conflicts every open PR each time dev moves.
Two amplifiers:
- Root
package.json has "prepare": "bun --cwd=packages/coding-agent run generate-docs-index", so a plain bun install rewrites the file. Contributors get a dirty tree they did not ask for and routinely commit it.
packages/coding-agent/scripts/generate-docs-index.ts walks docs/ from disk, so the output is a pure function of the docs tree — the committed copy carries zero information that cannot be recomputed.
Proposed fix
Ordered by cost, any one of these removes the conflict class:
- Stop committing it. Gitignore
docs-index.generated.ts, keep the prepare/prepack hooks that already produce it, and add a CI check that the working tree is clean after bun run generate-docs-index so a stale checked-in copy cannot come back. This is the smallest change and kills the conflict entirely.
- If it must stay committed, make it mergeable. Emit one line per paragraph (template literal or an array of chunks joined at load), so git can three-way merge normal doc edits. This shrinks but does not eliminate conflicts.
- Add a merge driver.
.gitattributes entry packages/coding-agent/src/internal-urls/docs-index.generated.ts merge=docs-index with a driver that discards both sides and reruns the generator. Correct, but every contributor has to install the driver locally, so it fails open.
Option 1 is the right one unless something consumes the file without a build step — src/internal-urls/gjc-protocol.ts imports it at runtime, so the packaging path (prepack) already covers publish.
Why this is worth fixing now
The repo runs an exact-head CI gate (git merge-base --is-ancestor "$GITHUB_BASE_SHA" HEAD in dev-ci.yml), so every PR must rebase onto current dev before merge. With a file that reliably conflicts on rebase, that gate multiplies against itself: each merge forces N rebases, and a share of those rebases hit an unresolvable generated-file conflict. That is the mechanism keeping the open-PR count where it is.
Note on the surrounding measurement
While collecting this I also found GitHub's mergeable field is badly stale on this repo: 24 open PRs report CONFLICTING/DIRTY, but 14 of them merge cleanly into current dev. Anyone triaging by the GitHub badge is chasing phantom conflicts. Worth knowing before acting on the numbers above — they come from local merge-tree, not from the API field.
Problem
packages/coding-agent/src/internal-urls/docs-index.generated.tsis a committed generated file that inlines the entire body of each doc onto a single source line:Git merges line-by-line. One doc = one line, so two PRs that touch the same doc always produce a whole-line conflict with no usable three-way resolution — the conflict hunk is two multi-thousand-character strings. There is nothing to hand-merge; the only correct resolution is "take neither side, rerun the generator", which nobody can tell from the diff.
Impact (measured against
dev@1f735b7bc6bb1fc62c782496f2e2ab9b02adec2a, 39 open PRs)Test-merging every open PR into current
devwithgit merge-tree --write-tree:docs-index.generated.ts: fix(ai): add explicit Responses relay session affinity #3918, perf(docs): split embedded manifest from payload #3868, feat(rust-port): phases 0-1 foundations — Bun-free gjc host binary slice #3788, feat(app-server): Codex-compatible app-server protocol surface #3782, feat(models): add Atlas Cloud provider preset #3777, fix(onboarding): load pasted custom-provider credentials #3741.Churn confirms it is not a docs-authoring problem: 31 commits touched this file in the last 30 days, including #3922, #3923, and #3924 — an ACP change and two AI/model changes. It is on the hot path of nearly every merge, so it re-conflicts every open PR each time
devmoves.Two amplifiers:
package.jsonhas"prepare": "bun --cwd=packages/coding-agent run generate-docs-index", so a plainbun installrewrites the file. Contributors get a dirty tree they did not ask for and routinely commit it.packages/coding-agent/scripts/generate-docs-index.tswalksdocs/from disk, so the output is a pure function of the docs tree — the committed copy carries zero information that cannot be recomputed.Proposed fix
Ordered by cost, any one of these removes the conflict class:
docs-index.generated.ts, keep theprepare/prepackhooks that already produce it, and add a CI check that the working tree is clean afterbun run generate-docs-indexso a stale checked-in copy cannot come back. This is the smallest change and kills the conflict entirely..gitattributesentrypackages/coding-agent/src/internal-urls/docs-index.generated.ts merge=docs-indexwith a driver that discards both sides and reruns the generator. Correct, but every contributor has to install the driver locally, so it fails open.Option 1 is the right one unless something consumes the file without a build step —
src/internal-urls/gjc-protocol.tsimports it at runtime, so the packaging path (prepack) already covers publish.Why this is worth fixing now
The repo runs an exact-head CI gate (
git merge-base --is-ancestor "$GITHUB_BASE_SHA" HEADindev-ci.yml), so every PR must rebase onto currentdevbefore merge. With a file that reliably conflicts on rebase, that gate multiplies against itself: each merge forces N rebases, and a share of those rebases hit an unresolvable generated-file conflict. That is the mechanism keeping the open-PR count where it is.Note on the surrounding measurement
While collecting this I also found GitHub's
mergeablefield is badly stale on this repo: 24 open PRs reportCONFLICTING/DIRTY, but 14 of them merge cleanly into currentdev. Anyone triaging by the GitHub badge is chasing phantom conflicts. Worth knowing before acting on the numbers above — they come from localmerge-tree, not from the API field.