From the private skill repo (SSOT), sync only the skills that are safe for each destination to public / EMU private / GIM internal. Self-contained SKILL for the CLI (.copilot, prompts not allowed). In VS Code, use the prompt of the same name.
Scope
- Target source: private repo's
.github/skills/<skill>/(native skill)。copilot-skills/{skills,m-skills}/is treated as a private inventory and is not synced to public - Publication destinations: public skill repo, EMU private repo, GIM internal repo
- Distribution (public/private → execution environment
~/.copilot) is handled by Agent Skills Ninja. This SKILL only handles sync / publication to repos
Environment
SYNC_PUBLIC_SKILLS_PRIVATE_REPO: private repo rootSYNC_PUBLIC_SKILLS_PUBLIC_REPO: public repo rootSYNC_PUBLIC_SKILLS_SCRIPT:Sync-AndPush.ps1full path ofSYNC_INTERNAL_SKILLS_EMU_REPO: EMU private repoSYNC_INTERNAL_SKILLS_GIM_REPO: GIM internal repo- In all cases, resolve with Process scope first, and if not present, with User scope (
[System.Environment]::GetEnvironmentVariable($name,'User')) - In this document,
scripts/...(Commit-DirtySkills.ps1、skill-distribution.json、Sync-AndPush.ps1, etc.) are not bundled with the skill but are external dependencies relative to the private repo root. If they do not exist, do not execute and stop
Mode
- Default is
safe-auto: only when this skill is explicitly executed, proceed through audit → sync only the skills safe for each destination → push review-only/dry-run/プレビューWhen specified, present candidates, audit, planned diff, and commit message, then stop- Explicit requests approve their named scope and known destinations. Display remotes/visibility; confirm new or unclear destinations, visibility/privileges, destructive deletion or sensitive decisions. "All" adds no destinations.
- EMU/GIM require an explicit destination request and their sync flags; known configuration alone is not approval. Safe-auto all includes confirming/pushing its own allowed intake commits to the verified private origin before distribution, never unrelated queued commits.
allWhen specified, make not onlyprimarybut also the private repo's uncommitted skill diff a target (All Mode below)
All Mode(all dirty ingestion when specified)
- First,
scripts/Commit-DirtySkills.ps1dry-run, and check skill content and Not Done. Only when the meaning and scope are clear,-Applyand commit per skill - Target is skill content only:
.github/skills/<skill>/**とcopilot-skills/skills/<skill>/**。copilot-skills/m-skills/<skill>/**is targeted only for legacy / manual opt-in..skill-meta.jsonand shared files (README / assets) are excluded .skill-meta.jsonIf is untracked and appears as dirty, treat it as local-only metadata, and it may be deleted without staging. If tracked, do not auto-delete and stop- Dirty items other than skills (scripts, settings, unrelated files,
/memories/**) are not committed. If mixed in, do not stage and list them in Not Done - Commit by owning skill; group its related small edits and relevant formatting together. Never mix unrelated skills, shared files or other dirty paths, and do not require separate pushes for one bounded improvement.
- After committing, audit each skill's public / EMU / GIM routing. Route only public-safe ones to public, and internal-only / private-only ones to EMU/GIM, without leaking them to public
- Skills containing secrets / customer names / personal emails / specific TPIDs / local absolute paths may be committed but are excluded from public sync. For those that cannot be generalized, also stop and confirm on the EMU/GIM side
- Hold only the affected skill when scope is unclear, deletion is destructive, or privileges/publication/default behavior change; bounded authoring within approved scope needs no repeated approval.
Gates (always check before publication)
- The classification SSOT for public / internal / denied / copilot-denied is
scripts/skill-distribution.json。publicCopilotSkillsis kept empty, and the current list is not duplicated into prompts or SKILL bodies dirtyis treated not as a sync necessity but as a gate for undetermined authoring. Whether normal sync is needed is determined by the content diff between the private source path and the public / EMU / GIM destination path. Content diff is based on tracked files, and do not judge by raw filesystem hash comparison alone. Untracked build artifacts in both repos (__pycache__/*.pyc, etc.) appear as phantom diffs, making the pending set look nearly double the actual size. When candidates appear,git ls-filesand check whether they are tracked before including them in the target- Before execution
Mode / Selected Skills / 選択外の public diffIndicates. If the target is explicitly specified,primary-only、all/broadthen use broad, and do not infer primary from the conversation flow alone - If primary is explicitly specified, limit the default confirmation scope to primary and its synchronization path. Full skill inventory, all duplicates, and full copilot-skills license audit are
all/broad/audit/棚卸しperformed only when explicitly specified - Exclude private-only / internal-only / MS-internal skills from public sync. Route internal-only ones through the EMU private repo or GIM internal repo path
.skill-meta.jsonas local-only metadata, exclude it from dirty detection / stage / push / public diff- shared file(
.github/skills/README.md、assets/**, auto-generated.github/skills/LICENSE) is separated from the skill commit. After broad sync, if onlyLICENSEleaves generated drift, check the contents, and if it is as intended, separate it into a sync/index commit - During sync-only execution, do not edit README / assets / index / SKILL body
- public safety audit: If an unexpected skill leak or unexpected deletion occurs, stop and check the cause
- Stop for ambiguous remotes, unconfirmed selected content, unexpected deletion or audit failure. Complete explicitly authorized all-mode intake/private push before distribution; snapshot primary-only rejects selected dirty/unpushed content. Preserve unrelated dirty; broad/all retains branch/clean/current/classification.
- Do not create manual copies or temporary sync scripts; use the official runner's
Sync-AndPush.ps1and its scope parameter - Do not put secrets / customer information / personal email / specific TPID / local absolute paths into public or EMU. Use placeholders for examples
Destination Audits and Gates
This SKILL decides the judgment per Destination (publishability / exclusion list / repo visibility / sensitive scan). Detailed procedures and default lists are in references/instructions/audits-and-gates.md。
- Runner capability gate: relaxed primary-only requires committed audited-SHA/origin, same-SHA policy, scoped audits, source preservation and public tree/scope checks. Local drafts are not support. Otherwise use no new flags/relaxation and hand off the update; legacy broad may retain its existing full gates.
- New Skill Classification Gate: with that runner, primary-only audits selected skills and defers unselected dirty/unknowns without copying them; broad/all retains whole-repo classification. Legacy runners retain their existing stop conditions.
- Agent Discovery Gate: ask classification only for an unknown selected skill. Never infer public permission or use
-AllowUnknownSkillsas a bypass. "Not this run" excludes that skill temporarily; it is neither permanent deny nor publication approval. - Copilot-Skills Private Inventory Gate:
.copilotMirrors originating from are excluded from public targets regardless of license, and are kept only within the private repo - EMU Private Sync Gate: visibility
PRIVATE/INTERNALconfirmation, convert secrets to placeholders - GIM Internal Sync Gate: Aggregate MS-internal skills into org-owned internal. Default internal set SSOT
- Incident Recovery: For recovery when something bypasses the prevention gate and leaks to public (limitations of filter-repo, GitHub Sensitive Data Removal request, fork purge, rename vs delete, pitfalls of robocopy move), refer to the Incident Recovery section in references
Sync Strategy
- The explicit skill to sync this time
primaryas the primary - Capable primary-only pins selected native content/config with
-PrimarySkills,-SourceCommit,-ExpectedSourceOrigin; unselected/shared/inventory/orphan paths remain untouched. - If the target skill is explicitly specified, first check only that skill's readiness, source/destination diff, and leaks. The default is
primary-onlyassume - Capability-verified snapshots reject selected/config dirty or unpushed commits, but allow detached/behind original sources with unrelated dirty. Legacy primary/broad retains master/clean/current gates; never apply snapshot exceptions to it.
- Review the whole ahead range before a separate authorized private push; integrate divergence before push and refresh pins. Read-only primary never pushes private authoring; zero committed diff means no sync.
allWhen specified, do not leave unselected dirty items unattended; commit per skill in All Mode before syncing- For capability-verified primary-only, audit/pin remote blobs/config, re-audit after advancement, and use matching code from a clean audited checkout when needed; temporarily redirect Process source env and restore finally. Legacy cannot promise SHA-bound execution and must not simulate it.
primary-onlydoes not use deletion of other skill directories, shared file updates, or broad bulk deletion logic. Verify that the public / internal diff is only the selected primary destination path- Capability-verified primary-only requires pre-push public index/commit identity and whole-commit literal scope after exclusions. Reject transformation/leakage without retrying. Legacy keeps its existing verification but is insufficient for this new pre-push guarantee; use the update handoff when that guarantee is required.
Workflow
- Resolve private / public / script, and if necessary EMU / GIM repos, and
primarycheck branch / remote, ahead/behind, and dirty state - Check capabilities and selected readiness/classification/content diff. Only capable primary-only defers unselected authoring; legacy/broad/all retains full stop gates. Never skip selected license, secret, deletion or mirror checks.
allWhen specified,Commit-DirtySkills.ps1のdry-run→-Applycommit per skill with. Leave non-skill dirty items as Not Done, and the sync script does not implicitly commit private dirty items- In safe-auto all, verify private origin/visibility and the entire ahead range, isolate unrelated dirty, integrate behind/divergence, validate and push only the authorized intake commits before sync. If isolation or scope cannot be established, stop that pre-step; never let
-SkipDevPushhide pending commits. - Legacy/broad distribution must execute from a verified clean/current checkout with its Process source env temporarily aligned and restored afterward; otherwise hold distribution, not unrelated authoring.
- In safe-auto all, verify private origin/visibility and the entire ahead range, isolate unrelated dirty, integrate behind/divergence, validate and push only the authorized intake commits before sync. If isolation or scope cannot be established, stop that pre-step; never let
- choose safe path
- legacy primary-only: retain the old gates or hand off the runner update when relaxed behavior is required; never substitute broad to bypass a selected-scope stop.
- capability-verified primary-only:
Sync-AndPush.ps1 -PrimarySkills <skill-name...> -SourceCommit <audited-full-sha> -ExpectedSourceOrigin <approved-origin-url> -Message "sync: <skill summary>" -SkipDevPush - broad:
Sync-AndPush.ps1 -Message "sync: <summary>" -SkipDevPush -ExcludeCopilotSkills <監査で確定した除外名> - EMU private:
Sync-AndPush.ps1 -SyncEmu [-EmuDryRun] - GIM internal:
Sync-AndPush.ps1 -SyncInternal [-InternalDryRun]
- Confirm only the approved destination set changed. Primary-only never pushes private source; any separately requested private push must have a scoped ahead range, clean execution checkout and integrated remote updates.
- Git の
master = origin/masterDo not consider it complete with just that. For public, check the local source/destination hash and remote reachability; for GIM/EMU, check the remote tree's path set and blob SHA.Missing / Mismatch / Extra = 0Do not treat it as complete until it becomes
Gotchas
- Verification cost: measured on the sync suite, fixture rebuilds and pwsh-spawning integration tests dominate (about 100s for 42 tests); isolation and fetch cost seconds. For small skill edits run the targeted checks plus
Invoke-Pester -ExcludeTag Integration, and run the full suite once before committing runner/backend changes. CallUpdate-PublicSkillsReadme.ps1 -Checkonce; it can leave a stale non-zero$LASTEXITCODE, so reset it before reuse. - Formatter drift: relevant alignment belongs with the owning skill's bounded change; unrelated whitespace drift is a separate normalization change after verification. Do not blanket-stage other authoring or require a separate commit for every formatting line.
- Push rejected / divergence: Fetch before push and recalculate ahead/behind. If both sides have commits, check for overlapping changed paths, and if there are no conflicts, synchronize with a normal merge. Do not proceed to rebase or push while the tracking ref is stale
HEAD.lockrename failure: If the same failure occurs twice in a row, stop withnand check HEAD, status, diff, rebase metadata, and lock ownership. Protect uncommitted changes, and do not doreset --hardor bulk lock deletion. Only when it can be proven that HEAD is unchanged and only the index/worktree matches the fetched remote, return the target to HEAD and switch to a verified merge that does not detach HEAD- Git Data API transient failure: The blob/tree/commit/ref APIs go through common retry and empty-SHA fail-fast. After updating the ref, re-fetch the remote tree and confirm stale path deletion and an exact match
- Internal full mirror only: Reject internal subset specifications because they may delete unselected Skills. Use only the full set from the distribution config as the desired set
- Skill rename: Align the folder name with
name, the distribution config, and the README / LICENSE index in the same change, and apply it via a broad sync that deletes the old folder (primary-only does not delete the old folder). Since copies of the old name already installed at distribution destinations cannot be resolved by an update and may be left pending or require repair, guide the user in the completion report to reinstall under the new name and delete the old folder - All Mode rollback: Stop on tracked metadata, cross-root rename, or commit failure. For a failure midway through a commit, return to the original HEAD and keep the diff unstaged
Report
- Summary / Primary / Path Chosen / Audit / Private Sync / EMU / GIM / Public Sync / Verify / Not Done / Next Suggestions
- List up to three read-only candidates from Git state/committed differences: dirty -> Retro; pending -> private range review; public-safe gap -> separately requested sync. Honor holds/visibility; no unknown/private/internal/denied public proposals, extra mutations or unsolicited full audits.