---
name: memory-sync-setup
description: "Generates a project-tailored memory-sync skill: memory surface batches, checkable-fact catalogue, non-growth sync, independent verify, self-sync, agent re-audit. Triggers: memory sync init, generate memory sync, sync memory skill, установи memory-sync, синхронизируй память"
user-invocable: true
disable-model-invocation: true
argument-hint: "[prompt] [status|install|upgrade|enable|disable|uninstall|purge] [fine-tune-prompt]"
allowed-tools: [Read, Edit, Glob, Grep, Bash, Agent, AskUserQuestion]
model: opus
---
<!-- brewcode-meta: version=6.2.0 content_version=6.2.0 generated_by=brewdoc:memory-sync-setup -->

# Memory Sync Generator (brewdoc:memory-sync-setup)

**ROLE:** GENERATOR. It analyzes the TARGET project, then WRITES a self-contained, project-local
`.claude/skills/memory-sync/` into that repo. It NEVER syncs memory itself -- it emits the skill that does.

**WHY a generator:** generic memory sync produces generic results. Only a skill that already knows THIS repo's
batches, invariants, fact-verification commands, agent roster and language policy can keep instruction memory
truthful. A generic sweep cannot tell an intentional Russian trigger alias from a language violation, cannot tell
a stale lint-rule claim from a correct one, and cannot prove a removed fact is gone from REALITY rather than
merely deleted from a doc.

**OUTPUT:** `<target>/.claude/skills/memory-sync/` -- `SKILL.md` + `references/memory-guide.md` +
`references/agent-audit.md` + `references/hard-sync.md` + `references/prompting-guide.md`. Nothing else is
written; no agent is created, no rule is installed, no hook is registered.

## Prompt contract

Position 1 of `$ARGUMENTS` is a **free-form prompt** (RU/EN) -- modes and the fine-tune text are optional and may
follow in any order. Nobody types keys: resolve mode + scope FROM the prompt.

1. Strip flags. An explicit mode token anywhere wins outright, no scoring.
2. Else score modes by distinct whole-word keyword hits (table in `## Modes` below). Highest unique score wins.
   Tie with a destructive mode -> `AskUserQuestion`; tie with `status` -> `status`; tie of two mutating modes ->
   the keyword appearing first; all zero -> `status` if installed, else `install`.
3. Empty arguments -> `status` if installed, else `install`; ask ONE scoping `AskUserQuestion` only when the
   answer changes what gets written. A read-only run asks nothing.
4. Outcome-changing ambiguity -> ONE `AskUserQuestion` (max 4 questions) BEFORE any work.
5. Prose that is not a mode/id/path is still input: extract the id, path or target from it -- never treat the
   first word of a sentence as a positional id. The remainder becomes the fine-tune prompt / `{FOCUS_EMPHASIS}`.

Then print this block ONCE, before the first action (this replaces the old bare ANNOUNCE line below):

```
PLAN — brewdoc:memory-sync-setup
INPUT:  <arguments verbatim, or "(empty)">
MODE:   <resolved> — <explicit | matched keyword: X | default>
SCOPE:  target=<absolute repo root>; emphasis=<fine-tune prompt interpretation | "none">
DO:     <2-5 imperative bullets>
RESULT: <what the user ends up holding>
```

Labels are literal; values follow the conversation language.

## What the emitted skill does

The emitted `/memory-sync` is a long-running multi-agent coordinator that diffs instruction memory against the
code for a SCOPE and repairs it -- facts FIRST, dedup second, compression third -- under a NON-GROWTH prime
directive (every file ends `<=` its original line count, total delta `<= 0`). It sweeps the WHOLE memory surface
every run; free-form focus text steers EMPHASIS only and never narrows the sweep. Its batches are disjoint by
construction, so parallel edits never collide. It carries TWO orthogonal axes: `{SCOPE}` selects WHICH change
facts drive the sweep, `{DEPTH}` selects HOW HARD the surface itself is cut.

| Axis | Emitted behaviour |
|------|-------------------|
| Scopes | `session` (DEFAULT -- facts from THIS conversation, no gather agent), `branch` (diff vs the derived default branch), `commit <sha>` / `commit <a>..<b>`, `recent[:N]` (default 10), `all` (no diff -- every checkable fact re-verified) |
| Depth | `NORMAL` (DEFAULT -- fact sync + dedup + compression) or `HARD` (NORMAL plus the two passes in `references/hard-sync.md`), from the token `hard` or the same intent in prose ("too much context", "aggressive", "почисти жёстко") |
| HARD pass A | rules `paths:` PRECISION audit -- a broad or missing glob loads the rule into EVERY context and is paid for on every turn, so the glob must be the narrowest pattern still covering the rule's real subject. Verdicts `OK` / `TOO_BROAD` / `TOO_NARROW` / `DANGLING` / `MISSING` / `CORRECTLY_GLOBAL`; a genuinely repo-wide subject legitimately carries none and one is never invented |
| HARD pass B | OBVIOUS-KNOWLEDGE PURGE -- anything a competent model already knows is DELETED, not compressed. Keeps only what the model cannot know: decisions that invert a default, domain invariants, environment quirks, explicit prohibitions |
| Focus | free text after the scope token: emphasis ordering only. Never a filter, never a batch skip |
| Phase GATHER | parallel read-only agents: change-fact list + target inventory BY ENUMERATION (`{ENUMERATION_BASH}`), never a hardcoded file list |
| Phase SYNC | ONE bounded agent per disjoint batch, ALL spawned in ONE message, each with its file list, the change facts and the house invariants |
| Phase VERIFY | independent read-only checkers, one per EDITED batch, never the agent that wrote it: re-verify every added/fixed fact in code, prove every removed fact is gone from REALITY, assert frontmatter/ids/secrets/language |
| Phase SELF-SYNC | the emitted skill re-checks and updates ITSELF: re-enumerated counts, new batches, new sections for memory layers the project gained. Scope DECISIONS (batch table, exclusions) are never rewritten without explicit user instruction |
| Phase PROPOSE | new agent / new skill assessed against `{PROPOSAL_PRECEDENTS}` and PROPOSED in the report -- never auto-created |
| Agents | ALWAYS re-audited against current best practice (`references/agent-audit.md`), not merely fact-checked |
| Report | chat only, no report file; a run that touched only the root CLAUDE.md is an INCOMPLETE run |

**Arguments:** `$ARGUMENTS` -- an optional MODE token (`status` | `install` | `upgrade` | `enable` | `disable` |
`uninstall` | `purge`) followed by an optional
free-form fine-tune prompt. The prompt is woven into the emitted skill's focus ordering and recorded in
`{FOCUS_EMPHASIS}`.

---

## Modes (deterministic -- resolve BEFORE any work)

Canonical verbs, in order: `status | install | upgrade | enable | disable | uninstall | purge`.

An explicit mode token anywhere in `$ARGUMENTS`, lowercased, wins outright -- no scoring. Otherwise score every
mode by distinct whole-word keyword hits below; highest unique score wins. Everything that is not a matched
keyword is fine-tune text (`{FOCUS_EMPHASIS}`). No mode token and no keyword match -> `status` when
`<target>/.claude/skills/memory-sync/` exists, `install` when it does not.

| Mode | EN keywords | RU keywords | Mutates? |
|------|-------------|-------------|----------|
| `status` | *(empty when installed)*, status, check, show | статус, проверь, покажи | no |
| `install` | install, setup, generate | установи, настрой, сгенерируй | yes |
| `upgrade` | upgrade, refresh, update | обнови, апгрейд | yes |
| `enable` | enable, turn on | включи, верни | yes |
| `disable` | disable, pause, turn off | выключи, отключи, пауза | yes |
| `uninstall` | uninstall, remove | удали, убери | yes |
| `purge` | purge, wipe | вычисти, снеси | yes, destructive |

Tie-break: a tie involving `purge`/`uninstall` -> `AskUserQuestion` (never guess destructive); a tie with
`status` -> `status`; a tie of two mutating modes -> the keyword appearing first in the prompt.

Removed aliases -- `init`, `on`, `off`, `setup`, `remove`, `reset`, `create`, `update`, `cleanup` are no longer
accepted. Map them onto the canonical set (`init`/`create` -> `install`, `on` -> `enable`, `off` ->
`disable`, `remove`/`reset`/`cleanup` -> `uninstall` or `purge` -- ASK which) and say so in the PLAN block.
Never print a removed alias as a command.

| Mode | Reads | Writes | Does |
|------|-------|--------|------|
| `status` (**DEFAULT when installed**) | target + emitted skill | NOTHING | Report whether `<target>/.claude/skills/memory-sync/` exists, its provenance frontmatter (`doc_type` / `version` / `generated_by` / `last_updated` / `surface_files`), and how STALE its surface tables are vs the live repo: `surface_files` count baked in vs enumerated now, batches whose paths no longer exist, memory layers the project gained since. Ends with a verdict `IN SYNC` / `STALE (n drifts)` / `STALE-LEGACY (n drifts)` (pre-5.0 tail stamp) / `NOT INSTALLED`, each prefixed `PARKED - ` when the install is disabled (`INSTALLED=parked`) -- parked and absent are never collapsed |
| `install` (**DEFAULT when not installed**) | target | emits the 5 files | Full Phase 0-5 analysis + emit. Refuses an existing installation (see Error Handling) |
| `upgrade` | target + emitted skill | Edits the emitted skill | Re-scan, then REFRESH an existing installation: re-enumerate the surface, refresh the batch / fact / invariant tables, ADD sections for memory layers the project gained, and ALWAYS finish with `generate.sh restamp` (see Mode: upgrade). PRESERVE hand-edits -- the emitted skill is EXPECTED to have self-modified (SELF-SYNC phase). Never blind-overwrite |
| `enable` | target | one rename | `generate.sh enable`: `SKILL.md.disabled` -> `SKILL.md`, so `/memory-sync` is offered again. Regenerates nothing, so no provenance stamp and no hand-edit changes |
| `disable` | target | one rename | `generate.sh disable`: `SKILL.md` -> `SKILL.md.disabled`. Claude Code discovers a project skill ONLY through `SKILL.md`, so this withdraws `/memory-sync` from the roster while the 4 references and every SELF-SYNC hand-edit stay byte-identical on disk. Reversible by `enable`; deletes nothing |
| `uninstall` | target | deletes the emit manifest | `generate.sh uninstall`: removes exactly what `emit` wrote -- `SKILL.md` (or its parked form) plus the 4 references -- and nothing it did not. Files a user added to that dir are KEPT and listed. Confirmation first |
| `purge` | target | deletes the whole dir | `generate.sh purge`: removes `<target>/.claude/skills/memory-sync/` outright, user-added files included, plus any `.memory-sync-emit.*` staging a crashed emit left under `.claude/skills/`. Confirmation first |

> **Why `uninstall` and `purge` differ here.** `emit` writes a fixed manifest (`SKILL.md` + the 4 references), and
> that manifest is also the removal manifest: `uninstall` is scoped to it, so a note or an extra reference the user
> dropped into the skill dir is never destroyed by a removal they asked for. `purge` is the "I am done with this
> entirely" verb and takes the directory. The generator registers no hooks, writes no settings and no config, so
> these two paths ARE its whole footprint -- there is nothing else for `purge` to sweep.

Print the PLAN block (see Prompt contract above) before any work.

> `upgrade` NEVER runs `emit` over a live installation. `emit` refuses to overwrite (`MEMORY_SYNC_FORCE=1` is the
> conscious override, and it DESTROYS hand-edits). Upgrade works through targeted `Edit` calls, section by section,
> plus the metadata-only `generate.sh restamp`. `MEMORY_SYNC_FORCE=1` is never the answer to a stale stamp.

FIRST step of `status`, and of `upgrade` before it decides what to refresh -- **EXECUTE** using Bash tool:
```bash
bash "${CLAUDE_SKILL_DIR}/scripts/generate.sh" status
```

Its machine-greppable KEY=value block and closing verdict (`NOT INSTALLED` / `IN SYNC` / `STALE (<n> drifts)` /
`STALE-LEGACY (<n> drifts)`) ARE the staleness answer: never re-derive them by hand. `status` reports that output
enriched with your own reads and STOPS -- it writes nothing. `upgrade` takes the same drift list as its refresh
worklist and continues to Phase 1; `NOT INSTALLED` there means STOP (see Error Handling).

> **`STAMP_FORMAT=legacy` is NOT a special path.** A pre-5.0 install stamps its provenance as a tail comment
> (`<!-- memory-sync template vX.Y.Z emitted <date> by brewdoc:memory-sync-setup | surface: … -->`) instead of
> frontmatter. `generate.sh restamp` -- the mandatory last step of EVERY `upgrade`, below -- migrates it in one
> call: it writes the five frontmatter keys and DELETES the tail line. Report the migration explicitly when
> `STAMP_FORMAT` came back `legacy`; after `restamp` it must read `frontmatter`. Never hand-`Edit` the stamp.

### Mode: upgrade

Refresh an existing installation against the current repo AND the current plugin version. Every hand-edit
survives: `upgrade` never runs `emit`, never re-copies a file that carries content, and touches the stamp
only through `restamp`, which is proven metadata-only.

1. Run the `status` bash block above. `NOT INSTALLED` -> STOP (see Error Handling). `INSTALLED=parked` ->
   the install is DISABLED, not broken: say so and offer `enable`; upgrading a parked install is a no-op the
   user did not ask for.
2. Take the `status` drift list as the refresh worklist and run Phase 1 (re-scan) -> Phase 3 (targeted
   `Edit`s): re-enumerate the surface, refresh the batch / fact / invariant tables, ADD sections for memory
   layers the project gained. PRESERVE every hand-edited section; `AskUserQuestion` before REPLACING one.
3. **Restamp -- ALWAYS, whatever `STAMP_FORMAT` said, and never skipped because "the format is already
   current".** An install in the current format that is merely a version behind has no other route to a
   fresh stamp, and Phase 4 `validate` hard-fails on a stale one.

   **EXECUTE** using Bash tool:
   ```bash
   bash "${CLAUDE_SKILL_DIR}/scripts/generate.sh" restamp && echo "✅ restamp" || echo "❌ restamp FAILED"
   ```

   > **STOP if ❌** -- it never half-writes: the body is compared before and after and the file is left
   > untouched unless the ONLY change is the metadata block.

   It rewrites `version` / `last_updated` / `surface_files` (and adds `doc_type` / `generated_by` when they
   are missing), drops a surviving pre-5.0 tail stamp, and re-copies a `references/*.md` ONLY when that file's
   sole difference from the plugin source is the release stamp line. Report its `RESTAMPED:` / `REF …` lines
   verbatim. A `REF DIFFERS:` line is a decision for you, not a failure -- `hard-sync.md` always differs
   because Phase 3 filled its two BLOCKs; diff it against the plugin source and port real prose changes by
   hand, never by re-copying over the filled tables.
4. Phase 4 `validate`, then the Phase 5 report.

### Mode: enable / disable

A rename, nothing more. Use `disable` to park a `/memory-sync` that should stop being offered for a while without
losing a single hand-edit; use `uninstall` when it should really go.

1. Run the `status` bash block above. `NOT INSTALLED` -> report "nothing to {enable|disable}" and STOP. Never emit
   a fresh install as a "fix" for a toggle verb.
2. **EXECUTE** using Bash tool (substitute the resolved verb):
   ```bash
   bash "${CLAUDE_SKILL_DIR}/scripts/generate.sh" MODE_HERE && echo "✅ MODE_HERE" || echo "❌ MODE_HERE FAILED"
   ```
3. Report the script's `MOVED:` / `KEPT:` lines verbatim. `✅ already {enabled|disabled}` is a clean no-op, not a
   failure -- report it and STOP.
4. Say that the change lands in the NEXT session: skills are discovered at session start.

> `validate` FAILS on a disabled installation, because it looks for `SKILL.md` and finds `SKILL.md.disabled`.
> That is the toggle working, not a broken install. Never re-`emit` to "repair" it -- `emit` would destroy the
> SELF-SYNC hand-edits the parked file still carries. `enable` is the fix.

### Mode: uninstall / purge

The generator's ONLY footprint in the target is `<target>/.claude/skills/memory-sync/` (plus, after a crashed emit,
a `.memory-sync-emit.*` staging dir beside it) -- it registers no hooks, writes no settings and touches no config.
`uninstall` removes exactly the emit manifest; `purge` removes the directory outright.

1. Run the `status` bash block above. `NOT INSTALLED` -> report "nothing to {uninstall|purge}" and STOP.
2. List what is there -- **EXECUTE** using Bash tool:
   ```bash
   ROOT="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")}"
   find "$ROOT/.claude/skills/memory-sync" -type f | sort
   ```
3. **ASK** via `AskUserQuestion`, ONCE, naming the real count:
   - `uninstall`: "Delete the 5 emitted files under `<target>/.claude/skills/memory-sync/` (N files present)?
     Hand-edits to them are lost; anything you added yourself is kept."
     Options: **Yes, uninstall** / **Purge instead (deletes the whole dir)** / **Cancel**.
   - `purge`: "Delete `<target>/.claude/skills/memory-sync/` entirely (N files)? Nothing is recoverable."
     Options: **Yes, purge** / **Uninstall instead (keeps files I added)** / **Cancel**.

   Anything but the affirmative -> switch to the other verb or **STOP**. A declined confirmation deletes nothing.
4. On confirmation -- **EXECUTE** using Bash tool (substitute the confirmed verb):
   ```bash
   bash "${CLAUDE_SKILL_DIR}/scripts/generate.sh" MODE_HERE && echo "✅ MODE_HERE" || echo "❌ MODE_HERE FAILED"
   ```
5. Report the script's `REMOVED:` / `KEPT:` lines verbatim. After `uninstall`, any `KEPT:` list is the exact reason
   to offer `purge`. `/memory-sync` disappears on the next session reload.

---

## Execution

### Delegation (applies to every Agent this generator spawns AND to the fan-out it emits)

A big task handed to one agent = an agent gone for an hour: you cannot observe it, cannot correct it, and it
usually drifts off-target. One subagent = ONE bounded unit -- one deliverable (here: ONE batch), ~<=5 files,
~<=10 steps. Bigger MUST be split into N tasks, all spawned in ONE message -- that is exactly why the emitted
skill splits the surface into disjoint batches instead of handing one agent the whole memory tree.

Every spawn prompt MUST carry:

| Field | Content |
|-------|---------|
| GOAL | the overall task and why it exists -- the point beyond the file edit |
| ROLE | what this agent owns; what it must NOT touch |
| SCOPE | exact paths/commands in bounds + explicit out-of-bounds |
| CONTEXT | what is already done, by whom, what runs in parallel -- trimmed to what THIS agent needs |
| CONSUMER | who or what uses the result next, and the shape it must fit |
| DONE | acceptance criteria + the exact report shape you want back |

A bare one-line task is never enough. When filling `{BATCH_TABLE}` in Phase 3, keep every batch small enough to be
one bounded unit -- split an oversized batch (a 26-agent roster, a 20-file rules dir) into two rows rather than
emitting one agent that owns half the surface.

### Phase 0 -- Pre-analysis (read THIS skill's emit material)

Read the emit material this generator ships, relative to `${CLAUDE_SKILL_DIR}`:

- `references/SKILL.md.template` -- the emitted SKILL.md, with `{PLACEHOLDER}` slots
- `references/memory-guide.md` -- where-does-it-belong decision tree, compression patterns, obvious-vs-domain facts
- `references/agent-audit.md` -- the agent/skill re-audit procedure the emitted skill runs every sweep
- `references/hard-sync.md` -- the two `HARD`-depth deletion passes (`paths:` precision audit + obvious-knowledge
  purge) and their reporting contract; it holds TWO of the twelve BLOCK placeholders
- `references/prompting-guide.md` -- the merged Claude 5 + OpenAI/Codex prompting-quality rule table applied at
  Phase 2/3; carries no BLOCK placeholders

Confirm the TARGET project is the current working directory. All emitted paths are relative to that repo root.

> Missing template -> ERROR "missing emit material: `<path>` -- rein