Add copilot-globals sync mechanism (closes #59)#63
Conversation
Hoists Joe's user-level review rules out of every project's .github/copilot-instructions.md (which were pushing 3 repos past the 4k Copilot-read cap) into a path-scoped .github/instructions/globals.instructions.md file synced from a single source. - scripts/sync-copilot-globals.py reads ~/.claude/copilot-globals.md (hand-curated source) and writes .github/instructions/globals.instructions.md into each repo listed in scripts/sync-targets.txt. Supports --dry-run, --only NAME filter, and --source / --targets overrides for testing. Idempotent (re-runs report 'unchanged'). - scripts/sync-targets.txt: subscribed repos, one absolute path per line, '#' for comments, '~' expansion. Initially just tools/. - .github/instructions/globals.instructions.md: generated output. Has applyTo: "**" frontmatter so Copilot's PR reviewer reads it on every PR. Contains writing style, banned words, AI-attribution rule, and code-quality basics. - .github/copilot-instructions.md: removed the now-redundant 'Global rules to flag' section (down from 2886 to 2845 chars; ~1700 chars freed for project-specific bug classes). Tightened the favicon/OG rule to scope to resource-kit/docs/**/*.html (the actual deployed surface), exempting _archive/**. - CLAUDE.md: documents the sync workflow, where the source lives, and the explicit rule that no project's CLAUDE.md is sliced for the Copilot cap. CLAUDE.md remains single source of truth for primary coding assistants. The next 3 PRs (rosen-frontend, class, houseofjawn-bot) add those repos to sync-targets.txt and slim their copilot-instructions.md files the same way.
|
Closing — architecturally superseded by PR #60 ( PR #60's merge commit message captured the lesson cleanly: "Copilot's PR review bot enforces code-bug-shaped rules but won't flag English-prose conventions like sentence case or banned words." That's the same constraint memorialized in MEMORY.md → This PR's premise was that the ~1700 chars of English-prose globals (sentence case, banned words, etc.) needed a sync mechanism to live in a separate path-scoped Copilot-readable file. PR #60 dissolved that premise by removing those rules from Copilot-facing files entirely — they belong in CLAUDE.md (which the primary assistant reads and enforces), not in copilot-instructions.md or globals.instructions.md (which Copilot reads but won't act on for prose conventions). After PR #60, master's What to do for the 3 over-cap repos insteadThe actual remaining followup is to apply PR #60's pattern to Cleanup
Procedural lesson going into MEMORY: when starting work in a repo I haven't touched this session, |
There was a problem hiding this comment.
Pull request overview
Introduces a cross-repo sync mechanism to keep Copilot PR review “global” rules in a single source and distribute them into a path-scoped .github/instructions/*.instructions.md file, reducing pressure on the ~4k truncation cap for .github/copilot-instructions.md.
Changes:
- Added
scripts/sync-copilot-globals.pyplusscripts/sync-targets.txtto sync~/.claude/copilot-globals.mdinto subscribed repos. - Added
.github/instructions/globals.instructions.md(withapplyTo: "**") and removed the duplicated “globals” block from.github/copilot-instructions.md. - Documented the workflow and rationale in
CLAUDE.md.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
scripts/sync-targets.txt |
Adds a subscribed-repo list consumed by the sync script. |
scripts/sync-copilot-globals.py |
Implements the CLI that renders and writes the generated Copilot globals file per repo. |
CLAUDE.md |
Documents the new cross-repo Copilot-globals sync workflow and boundaries. |
.github/instructions/globals.instructions.md |
Adds the generated, path-scoped global Copilot instructions file. |
.github/copilot-instructions.md |
Removes duplicated global rules and links to the generated instructions file. |
|
|
||
| If REPO arguments are given, they override the targets file. | ||
| Default source: ~/.claude/copilot-globals.md | ||
| Default targets file: tools/scripts/sync-targets.txt (sibling to this script). |
| DEFAULT_SOURCE = Path.home() / ".claude" / "copilot-globals.md" | ||
| DEFAULT_TARGETS_FILE = Path(__file__).resolve().parent / "sync-targets.txt" | ||
| GENERATED_HEADER = ( | ||
| "<!-- Generated by tools/scripts/sync-copilot-globals.py " |
|
|
||
| These rules apply to ALL pull requests across Joe's repositories. They live here once and are synced into each subscribed repo's `.github/instructions/globals.instructions.md` by `tools/scripts/sync-copilot-globals.py`. Each project's `.github/copilot-instructions.md` then carries only project-specific bug classes, leaving room under the ~4k-char Copilot read cap for that project's real architecture rules. | ||
|
|
||
| The Copilot PR review bot reads this file in addition to `.github/copilot-instructions.md` and the project's `CLAUDE.md` / `AGENTS.md` / `GEMINI.md`. None of those need to restate the rules below. |
Summary
Hoists Joe's user-level Copilot-PR-review rules out of every project's
.github/copilot-instructions.md(which were pushing 3 repos within bytes of the ~4k silent-truncation cap) into a path-scoped.github/instructions/globals.instructions.mdfile synced from a single source. Per the GitHub Copilot path-specific instructions docs, the bot reads*.instructions.mdfiles in addition tocopilot-instructions.md, withapplyToglob andexcludeAgentopt-out support.Architecture explicitly does not slice any project's
CLAUDE.md. CLAUDE.md remains the single source of truth for primary coding assistants (Claude Code, etc.) and is not bound by the 4k Copilot cap.What's in this PR
scripts/sync-copilot-globals.py--dry-run,--only NAME,--source PATH,--targets PATH.scripts/sync-targets.txttools/)..github/instructions/globals.instructions.mdapplyTo: \"**\"frontmatter so Copilot reads it on every PR..github/copilot-instructions.mdresource-kit/docs/**/*.html.CLAUDE.mdSource file
The script reads from
~/.claude/copilot-globals.md(per-user, not in this repo). Initial content (3kb): writing style, banned words, AI-authorship ban, code-quality basics. The script errors clearly if the source is missing.Test plan
python3 -c \"import ast; ast.parse(open(...).read())\"— syntax clean--helprenders the docstringunchanged: ...--dry-runpreviews without writing--source /tmp/missing.mderrors with non-zero exit--only nonexistenterrors with non-zero exitwc -c .github/copilot-instructions.mdconfirms reduction (2886 → 2845)wc -c .github/instructions/globals.instructions.mdconfirms 3081 chars (well under 4k)Followups (separate PRs, one per repo)
After this lands, three follow-up PRs add each over-cap repo to
sync-targets.txtand slim its.github/copilot-instructions.md:rosen-frontend(currently 3995 chars — 5 chars from cap)class(3993 chars)houseofjawn-bot(3992 chars)Other repos adopt opportunistically (worth doing on socialsnag, claude-skills-journalism, reroute-nj, cjs2026 too — all close enough to cap that a future rule addition could silently truncate).
Reference
MEMORY.md→reference_copilot_pr_review_reading_scope.mdfor the underlying constraint, and the verified GitHub Copilot path-specific instructions docs (read 2026-05-02) confirmingapplyTo/excludeAgentschema.