Skip to content

docs-index.generated.ts is a committed one-line-per-doc artifact that conflicts on every rebase — 6 of 10 real PR conflicts, 4 blocked by it alone #3928

Description

@yazzang-homelab

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:

  1. 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.
  2. 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:

  1. 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.
  2. 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.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions