Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{
"name": "mnemo",
"description": "7 memory skills for Claude Code and Codex via Obsidian — vault audit, knowledge search, bounded cross-runtime recall, connection discovery, session handoff, memory routing, review orchestration, and setup",
"version": "1.2.6",
"version": "1.2.7",
"source": "./plugins/mnemo",
"category": "productivity",
"keywords": [
Expand Down
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

## [Unreleased]

## [1.2.7] - 2026-07-21

### Added

- **First-class "how you think" capture (`principle` / `pain` / `stance`)** — `save` gains a semantic sub-type for the user's business logic, pains, and decision stance, piggybacking on the `insight` role (no `taxonomy_roles` schema change, so it works on every existing vault without re-`setup`). These are human-authored/confirmed atomic claims — never an agent-generated dossier — recorded with a searchable `kind:` field so `[kind:pain]` is enumerable in `/mn:ask`.
- **Typed body slots** — each note's body now follows a template for its semantic type: `decision` → one Y-statement (context / choice / rejected / goal / trade-off / because); `gotcha` / business rule → GIVEN / WHEN / THEN + Because + Fails-when; `principle` / `pain` / `stance` → JTBD (Job / Pain / Done-well / Anti-goal); `fact` / `insight` → claim-title + BLUF first line + evidence. "Poured-in" polish achieved by structure, not verbosity.
- **Optional `aliases:` retrieval keys** — EN/RU synonyms or a short name so a cross-language or short query still reaches an atom (a polyglot-vault search key, not authored content).

### Changed

- **`save` splits deep material into atoms, never one blob** — a new Step 0b atomicity gate requires a claim-shaped title plus a `because` rationale per typed note (hard-gated for `decision` / actionable rule / `principle`·`pain`·`stance`; a soft nudge for a plain `fact`). Material carrying ≥2 separable claims becomes ≥2 notes plus an optional synthesis, never one exhaustive note. This keeps point-precise retrieval intact and stays inside the human-authored, non-destructive principle — no auto-ingest. The `save` description and `agents/openai.yaml` presentation are updated with the new triggers; `evals/trigger-eval.json` adds W4 positives and a near-miss.

## [1.2.6] - 2026-07-20

### Changed
Expand Down Expand Up @@ -899,7 +911,8 @@ Frontmatter now includes `session_id: {CLAUDE_SESSION_ID}` — disambiguates sam
- `config.example.json`
- MIT License

[Unreleased]: https://github.com/jojoprison/mnemo/compare/v1.2.6...HEAD
[Unreleased]: https://github.com/jojoprison/mnemo/compare/v1.2.7...HEAD
[1.2.7]: https://github.com/jojoprison/mnemo/compare/v1.2.6...v1.2.7
[1.2.6]: https://github.com/jojoprison/mnemo/compare/v1.2.5...v1.2.6
[1.2.5]: https://github.com/jojoprison/mnemo/compare/v1.2.4...v1.2.5
[1.2.4]: https://github.com/jojoprison/mnemo/compare/v1.2.3...v1.2.4
Expand Down
15 changes: 14 additions & 1 deletion docs/save.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ The brain of mnemo. When you say "remember this" or "save to memory", this skill
/mn:save "we decided to use SCOPE over TextGrad for self-correction"
/mn:save "gotcha: execSync with shell=true is banned in antomate"
/mn:save "HisPO algorithm stabilizes RL training for MoE models"
/mn:save "принцип: сначала ambitious-вариант с честными trade-offs"
/mn:save "это моя боль: вставляю стену промпта каждую сессию"
```

Or just say naturally:
Expand Down Expand Up @@ -68,10 +70,21 @@ In `~/.mnemo/config.json`:

Don't have claude-mem? Set `"enabled": false` — everything else works.

## Depth via structure, not volume

`save` never writes one exhaustive blob — depth is distributed across many atomic, claim-titled notes so a future agent can grab the exact slice. Each note's body follows a **typed slot** for its semantic type (Step 0b):

- **decision** → a single Y-statement (context / choice / rejected / goal / trade-off / because)
- **gotcha / business rule** → GIVEN / WHEN / THEN + Because + Fails-when
- **principle / pain / stance** → JTBD (Job / Pain / Done-well / Anti-goal) — captures your business logic, pains, and how you think/decide as human-authored/confirmed atoms (recorded with a searchable `kind:` field), never an agent-invented dossier
- **fact / insight** → claim-title + BLUF first line + evidence

Material with ≥2 separable claims becomes ≥2 notes (plus an optional synthesis), never a single note. Every typed note carries a claim-shaped title + a `because` rationale (hard-gated for decision / rule / pain).

## Important Notes

- **Fails visibly, never invents a shadow store** — unavailable durable backends are reported so the user can retry
- **Classifies automatically** — you don't choose a physical type; the exact five-key `taxonomy_roles` map resolves it
- **Classifies automatically** — you don't choose a physical type; the exact five-key `taxonomy_roles` map resolves it, and a narrower `kind:` sub-type shapes the body
- **Duplicate check** — always searches Obsidian before creating
- **Bundled adapters in both runtimes** — dynamic reads go through `safe-read.py`; every vault Markdown write goes through the JSON-stdin optimistic `vault-write.py`

Expand Down
7 changes: 5 additions & 2 deletions evals/trigger-eval.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
{
"about": "Trigger-eval set for mnemo skill descriptions. 6 proactive-positive prompts (a specific skill SHOULD auto-invoke) + 6 near-miss negatives (share keywords but must NOT trigger). Re-run after editing any canonical description to catch trigger regressions. Baseline 2026-07-05 (v1.1.x): 12/12 at the simulated-routing level. Format is compatible with skill-creator's run_loop.py (query + should_trigger); expect_skill/why are extra context.",
"about": "Trigger-eval set for mnemo skill descriptions. 8 proactive-positive prompts (a specific skill SHOULD auto-invoke) + 7 near-miss negatives (share keywords but must NOT trigger). Re-run after editing any canonical description to catch trigger regressions. Baseline 2026-07-05 (v1.1.x): 12/12 at the simulated-routing level. 2026-07-21 (v1.2.7): +P7/P8 for the save W4 principle·pain·stance layer, +N7 near-miss (a code-comment 'принцип', not a personal-memory save). Format is compatible with skill-creator's run_loop.py (query + should_trigger); expect_skill/why are extra context.",
"evals": [
{ "id": "P1", "query": "Сейчас буду чинить баг в auth — токен опять отваливается на рефреше, вроде уже сталкивались с похожим", "should_trigger": true, "expect_skill": "ask", "why": "recurring/previously-seen bug → recall before re-fixing" },
{ "id": "P2", "query": "Разобрался почему CI падал: race condition в setup-фикстуре, добавил await перед teardown. Наконец-то", "should_trigger": true, "expect_skill": "save", "why": "solved a tricky bug → proactive save" },
{ "id": "P3", "query": "Мне надо влезть в payments/webhooks — незнакомый модуль, хочу понять как он устроен прежде чем менять", "should_trigger": true, "expect_skill": "ask", "why": "unfamiliar subsystem → recall" },
{ "id": "P4", "query": "Окей, решили брать Redis вместо in-memory очереди — нужна персистентность между рестартами", "should_trigger": true, "expect_skill": "save", "why": "non-obvious decision → save (post-decision, not council)" },
{ "id": "P5", "query": "что мы решили про стратегию миграций схемы?", "should_trigger": true, "expect_skill": "ask", "why": "explicit recall query" },
{ "id": "P6", "query": "найди связи для только что созданной заметки про OAuth", "should_trigger": true, "expect_skill": "connect", "why": "explicit connect + new note" },
{ "id": "P7", "query": "запомни как я обычно принимаю решения — сначала ambitious-вариант с честными trade-offs, потом safe", "should_trigger": true, "expect_skill": "save", "why": "the user's decision stance / mental model → W4 principle·stance save" },
{ "id": "P8", "query": "вот моя боль: каждую сессию вставляю огромную портянку промпта чтобы получить нормальный save", "should_trigger": true, "expect_skill": "save", "why": "a user pain / business-logic → W4 pain save" },
{ "id": "N1", "query": "найди функцию parse_order в кодовой базе и покажи где она вызывается", "should_trigger": false, "why": "grep of CODE, not vault recall — near-miss ask" },
{ "id": "N2", "query": "поищи в интернете как работает OAuth PKCE flow, дай ссылки", "should_trigger": false, "why": "web search, not vault — 'поищи' overlaps, meaning differs" },
{ "id": "N3", "query": "сохрани этот файл и закоммить", "should_trigger": false, "why": "'сохрани' is about a FILE + VCS, not memory — near-miss save" },
{ "id": "N4", "query": "свяжись с бэкенд-командой насчёт API-контракта", "should_trigger": false, "why": "'свяжись' = communicate, not 'link notes' — near-miss connect" },
{ "id": "N5", "query": "проверь здоровье сервиса — дёрни /health эндпоинт прода", "should_trigger": false, "why": "service health, not vault health — near-miss health" },
{ "id": "N6", "query": "почини опечатку в переменной userNmae → userName", "should_trigger": false, "why": "trivial fix, not a recurring bug — ask must NOT fire" }
{ "id": "N6", "query": "почини опечатку в переменной userNmae → userName", "should_trigger": false, "why": "trivial fix, not a recurring bug — ask must NOT fire" },
{ "id": "N7", "query": "запиши в комментарии к функции принцип работы алгоритма сортировки", "should_trigger": false, "why": "'принцип'/'запиши' about a CODE comment, not the user's personal mental model — near-miss save (W4)" }
]
}
2 changes: 1 addition & 1 deletion plugins/mnemo/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "mn",
"displayName": "mnemo",
"version": "1.2.6",
"version": "1.2.7",
"description": "Persistent memory layer for Claude Code and Codex via Obsidian — 7 skills for vault health, knowledge search, verified cross-runtime project recall, connection discovery, session continuity, memory routing, skill-aware session review, and interactive setup. Bundled JSON-stdin atomic vault writer, argv-safe indexed reads, dual-runtime helpers, hybrid model routing, parallel CLI calls, SessionStart prewarm, incremental JSONL parsing, shared references, and semantic taxonomy roles.",
"author": {
"name": "jojoprison",
Expand Down
2 changes: 1 addition & 1 deletion plugins/mnemo/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mnemo",
"version": "1.2.6",
"version": "1.2.7",
"description": "Persistent memory layer for Codex and Claude Code via Obsidian: vault health, knowledge search, verified cross-runtime project recall, link discovery, session notes, memory routing, review orchestration, and setup.",
"author": {
"name": "jojoprison",
Expand Down
21 changes: 21 additions & 0 deletions plugins/mnemo/references/config-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ Two optional fields override the config cadence on a single note. Neither is wri

This is deliberately **not** an absolute `review-by:` date. Computed-from-type plus an optional relative `ttl` does not rot the way a hand-typed future date does, and avoids the "guilt-debt" failure mode where stale review dates pile up as unactioned nags.

## Optional per-note frontmatter (retrieval)

Two optional fields sharpen retrieval; both are written by `save` (see `Step 0b` in `../skills/save/SKILL.md`), never required:

| Field | Meaning | Example |
|-------|---------|---------|
| `kind` | Semantic sub-type when it is **narrower** than the taxonomy role: `decision`/`gotcha` (on the `fact` role), `principle`/`pain`/`stance` (on the `insight` role). Makes `[kind:pain]` property-searchable in `/mn:ask`. Omit for a plain `fact`/`insight`/`source` — there it would only echo the role | `kind: pain` |
| `aliases` | Retrieval keys — EN/RU synonyms or a short name so a cross-language or short query still finds the note. A search key, **not** authored content; add only when a future search would plausibly use a different term than the title | `aliases: [save redesign, редизайн save]` |

## Defaults when fields are missing

If the whole `cascade` section is absent, defaults are: obsidian=true, claude_mem=false, memory_dir=true, project_rules=true, claude_md=false.
Expand Down Expand Up @@ -202,6 +211,18 @@ The PARA role map above is the setup suggestion: durable knowledge defaults to `

**Atom vs Molecule:** if one source note supports the claim → Atom. If the insight only emerges by combining ≥2 → Molecule. "Linked two notes" alone is not a Molecule.

## Semantic sub-types (the `kind` field)

The five `taxonomy_roles` are the physical routing targets; a note may also carry a narrower **semantic sub-type** in `kind:` that shapes its body (typed slots) without changing where it is stored. These piggyback on a role — no schema change, works on every vault:

| `kind` | Piggybacks on role | Body slot (see `save` Step 0b) |
|--------|--------------------|-------------------------------|
| `decision` | `fact` | Y-statement: context / choice / rejected / goal / trade-off / because |
| `gotcha` | `fact` | GIVEN / WHEN / THEN + Because + Fails-when |
| `principle` / `pain` / `stance` | `insight` | JTBD: Job / Pain (func·emo·social) / Done-well / Anti-goal |

`principle`/`pain`/`stance` capture the **user's** business logic, pains, and decision stance as human-authored/confirmed atomic claims — never an agent-generated dossier (that would be the rejected auto-ingest fork; see `../../../docs/design-decisions.md`). A plain `fact`/`insight`/`source` note omits `kind:`.

## Internationalization

`links_section` is the natural i18n point. Russian vaults use `## Связи`, English `## Links`, Chinese `## 链接`, etc. All skills honor whatever string is set.
Loading
Loading