memory-sync · git:20260717.da342b0 · 2026-07-17 · sha256 760ac4c87c296c4d
memory-sync git:20260717.da342b0A
Immutable. This exact content is served forever at /api/v1/blob/760ac4c87c296c4d.
---
name: memory-sync
description: >
Persist new context, terms, learnings, and settled lightweight decisions. Use when
the user says remember this, save this for later, add to glossary, note this down,
or at the end of a session to consolidate what was learned — that goes to the
memory layer (CLAUDE.md hot cache, docs/memory/, docs/inbox.md). Also use to
record a decision, remember this decision, or write this decision down when the
call is a lightweight one shipped outside a spec slice: UI strings, visual and CSS
choices, sizes, copy, or translation fixes. Those go to
docs/decisions/lightweight-decisions.md via decisions.py. Also auto-fires at
session end to surface capture-worthy items. Do not use for updating specs or code
comments — those have their own workflows. For a load-bearing or architectural
decision, one with rejected alternatives worth recording, or any decision the user
wants written up as an ADR, use `/jig:adr-workflow` instead.
user-invocable: true
---
> Spec 002 (memory layer) is fully closed — all four slices DONE: 002-01
> (explicit-sync), 002-02 (lookup-pattern), 002-03 (auto-detect-hooks),
> 002-04 (reconciliation-integration). 002-04's reconciliation integration
> is now the Memory-sync gate in the spec-workflow reconciliation checklist.
## What this skill does
Persists session-derived context to the memory layer via a deterministic helper.
Claude makes the *what / where* decisions; `memory.py` does the file I/O,
idempotency, and self-healing of missing memory structure.
## When to invoke
- User says "remember this", "save this for later", "add this to the glossary",
"note this down", or similar (→ persist flow below).
- User explicitly invokes `/jig:memory-sync`.
- An unknown capitalized reference appears in the conversation (→ lookup-pattern flow below).
- Session-end consolidation (after slice 002-03 auto-trigger ships).
- **The session settled a non-spec shipped decision** — a UI string, visual/CSS
choice, translation correction, or scoped brand/icon call made *outside* a spec
slice (→ lightweight-decision flow below). This is the forcing function for
out-of-spec work, which has no reconciliation phase to catch it.
## Lookup-pattern flow
When you see a capitalized reference, acronym, or project-specific term you
don't recognize, follow this flow **before asking the user**:
```
seen unknown reference X
↓
python3 memory.py lookup "X" .
↓ exit 0 → use the printed definition; do not ask
↓ exit 2 → ask the user once: "I don't recognize X — what is it?"
↓ user answers
↓
python3 memory.py add-term "X" "<definition>" . (or promote if high-frequency)
↓ next time X appears, lookup hits
```
Concretely, the commands are:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" lookup "<term>" "<target>"
# exit 0 = hit (definition + source on stdout)
# exit 2 = miss (proceed to ask the user)
```
The lookup is case-insensitive and checks hot cache first, then glossary. Hot
cache hits win when a term exists in both (the user has explicitly elevated it).
**Do not ask twice.** Once a term is persisted (via `add-term` or `promote`),
future lookups in the same or later sessions resolve without re-asking. If the
user says "I told you this already," check whether you forgot to persist last
time, then persist now.
## How to use
1. **Identify candidate items** from the recent session:
- **New domain terms** — anything the user defined or that needed explaining.
- **Learnings** — failed approaches, dead ends, "we tried X" gotchas.
- **Parked ideas** — things mentioned but not yet decided on.
- **Frequently-referenced terms** — anything used ≥3 times this session.
- **Non-spec shipped decisions** (spec 083) — UI strings, visual/CSS choices,
translation corrections, scoped brand/icon calls settled *outside* a spec
slice. **Conditional, to avoid noise:** only surface this when the session
actually touched such product/UI/out-of-spec work — skip it entirely for
pure backend/refactor/spec sessions.
- **Load-bearing decision escape hatch** (spec 083-06 / ADR-0031) — the
enumerated surface list above is **not** a closed gate. This session-end
prompt is the **only** judgment owner for *out-of-spec* load-bearing
decisions (which have no reconciliation phase), so also surface — regardless
of which surface was touched — any decision the canonical ADR trigger
covers. Canonical wording — single-sourced from ADR-0031, drift-tested
verbatim across all four surfaces:
A load-bearing design choice with rejected alternatives — one a future agent would need to know about to avoid undoing it — warrants an ADR even when it changes no module boundary or public contract.
2. **Decide per item** which file it belongs in:
- Niche/domain term → glossary
- Failed approach / gotcha → learnings
- Unresolved/unfinished thought → inbox
- High-frequency term → hot cache (in CLAUDE.md)
- Non-spec shipped decision → `docs/decisions/lightweight-decisions.md`
3. **Invoke `memory.py` once per item** with the right command. **Always quote
the term/definition/body arguments** — terms may contain spaces, definitions
often contain punctuation:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" add-term "<name>" "<definition>" "<target>"
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" add-learning "<title>" --body "<text>" "<target>"
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" add-inbox "<text>" "<target>"
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" add-refinement-todo "<raw-markdown-chunk>" "<target>"
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" promote "<term>" "<definition>" "<target>"
```
`add-refinement-todo` appends raw text (caller composes the markdown chunk —
H2 category, deferred-/resolution-trigger structure, etc.) to
`docs/refinement-todo.md` under the parallel-session file lock (slice 028-02).
Where `<target>` is the project root (usually `.`).
**Non-spec shipped decisions use `decisions.py`, not `memory.py`** (spec
083-05): the file lives in `docs/decisions/`, not `docs/memory/`. Record one
with the idempotent helper (it appends in the file's `### [Date] — [Title]` /
Decision / Context / Scope / Commit template; re-running with the same title
is a no-op):
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/decisions.py" add-lightweight \
--title "<short title>" --decision "<what>" --context "<why>" \
--scope "<which screen / component / string / asset>" [--commit "<SHA/PR>"]
```
The helper seeds `lightweight-decisions.md` from jig's template when the
project has none (bug 012) and says so — a project that adopted jig before
the feature landed never received the file. **Never hand-write the file
yourself:** if the helper refuses because an existing file is not in jig's
format, it names both remedies — follow one, don't invent a third.
Confirm with the user before writing — it's their decision to record, not
yours to infer. If the decision clears the ADR trigger above, route it to an
ADR (`adr.py new`) instead of here.
4. **Report a summary** at the end:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" summary <target>
```
5. **Re-check the team signal** as the final step (spec 050-01). This
re-runs scaffold-init's exact team detection (≥2 distinct mailmap git
authors, monorepo-guarded). When the project has grown past solo and
`docs/memory/people.md` is absent (and no `.jig/no-people-md` opt-out
marker is present), the helper surfaces a structured nudge:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" team-check <target>
```
The advisory offers three options — `[y]` bootstrap people.md now,
`[n]` skip this run, `[never]` suppress future nudges. In an
**interactive terminal** the helper prompts and acts. In **agent
(non-TTY) context** it prints the advisory and exits 0 *without
blocking* — **you must surface the advisory to the user, ask which
option they want, and relay their choice** by re-running with the
matching flag:
```bash
# user chose [y] — create docs/memory/people.md from the template:
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" team-check --bootstrap <target>
# user chose [never] — write the opt-out marker, never ask again:
python3 "${CLAUDE_PLUGIN_ROOT}/skills/memory-sync/memory.py" team-check --never <target>
# user chose [n] — do nothing this run (they'll be asked next memory-sync).
```
`team-check` is a no-op when `people.md` already exists, when
`.jig/no-people-md` is present, or when the project is still solo —
so it is safe to run unconditionally at the end of every memory-sync.
## Judgment guidance
- **Don't over-persist.** Persisting trivia bloats memory files. If you wouldn't
want to read it back in a future session, don't write it.
- **"≥3 references" is your judgment.** The helper does not track session counts —
you decide when a term has been used enough to deserve hot-cache promotion.
- **Inbox > glossary** when in doubt. An inbox entry can be promoted later; a
premature glossary entry pollutes the searchable terminology.
- **The reviewer subagent cannot run this skill.** Reviewers read from memory but
must not write — defining the glossary is not the reviewer's job (see
`agents/reviewer.md`).
## Self-healing
If `docs/memory/` or `docs/inbox.md` don't exist (pre-scaffold-init project),
the helper creates them. If `CLAUDE.md` is absent, `promote` falls back to
`add-term` (writes to glossary) and warns on stderr. The skill works on
unscaffolded projects, though scaffold-init is the recommended setup.
## Gotchas
- `add-term` and `add-learning` are idempotent on the exact heading text. Re-running
with the same `term`/`title` is a no-op. To genuinely update an existing entry,
edit the file by hand or use Edit.
- `add-inbox` is NOT idempotent — it always appends. The inbox is a stream; near-
duplicates are tolerated and triaged later.
- `promote` is idempotent on a line-anchored `- **<term>**` match. If a term is
in the Key terms list with a slightly different label or hyphenation, it counts
as new.
- `promote` inserts new bullets immediately after the `### Key terms` heading
(LIFO — newest first). This is intentional: the most recently promoted term is
the most likely to be referenced in the next session. If alphabetical or
chronological order is preferred later, this is a design point worth revisiting.
- Definitions are stored as-is; markdown is allowed but be conservative — these
files are scanned by humans more often than parsed.