Skip to content

Fix Copilot instruction propagation failing for a third of the repositories - #63

Open
woksin wants to merge 1 commit into
mainfrom
fix/propagation-tree-conflicts-and-write-volume
Open

Fix Copilot instruction propagation failing for a third of the repositories#63
woksin wants to merge 1 commit into
mainfrom
fix/propagation-tree-conflicts-and-write-volume

Conversation

@woksin

@woksin woksin commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Copilot instruction propagation has been failing for roughly a third of the Cratis repositories since late July.

Fixed

  • Propagation no longer exhausts the API rate limit partway through the repository matrix — only files whose content differs from the target are uploaded
  • Propagation no longer fails with GitRPC::BadObjectState (HTTP 422) where an adapter path is a file in one repository and a directory in another

Propagation has failed for a third of the Cratis repositories since late
July, in two ways.

Every run uploaded the whole instruction corpus to every repository — over
seven thousand blob writes per run — so the API write allowance ran out
partway through the matrix and the remaining repositories failed with a rate
limit that the retry helper could not clear. Only the files whose content
actually differs are uploaded now; a repository that is already in sync
costs no writes at all.

The rest failed with GitRPC::BadObjectState because the corpus holds a file
in one repository where another holds a directory — .github/instructions is
a folder symlink here and a real directory there, .github/agents the other
way around. A tree entry cannot replace an entry of the opposite kind, so
the colliding entries are now removed in a preparatory commit before the
sync commit writes the new shape.
@woksin

woksin commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Reviewer context — how the two failures were identified and what the fix computes.

Rate limit. Every run uploaded all 227 corpus files to each of ~34 repositories (~7,700 blob writes) because the up-to-date check bailed on the first difference and then re-uploaded everything. Failing jobs reported Could not create blob for ... — GitHub API rate limit hit ... (attempt 1/8) after the retry helper exhausted its 8 attempts. The per-path comparison now yields, against live data: Arc/Components/Studio changed=0 (no writes at all), Fundamentals/cli changed=150, Ante changed=99 — those three are far behind precisely because they have been failing for weeks.

Tree conflict. Fundamentals, cli and Ante failed with Could not create tree ... GitRPC::BadObjectState (HTTP 422). They hold .github/agents as a folder symlink where the source has a directory of per-file .agent.md adapters, and .github/instructions as a real directory where the source has a folder symlink. The new deletion pass finds exactly those collisions in both directions (28 paths for Fundamentals and cli, 36 for Ante — all under .github/agents and .github/instructions) and removes them in a preparatory commit, so the sync commit writes onto a clean path. The sync commit stays last, so the existing "skip if HEAD is a sync commit" guard still suppresses re-propagation.

Verified: bash -n and shellcheck clean (only the pre-existing SC1091 about sourcing the retry helper), and both jq passes were run against live trees for the six repositories above. The large JSON values go to jq as files rather than arguments — passing a recursive tree on the command line exceeds the per-argument length limit and aborts with "Argument list too long".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant