feat(mappa-knowledge): merge using-wiki + using-wiki-graph → mappa-knowledge v1.0.0 (cycle ingest/query/lint + graph layer, guarded failure-mode, old names = trigger synonyms) [skip-tdd: visual]
This commit is contained in:
261
skills/mappa-knowledge/SKILL.md
Normal file
261
skills/mappa-knowledge/SKILL.md
Normal file
@@ -0,0 +1,261 @@
|
||||
---
|
||||
name: mappa-knowledge
|
||||
author: ours
|
||||
version: 1.0.0
|
||||
description: >
|
||||
Цикл работы со знаниями проекта в Mappa (Karpathy LLM Wiki, канал =
|
||||
mappa-сущности): ingest → query → lint + граф-слой для
|
||||
реляционных/структурных вопросов. Поглощает using-wiki + using-wiki-graph
|
||||
(старые имена — триггер-синонимы). Триггеры: «заингесть», «обнови вики»,
|
||||
«запроси вики», «проверь вики», «use project wiki», «query the wiki»,
|
||||
«что связывает X и Y», «как связаны», «путь между X и Y», «what connects
|
||||
X and Y», «что ссылается на X», «backlinks of X», «сироты», «битые ссылки»,
|
||||
«orphan pages». Wiki = сущности type=wiki (чтение — карв-аут лиза; запись —
|
||||
под лизом проекта, решение 19). Реляционные вопросы — через graph_* (BFS на
|
||||
стороне сервиса), guarded failure-mode: одна страница и стоп, без
|
||||
многохоповых цепочек чтением. Skip для одно-страничных контентных вопросов.
|
||||
---
|
||||
|
||||
# mappa-knowledge
|
||||
|
||||
Единый цикл работы со знаниями проекта в **Mappa**: три операции (ingest /
|
||||
query / lint) + **граф-слой** для реляционных и структурных вопросов. Скилл =
|
||||
цикл, не тул: знание **компилируется один раз и держится актуальным**
|
||||
(ingest), к нему обращаются (query), его проверяют (lint), а связи между
|
||||
сущностями читают через граф (graph_*).
|
||||
|
||||
Канал — Mappa (`mcp__mappa__*`), НЕ файлы. Страница — сущность `type=wiki`
|
||||
(`wiki:N`); чтение — карв-аут лиза, запись — под лизом проекта (решение 19).
|
||||
Файлового `.wiki/` больше нет; `setup-wiki` умер (нечего настраивать).
|
||||
|
||||
## Когда использовать
|
||||
|
||||
- Заингестить документ/источник в вики («заингесть X», «обнови вики»).
|
||||
- Ответить из вики / проверить вики («запроси вики», «проверь вики», lint).
|
||||
- Реляционный/структурный вопрос («что связывает X и Y», «backlinks», «сироты») — граф-слой.
|
||||
- Модифицировать любую страницу — форматы ниже обязательны; конвенции проекта
|
||||
живут в `AGENTS`-сущности (legacy — `CLAUDE`-указатель).
|
||||
|
||||
**НЕ для:** разовых вопросов по коду (обычное чтение файлов), однофайловых
|
||||
README/ADR (не персистентная база знаний), проекта без вики в mappa.
|
||||
|
||||
## Три слоя (не смешивать)
|
||||
|
||||
1. **Raw-источники** — `sources/<slug>` страницы. Иммутабельны: читай, не
|
||||
редактируй (единственное исключение — блок-цитата `> Status` по явной
|
||||
просьбе пользователя).
|
||||
2. **Вики** — остальные страницы (entities/concepts/packages/contradictions/open-questions/overview).
|
||||
3. **Схема** — сущности `AGENTS` (канон, slug `AGENTS`) + `CLAUDE` (legacy-
|
||||
указатель «Canon is AGENTS»). Читай `AGENTS` первой; она перекрывает этот
|
||||
скил при конфликте.
|
||||
|
||||
## Первый шаг любой операции
|
||||
|
||||
1. `mcp__mappa__wiki_get(project, 'AGENTS')` — если есть, читай (канон; если
|
||||
нет — `wiki_get(project, 'CLAUDE')`, легаси-указатель).
|
||||
2. `mcp__mappa__wiki_get(project, 'index')` — каталог; найди нужные страницы.
|
||||
(Каталог по умолчанию — `entity_search`, решение 1; `index` — опора ориентации.)
|
||||
3. Только потом действуй.
|
||||
|
||||
Если `AGENTS`/`CLAUDE` нет — вики либо новая, либо неухоженная: не
|
||||
импровизируй структуру, первый ingest создаёт `AGENTS` (+ `CLAUDE`-указатель).
|
||||
|
||||
## MCP-поверхность
|
||||
|
||||
| Операция | Тул | Примечание |
|
||||
|---|---|---|
|
||||
| Чтение страницы | `mcp__mappa__wiki_get(project?, slug)` | чтение — карв-аут (решение 19) |
|
||||
| Поиск страниц | `mcp__mappa__entity_search(q, type='wiki', project?, scope?, limit)` | ILIKE по body/title |
|
||||
| Лиз для записи | `mcp__mappa__task_claim_next(project, owner)` | → `token`; таска может отсутствовать |
|
||||
| Продление лиза | `mcp__mappa__task_heartbeat(project, claim_token)` | долгие ingest-циклы |
|
||||
| Создать страницу | `mcp__mappa__wiki_create(project, slug, body, claim_token)` | под лизом |
|
||||
| Обновить страницу | `mcp__mappa__wiki_update(project, id, title?, body?, claim_token)` | под лизом; id — internal |
|
||||
| Путь между сущностями | `mcp__mappa__graph_path({from, to})` | кратчайшая цепочка, BFS |
|
||||
| Соседи / исходящие | `mcp__mappa__graph_neighbors({id})` | рёбра узла с резолвом целей |
|
||||
| Входящие ссылки | `mcp__mappa__graph_backlinks({id})` | кто ссылается на узел |
|
||||
| Здоровье графа | `mcp__mappa__graph_stats()` | nodes/edges/components |
|
||||
|
||||
**Запись всегда под лизом.** Мутации wiki гейтятся лизом проекта: без
|
||||
валидного `claim_token` — 422 busy. Лиз экспирится по TTL (дефолт 600s);
|
||||
закрыть вручную нечем (кроме `admin_release_lease` для залипших) — пиши,
|
||||
затем отпусти (не держи лиз на время чтения/размышлений).
|
||||
|
||||
**Рефы и id (#1037/#1028).** Публичная поверхность несёт per-type реф полным
|
||||
именем первым полем: `ref: "wiki:3"` (решение 20, конвенция #1028), `num`
|
||||
следом, глобальный `id` — internal (последним). Для `wiki_update` нужен
|
||||
internal `id` — из ответа `wiki_get`/`entity_search`. В прозе — слаг/имя
|
||||
первым, реф как якорь: «спека `concepts/session-live-ingest` (wiki:2604)».
|
||||
В теле страниц — викилинки по слагу (`[[concepts/foo]]`, решение 4) или
|
||||
per-type рефы полными именами (`[[task:N]]`/`[[inbox:N]]`).
|
||||
|
||||
---
|
||||
|
||||
## Цикл: три операции
|
||||
|
||||
### Ingest — «заингесть X»
|
||||
|
||||
1. Прочитай источник полностью.
|
||||
2. Извлеки: entities, concepts, packages, кросс-резы.
|
||||
3. Создай `sources/<slug>` — одну страницу-резюме на источник (~50–150 строк;
|
||||
ссылку на raw клади в frontmatter `raw_path` + `ingested:`).
|
||||
4. Для каждой затронутой страницы:
|
||||
- есть → обнови (`wiki_update(project, id, body, claim_token)`). **Противоречия
|
||||
помечай явно** блоком `> **Противоречие:** источник A говорит X, источник B — Y`.
|
||||
Не затирай молча.
|
||||
- нет → создай (`wiki_create`).
|
||||
5. Обнови `index` (каталог: одна строка на страницу) — опционально; каталог
|
||||
по умолчанию — `entity_search` (решение 1).
|
||||
6. Отчитайся пользователю: что создано, что обновлено, какие противоречия.
|
||||
Первый ingest новой вики: создай `AGENTS` (канон) + `CLAUDE` (указатель).
|
||||
|
||||
**Оп-лог — автоматический.** Каждая write-операция уже пишется сервисом в
|
||||
таблицу `logs` (component=тип сущности, message=slug+operation; смотреть —
|
||||
`mcp__mappa__admin_logs`). Ручную `log`-страницу НЕ веди — это дубль,
|
||||
аудит-след живёт в сервисе (решение 12, ратификация 2026-08-24).
|
||||
|
||||
**Один ingest может затронуть 10–15 страниц. Это нормально — для того LLM и нужны.**
|
||||
|
||||
Порядок записи: сначала лиз (`task_claim_next`), затем все wiki-мутации одним
|
||||
циклом (не бери лиз на чтение), затем отпусти (лиз живёт TTL — просто закончи
|
||||
писать; heartbeat только если цикл реально долгий).
|
||||
|
||||
### Query — вопрос по вики
|
||||
|
||||
1. Читай `index` сначала, затем углубляйся в страницы (`wiki_get` по слагу).
|
||||
2. Отвечай с цитатами-викилинками: `[[concepts/foo]]` (рёбра создаются при
|
||||
записи, решение 4).
|
||||
3. **Компаундируй вики.** Если ответ — реальный синтез (сравнение, анализ,
|
||||
новая связь) — спроси пользователя: «Сохранить как страницу wiki?» Хорошие
|
||||
вопросы становятся страницами в `concepts/`.
|
||||
|
||||
**Реляционные/структурные вопросы — не читай, а зови граф** (следующая секция):
|
||||
связи образуют граф, который LLM не обходит надёжно чтением.
|
||||
|
||||
### Lint — «проверь вики»
|
||||
|
||||
Ищи:
|
||||
- **Противоречия** между страницами.
|
||||
- **Сирот** — страницы без входящих ссылок: `graph_backlinks(id)` (id из
|
||||
`wiki_get`) → нет входящих рёбер = сирота.
|
||||
- **Stale-claims** — `updated_at` страницы старше источника, который она резюмирует.
|
||||
- **Потерянные сущности** — понятия из текста без своей страницы
|
||||
(`entity_search` по имени → пусто).
|
||||
- **Пустые/TODO-секции.**
|
||||
|
||||
Отчёт — панч-лист. Ничего не удаляй автоматически.
|
||||
|
||||
---
|
||||
|
||||
## Граф-слой (реляционные/структурные вопросы)
|
||||
|
||||
**Stop and call the graph.** На реляционный/структурный вопрос о вики или
|
||||
любых сущностях mappa (таски, письма, сессии) **не отвечай, прочитав одну
|
||||
страницу** — это 0%-recall провал, ради которого существует граф-слой.
|
||||
Сервис ходит по рёбрам детерминированно (BFS) и возвращает ответ в
|
||||
нескольких строках; контекст не засоряется.
|
||||
|
||||
Формы вопроса → тул:
|
||||
|
||||
| Вопрос | Тул |
|
||||
|---|---|
|
||||
| relational — «что связывает X и Y», «путь между», "what connects", "shortest path" | `graph_path({from, to})` |
|
||||
| neighbourhood — «соседи X», "neighbours of X" | `graph_neighbors({id})` |
|
||||
| incoming — «кто ссылается на X», «backlinks», "what links to X" | `graph_backlinks({id})` |
|
||||
| health — «сироты», «битые ссылки», «здоровье вики», "orphan pages" | `graph_stats()` + `graph_backlinks(id)` |
|
||||
|
||||
**Адресация: slug → internal id.** Резолвь `id` через `wiki_get`/`entity_search`
|
||||
(последнее поле ответа; `ref`/`num` — для показа). Ответы graph несут per-type
|
||||
refs полными именами (`task:N`/`inbox:N`/`wiki:N`, конвенция #1028) — реферируй
|
||||
по ним, не по id. Пустой `path` = связи реально нет — так и скажи; не выдумывай
|
||||
цепочку из текстовой близости.
|
||||
|
||||
**Precondition — граф реально связан.** Если сомневаешься — сначала
|
||||
`graph_stats()`: `edges` ≈ 0 ⇒ граф пуст, отвечай чтением. (Слаги без
|
||||
[[линков]] рёбер не создают; сироты — норма для разреженных вики.)
|
||||
|
||||
---
|
||||
|
||||
## Форматы страниц (ОБЯЗАТЕЛЬНО)
|
||||
|
||||
### Frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Человекочитаемое имя
|
||||
type: entity | concept | package | source | contradiction | open-question | overview
|
||||
tags: [short, tokens]
|
||||
sources: [concepts/mappa.md]
|
||||
updated: 2026-08-24
|
||||
---
|
||||
```
|
||||
|
||||
Страницы `sources/` дополнительно несут `ingested: YYYY-MM-DD` и `raw_path: …`.
|
||||
`contradictions/` — `status: open | resolved | accepted-divergence` и `affects:`.
|
||||
`open-questions/` — `status: open | answered | obsolete` и `touches:`.
|
||||
|
||||
### Слаги
|
||||
|
||||
- `kebab-case`, **только латиница**. Кириллицу/др. скрипты транслитерируй
|
||||
(`план переписывания` → `ozon-client-rewrite`). Оригинальный title — в H1 и frontmatter.
|
||||
- `entities/<name>`, `concepts/<name>`, `packages/<name>`, `sources/<slug>`,
|
||||
`contradictions/<slug>`, `open-questions/<slug>`.
|
||||
|
||||
### Оп-лог — таблица `logs`, не страница
|
||||
|
||||
File-based `log.md` мёртв (решение 12/15, ратификация 2026-08-24). Сервис пишет
|
||||
оп-лог сам при каждой write-операции: `mcp__mappa__admin_logs` (фильтры
|
||||
level/since/component/entity, retention 14d). Ручную `log`-страницу не заводи,
|
||||
не дописывай, не парси.
|
||||
|
||||
### `index` — каталог через поиск
|
||||
|
||||
Каталог = `entity_search(q, type='wiki', project)` (решение 1). `index`-страница
|
||||
— опциональная опора для ориентации: одна строка на страницу
|
||||
`- [Title](concepts/foo.md) — hook.`, секции по типам. Обновляй только если
|
||||
страница уже существует; не плоди каталог-дубли.
|
||||
|
||||
## Quick reference
|
||||
|
||||
| Ситуация | Что трогаем |
|
||||
|---|---|
|
||||
| Ingest одного документа | `sources/<slug>` (новая) + 3–15 entities/concepts/packages (+ опционально `index`) |
|
||||
| Query | (чтение) + возможно новая страница |
|
||||
| Query реляционный | graph_* (BFS), не чтение |
|
||||
| Lint | (чтение) + graph_backlinks/stats для сирот |
|
||||
| Новая вики проекта | первый ingest создаёт `AGENTS` + `CLAUDE`-указатель; оп-лог — автоматический |
|
||||
|
||||
## Частые ошибки
|
||||
|
||||
- **Правка `sources/`.** Нельзя. Только статус-блок по явной просьбе.
|
||||
- **Дамп сырья в `sources/`.** Резюме — это резюме. Ссылайся на raw, не копируй.
|
||||
- **Молчаливые перезаписи.** Новый источник противоречит странице — пометь
|
||||
блоком `> **Противоречие:**`; не затирай.
|
||||
- **Нарративный оп-лог.** Не веди его руками: сервис пишет logs сам (admin.logs).
|
||||
- **Не-ASCII слаги.** Ломают grep и кросс-платформенность. Транслитерируй.
|
||||
- **Пропущенные противоречия в lint.** Ценность вики — во вскрытых напряжениях,
|
||||
а не в ложном консенсусе.
|
||||
- **Запись без лиза.** Wiki-мутации без `claim_token` → 422 busy.
|
||||
- **Держать лиз на чтение/раздумья.** Лиз — на время записи. Чтение — карв-аут.
|
||||
- **Реляционный вопрос чтением одной страницы.** Это тот самый 0%-recall
|
||||
провал — зови graph_*.
|
||||
- **Слаги/пути в graph-тулы.** Только internal id, и только свежие (удалённая
|
||||
сущность → ошибка).
|
||||
- **Тащить всю вики в контекст**, чтобы «проследить» связи руками — сервис
|
||||
делает это за ноль токенов.
|
||||
|
||||
## Red flags
|
||||
|
||||
- Реляционный вопрос → читаешь страницу вместо `graph_*`.
|
||||
- Правка `sources/` или молчаливая перезапись противоречия.
|
||||
- Wiki-мутация без лиза (422) или лиз держится на чтение.
|
||||
- Нарративный оп-лог руками.
|
||||
|
||||
---
|
||||
|
||||
## Reference
|
||||
|
||||
- Поиск по сущностям: `mcp__mappa__entity_search` (FTS, решение 1).
|
||||
- Оп-лог: `mcp__mappa__admin_logs` (автоматический, решение 12).
|
||||
- Дерево/зонтики: `mcp__mappa__graph_tree(root, depth?, fields?, limit?)`.
|
||||
- Задачи: `mappa-task-work`. Почта: `mappa-messaging`. Делегирование: `mappa-delegation`.
|
||||
- Related: `using-projects-meta` (мост до флипа), `project-discipline`.
|
||||
Reference in New Issue
Block a user