8213ff750a
- rewrite ucnl-market-memory/SKILL.md with final layout (accounts/products/campaigns/markets + insights/conversations/inbox), extended frontmatter (sensitive flag), domain routing table with border examples - refresh obsidian-memory/SKILL.md with the same domain-routing section placed at top, matching examples, and updated description with negative trigger
315 lines
19 KiB
Markdown
315 lines
19 KiB
Markdown
---
|
||
name: obsidian-memory
|
||
description: Protocol for using creator/obsidian-vault (Gitea repo at h3fq32.golive.ru) as Claude's long-term memory for personal and R&D projects of Arthur Abelentsev. Trigger when the user references past work ("my X project", "we decided Y", "remember that..."), asks Claude to remember/save/update/forget something, mentions a project by name (lotus-eletre, uspeak-trademark, homework-*, 1c-<client>, pcb-*, obsidian, claude-skills), or whenever a substantive insight, decision, or fact surfaces that's worth preserving between sessions. Covers personal context, infrastructure (gitea/traefik/mikrotik/xray), embedded firmware, PCB design, 1C consulting for any client, R&D on UCN products (acoustics, firmware, algorithms), legal/trademark work, travel, vehicle/hardware, and general life. Also covers answering non-trivial project questions that benefit from previously stored context. Describes vault layout, frontmatter conventions, Gitea REST API mechanics (read/list/search/create/update), naming rules, and write permissions. Do NOT trigger for: simple one-off technical questions or casual chat that doesn't involve the user's ongoing projects. Do NOT trigger for UCN marketing/sales commercial work (clients, distributors, quotes, exhibitions, pricing, product marketing for uWave/Zima2/uSpeak) — that is handled by a separate ucnl-market-memory skill and a separate repo (ucnlmarket/ucnl-market-memory).
|
||
---
|
||
|
||
# obsidian-memory
|
||
|
||
Протокол работы с `creator/obsidian-vault` как долговременной памятью.
|
||
Vault — обычный git-репо в Gitea, хранит markdown-заметки с YAML-frontmatter.
|
||
Claude читает и пишет заметки через Gitea REST API.
|
||
|
||
## Разграничение доменов — прочитать первым
|
||
|
||
У пользователя **два репо памяти** с жёстким разделением:
|
||
|
||
| Домен | Репо | Скилл |
|
||
|---|---|---|
|
||
| Личные проекты Артура, инфраструктура, embedded, 1С-консалтинг (любые клиенты), R&D по UCN-продуктам, legal/trademark, быт | `creator/obsidian-vault` | **этот скилл** |
|
||
| Маркетинг и продажи UCN (клиенты, дистрибьюторы, выставки, КП, экспорт, product marketing uWave/Zima2/uSpeak/USBL) | `ucnlmarket/ucnl-market-memory` | `ucnl-market-memory` |
|
||
|
||
**Правило жёсткое:** материалы из одного домена НЕ попадают в репо
|
||
другого. Если тема пограничная — спросить пользователя, не додумывать.
|
||
|
||
**Примеры границы:**
|
||
|
||
| Запрос | Куда |
|
||
|---|---|
|
||
| «Прошивка uWave — обновить через STM32CubeProg» | R&D → **этот скилл** |
|
||
| «Письмо Mavi Marine по срокам поставки» | sales UCN → `ucnl-market-memory` |
|
||
| «Расчёт TDOA для uWave USBL» | R&D/алгоритмы → **этот скилл** |
|
||
| «Слайд для INNOPROM KSA 2026» | маркетинг UCN → `ucnl-market-memory` |
|
||
| «ТЗ на 1С для Teplovin» | 1С не-UCN → **этот скилл** |
|
||
| «Скидка дистрибьютору X» | sales UCN → `ucnl-market-memory` |
|
||
|
||
«UCN как клиент внутреннего 1С-проекта» — дефолт этот скилл (технический
|
||
слой), но с коммерческой частью (бюджет, контракт) — уточнить.
|
||
|
||
## Where things live
|
||
|
||
- **Gitea:** `https://git.h3fq32.golive.ru`
|
||
- **Repo:** `creator/obsidian-vault`
|
||
- **Branch:** `main`
|
||
- **Access:** `bash_tool` + `curl` с `Authorization: token $GITEA_TOKEN`
|
||
|
||
Токен должен быть в окружении (`$GITEA_TOKEN`) или в сессионном контексте.
|
||
Если ни там, ни там его нет — попросить пользователя один раз в начале,
|
||
в последующих вызовах использовать.
|
||
|
||
## Vault layout
|
||
|
||
```
|
||
00-inbox/ user's raw notes, READ-ONLY for Claude
|
||
10-projects/ active projects (lotus-eletre/, uspeak/, …), READ-ONLY
|
||
20-knowledge/ reference (1c/, embedded/, infrastructure/), READ-ONLY
|
||
30-daily/ daily log, meetings, READ-ONLY
|
||
claude/ Claude's own space, READ-WRITE
|
||
├── memory/
|
||
│ ├── facts.md stable facts (one file, append-only section)
|
||
│ ├── preferences.md user preferences and standards
|
||
│ ├── projects/
|
||
│ │ └── <slug>.md cumulative per-project context
|
||
│ └── 1c/ отдельная область: 1С-экосистема пользователя
|
||
│ ├── README.md протокол + конвенции именно для 1С
|
||
│ ├── configurations/ КА, ERP, УТ, ЗУП — по конфигурациям
|
||
│ ├── projects/ клиентские 1С-внедрения
|
||
│ └── files/ шаблоны и эталонные документы
|
||
│ ├── README.md
|
||
│ └── list.md реестр: имя файла ↔ описание
|
||
├── insights/ dated observations: YYYY-MM-DD-<slug>.md
|
||
├── conversations/ session summaries: YYYY-MM-DD-<slug>.md
|
||
└── inbox/ drafts for user review
|
||
```
|
||
|
||
**Areas vs projects:** `claude/memory/projects/` — разовый контекст
|
||
одного проекта в одном файле. `claude/memory/<area>/` — целая
|
||
тематическая область со своей подструктурой. Сейчас такая есть одна
|
||
(`1c/`), могут появиться ещё (`embedded/`, `infrastructure/` если
|
||
разрастётся из `facts.md`). Решение «один файл vs целая папка»
|
||
принимается по тому, нужна ли внутренняя структура (конфигурации,
|
||
клиенты, паттерны) — если да, это область.
|
||
|
||
### 1С — special case
|
||
|
||
В начале любого разговора, где всплывают 1С-темы (конфигурации КА/ERP/УТ/ЗУП,
|
||
внедрения, BSL-код, интеграции с Bitrix24, ТЗ на 1С-проекты):
|
||
|
||
1. Прочитать `claude/memory/1c/README.md` — там протокол
|
||
2. Листинг `configurations/` и `projects/` — увидеть актуальный набор
|
||
3. Прицельно 2–3 релевантных файла
|
||
4. Параллельно — skill `1c-analyst` для процедурных знаний
|
||
(как делать); vault — для «что у пользователя конкретно есть и как»
|
||
|
||
**Если запрос подразумевает генерацию документа** (приказ, ТЗ, регламент,
|
||
проектная документация, типовое письмо) — дополнительно:
|
||
|
||
5. Прочитать `claude/memory/1c/files/list.md` — это реестр шаблонов
|
||
6. Если в таблице есть подходящий по смыслу шаблон — скачать файл
|
||
через Gitea raw-endpoint, открыть через соответствующий skill
|
||
(`docx`/`xlsx`/`pdf-reading`), использовать как основу
|
||
7. Если подходящего шаблона нет — сгенерировать с нуля, в конце
|
||
предложить пользователю сохранить результат в `files/` как новый
|
||
шаблон (тогда одним коммитом: файл + строка в `list.md`)
|
||
|
||
**Важно:** файл в `files/` без строки в `list.md` для Claude не
|
||
существует. При любом добавлении/обновлении — реестр дописывается.
|
||
|
||
**Write rule:** Claude пишет *только* в `claude/**`. Всё остальное —
|
||
read-only. Если кажется что стоит дополнить `20-knowledge/…` — положить
|
||
в `claude/inbox/` с пометкой «proposed addition to <path>» и отдать
|
||
пользователю на ревью.
|
||
|
||
## Frontmatter
|
||
|
||
Каждый файл в `claude/**` начинается с YAML-frontmatter:
|
||
|
||
```yaml
|
||
---
|
||
type: memory | insight | conversation | fact | preference
|
||
project: <slug> # опционально; lotus-eletre, uspeak, и т.п.
|
||
tags: [<tag1>, <tag2>] # свободная форма, kebab-case
|
||
created: YYYY-MM-DD
|
||
updated: YYYY-MM-DD
|
||
relevance: 0.0-1.0 # оценка важности, используется при ранжировании
|
||
confidence: low | medium | high
|
||
private: false # true → не использовать в ответах, не упоминать наличие
|
||
sources: # опционально: откуда знание пришло
|
||
- conversation: 2026-04-19-lotus-yaw-calibration
|
||
- url: https://…
|
||
---
|
||
```
|
||
|
||
`private: true` — сильное правило. Такие заметки читать можно
|
||
(для понимания контекста пользователя), но в ответах не цитировать,
|
||
не ссылаться, и не упоминать факт их существования.
|
||
|
||
## Protocol
|
||
|
||
### 1. В начале содержательного разговора
|
||
|
||
Если разговор касается проекта/системы/темы, по которым у пользователя
|
||
может быть накопленный контекст:
|
||
|
||
1. **Проверить домен.** Если это маркетинг/продажи UCN — СТОП,
|
||
переключиться на `ucnl-market-memory` skill.
|
||
2. **Поиск по теме.** Content-поиск по vault через API:
|
||
```
|
||
GET /api/v1/repos/creator/obsidian-vault/search?q=<keyword>&type=code
|
||
```
|
||
Альтернатива для поиска по frontmatter-полю — grep по всем файлам в
|
||
`claude/memory/projects/`:
|
||
```
|
||
GET /api/v1/repos/creator/obsidian-vault/contents/claude/memory/projects
|
||
```
|
||
3. **Читаем top-3..5 самых релевантных.** Приоритет: свежесть (`updated`),
|
||
явный `project` match, высокий `relevance`. Исключить `private: true`
|
||
из ответов (но прочитать можно).
|
||
4. **Использовать контекст** в ответе естественно, без меты про «я
|
||
нашёл заметку...».
|
||
|
||
### 2. Когда НЕ искать
|
||
|
||
- Простые технические вопросы без персонального контекста
|
||
(«как в Python отсортировать список по ключу»)
|
||
- Разговорная болтовня, приветствия
|
||
- Одноразовые операции
|
||
- Вопросы, где пользователь сам дал весь нужный контекст в сообщении
|
||
- Темы маркетинга/продаж UCN — это не сюда
|
||
|
||
### 3. В процессе разговора
|
||
|
||
- При упоминании сущностей, имеющих свою заметку в vault, использовать
|
||
`[[wiki-links]]` в новых заметках (пригодится для навигации в Obsidian)
|
||
- Если обнаружилось противоречие между памятью и тем что говорит
|
||
пользователь сейчас — честно сказать («в заметках было X, сейчас Y —
|
||
обновить?»), не тихо исправлять
|
||
|
||
### 4. В конце содержательного разговора
|
||
|
||
Если всплыли значимые инсайты / факты / решения — сохранить:
|
||
|
||
| Что появилось | Куда класть |
|
||
|---|---|
|
||
| Одноразовое наблюдение по проекту | `claude/insights/YYYY-MM-DD-<slug>.md` |
|
||
| Накопительный контекст по проекту (обновляется) | `claude/memory/projects/<slug>.md` |
|
||
| Стабильный факт общего характера | `claude/memory/facts.md` (append в секцию) |
|
||
| Предпочтение пользователя | `claude/memory/preferences.md` |
|
||
| Выжимка самой беседы | `claude/conversations/YYYY-MM-DD-<slug>.md` |
|
||
| Сомневаешься куда — | `claude/inbox/` + explicit note пользователю |
|
||
|
||
**Не писать ради галочки.** Лучше 0 файлов, чем пять пустословных.
|
||
Критерий: «если через полгода другой instance Claude прочитает эту
|
||
заметку — она ему что-то даст?».
|
||
|
||
## Gitea REST API — шпаргалка
|
||
|
||
```bash
|
||
GITEA=https://git.h3fq32.golive.ru
|
||
REPO=creator/obsidian-vault
|
||
TOKEN=$GITEA_TOKEN # или подставить вручную
|
||
|
||
# ── READ ────────────────────────────────────────────────────────────────────
|
||
|
||
# Прочитать файл (raw содержимое)
|
||
curl -sS -H "Authorization: token $TOKEN" \
|
||
"$GITEA/api/v1/repos/$REPO/raw/claude/memory/facts.md"
|
||
|
||
# Листинг папки (metadata всех файлов)
|
||
curl -sS -H "Authorization: token $TOKEN" \
|
||
"$GITEA/api/v1/repos/$REPO/contents/claude/memory/projects?ref=main" \
|
||
| python3 -c "import sys,json; [print(x['path'], x['size']) for x in json.load(sys.stdin)]"
|
||
|
||
# Content-поиск (требует включённый индекс на уровне инстанса Gitea)
|
||
curl -sS -H "Authorization: token $TOKEN" \
|
||
"$GITEA/api/v1/repos/$REPO/search?q=eletre+alignment&type=code"
|
||
|
||
# Tree (вся структура целиком с recursive)
|
||
curl -sS -H "Authorization: token $TOKEN" \
|
||
"$GITEA/api/v1/repos/$REPO/git/trees/main?recursive=true"
|
||
|
||
# ── WRITE ───────────────────────────────────────────────────────────────────
|
||
|
||
# Создать новый файл (POST contents). Содержимое — base64.
|
||
content_b64=$(base64 -w0 /tmp/note.md)
|
||
curl -sS -X POST -H "Authorization: token $TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
"$GITEA/api/v1/repos/$REPO/contents/claude/insights/2026-04-19-foo.md" \
|
||
-d "{
|
||
\"message\": \"claude: insight on X\",
|
||
\"content\": \"$content_b64\",
|
||
\"branch\": \"main\"
|
||
}"
|
||
|
||
# Обновить существующий файл (PUT, нужен sha текущей версии)
|
||
sha=$(curl -sS -H "Authorization: token $TOKEN" \
|
||
"$GITEA/api/v1/repos/$REPO/contents/claude/memory/facts.md?ref=main" \
|
||
| python3 -c "import sys,json; print(json.load(sys.stdin)['sha'])")
|
||
content_b64=$(base64 -w0 /tmp/facts-new.md)
|
||
curl -sS -X PUT -H "Authorization: token $TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
"$GITEA/api/v1/repos/$REPO/contents/claude/memory/facts.md" \
|
||
-d "{
|
||
\"message\": \"claude: update facts — add Eletre calibration notes\",
|
||
\"content\": \"$content_b64\",
|
||
\"sha\": \"$sha\",
|
||
\"branch\": \"main\"
|
||
}"
|
||
|
||
# Batch (несколько файлов одним коммитом) — POST contents БЕЗ пути
|
||
curl -sS -X POST -H "Authorization: token $TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
"$GITEA/api/v1/repos/$REPO/contents" \
|
||
-d '{
|
||
"branch": "main",
|
||
"message": "claude: session summary with 2 artefacts",
|
||
"files": [
|
||
{"operation":"create", "path":"claude/conversations/…", "content":"<b64>"},
|
||
{"operation":"update", "path":"claude/memory/projects/…", "content":"<b64>", "sha":"<prev-sha>"}
|
||
]
|
||
}'
|
||
```
|
||
|
||
## Gotchas (learned the hard way)
|
||
|
||
1. **`content`, не `content_base64`.** В `POST /contents` (включая batch)
|
||
поле называется `content`. Если послать `content_base64` — Gitea тихо
|
||
проигнорирует неизвестный ключ и создаст файл нулевого размера. Файл
|
||
«появится», коммит пройдёт, а содержимое будет пустое.
|
||
2. **URL-encode путей.** Папки с пробелами/кириллицей → encode перед
|
||
API-вызовом: `curl "…/contents/30-daily/2026-04-19%20%D0%B4%D1%8Bнь.md"`.
|
||
3. **`PUT` требует `sha` текущей версии.** Забыл sha — получишь 409.
|
||
Всегда перечитывать перед update'ом.
|
||
4. **Новый репо «пустой» после `auto_init=true`.** Первый commit через
|
||
API создаёт initial commit и ветку main. До этого момента API
|
||
`?ref=main` возвращает 404.
|
||
5. **Rate limit.** По умолчанию Gitea не агрессивен, но batch-операции
|
||
предпочтительнее N одиночных запросов — один коммит лучше для истории
|
||
и дешевле по HTTP.
|
||
|
||
## Commit message format
|
||
|
||
Все коммиты Claude в vault — префикс `claude:`:
|
||
|
||
- `claude: save <тема> from conversation` — новая заметка
|
||
- `claude: update <путь> — <что именно>` — правка
|
||
- `claude: merge <откуда> → <куда>` — переорганизация
|
||
- `claude: remove <путь> — <причина>` (редко; чаще `private: true`)
|
||
|
||
Это позволяет пользователю легко фильтровать `git log | grep ^claude:`
|
||
и понять что делал Claude в vault.
|
||
|
||
## Naming
|
||
|
||
- `claude/insights/YYYY-MM-DD-<slug>.md` — slug kebab-case, ASCII
|
||
- `claude/conversations/YYYY-MM-DD-<slug>.md` — аналогично
|
||
- `claude/memory/projects/<slug>.md` — slug совпадает с
|
||
`10-projects/<slug>/` если проект существует
|
||
- `claude/memory/<topic>.md` — accumulating files (facts, preferences)
|
||
|
||
Русские названия → транслит или короткий англ. эквивалент.
|
||
`лотос-настройка-развала` → `lotus-alignment`.
|
||
|
||
## Boundaries
|
||
|
||
- **Не писать в пользовательские папки** (00–30). Если нужно предложить
|
||
изменение — в `claude/inbox/` с пометкой.
|
||
- **Не удалять пользовательские файлы никогда.** Свои (`claude/**`) —
|
||
можно, если очевидно устарело; предпочтительнее `private: true` чем
|
||
удаление (история сохраняется в git, но из выдачи исчезает).
|
||
- **Не обходить `private: true`.** Такие заметки не цитировать
|
||
и не упоминать.
|
||
- **Честно флагить противоречия** между тем что в vault и что говорит
|
||
пользователь, не исправляя молча.
|
||
- **Не писать в `ucnlmarket/ucnl-market-memory` из этого контекста.**
|
||
Если тема всплыла UCN-sales — переключиться на `ucnl-market-memory` skill.
|