---
name: resync
description: Re-stamp the vendored promotion tooling (tools/promote.py, promote.bat, verify.bat) of Promotion-Gated Publish Workspaces from the canonical bundled templates, so a template improvement propagates to every workspace without re-introducing drift. Use when the canonical promote.py/verify templates change and you want existing private/public workspaces updated, or when the user asks to "resync the promotion tooling", "propagate the template", or "update promote.py everywhere". Skips a customized verify.py (only re-stamps untouched stubs). For creating a new workspace use the g-workspace-init plugin; for converting/migrating use g-workspace-convert.
disable-model-invocation: false
---

# g-workspace-resync

The promotion tooling is **vendored** per workspace (each `tools/promote.py` is a local copy, keeping the
workspace self-contained). This skill is the controlled way to update those vendored copies from a single
source of truth — the canonical templates bundled at `${CLAUDE_SKILL_DIR}/templates/` (the same templates
shipped by the g-workspace-init plugin) — so an improvement to `promote.py` reaches every workspace without
the hand-editing that causes drift.

It re-stamps only the **project-agnostic** tooling and never touches project-specific content.

| File | Behaviour |
|------|-----------|
| `tools/promote.py` | Always re-stamped from template (fully project-agnostic). |
| `tools/promote.bat` | Always re-stamped. |
| `tools/verify.bat` | Always re-stamped (generic venv wrapper). |
| `tools/verify.py` | Re-stamped **only if it is still the untouched stub** (`CONFIGURED = False`). A configured/customized verify.py is **skipped** and reported. |

It **never** touches `manifests/`, `CLAUDE.md`, `.gitignore`, `private/`, or `public/`, and makes **no git
commits**.

## Instructions

1. **Choose the targets.** Either explicit workspace roots, or discovery under a base directory (use
   `python3` on macOS/Linux, `python` on Windows):
   ```
   # explicit
   python3 "${CLAUDE_SKILL_DIR}/scripts/resync_tooling.py" "<workspace-root>" ["<root2>" ...]
   # discover all migrated workspaces under a base
   python3 "${CLAUDE_SKILL_DIR}/scripts/resync_tooling.py" --discover "X:/"
   ```
   Discovery identifies a workspace as a directory holding `tools/promote.py`, `manifests/public.manifest.yaml`,
   and both `private/` and `public/`. Non-workspaces are skipped with a notice.

2. **Run the dry-run first** (default — changes nothing). Show the user the per-file status table:
   `unchanged` / `updated` / `added` / `skipped (customized)`.

3. **Apply once confirmed**, adding `--apply`:
   ```
   python3 "${CLAUDE_SKILL_DIR}/scripts/resync_tooling.py" --discover "X:/" --apply
   ```

4. **Report** which files were re-stamped in which workspaces. If any `verify.py` was `skipped (customized)`,
   note that those keep their project-specific logic by design — if the verify *template* changed in a way those
   should adopt, that is a manual, per-project port (see `${CLAUDE_SKILL_DIR}/reference/workspace-pattern.md` §10).

5. **Commits are the user's.** After a resync, each affected workspace's root repo will show modified
   `tools/` files; the user reviews and commits them following the project's authorship conventions.

## Notes

- Re-stamping is idempotent: if a workspace already matches the template, everything reports `unchanged`.
- The canonical templates are bundled with this plugin (and are the same ones shipped by g-workspace-init).
  If you change the canonical templates, update them in the template source and re-run this skill.
- This is the maintenance counterpart to the **g-workspace-init** (create) and **g-workspace-convert**
  (convert/migrate) plugins. The pattern and the known-workspace conventions are documented in
  `${CLAUDE_SKILL_DIR}/reference/workspace-pattern.md`.

$ARGUMENTS
