diff --git a/docs/superpowers/plans/2026-10-27-wiki-package-d.md b/docs/superpowers/plans/2026-10-27-wiki-package-d.md
new file mode 100644
index 0000000..faf09a0
--- /dev/null
+++ b/docs/superpowers/plans/2026-10-27-wiki-package-d.md
@@ -0,0 +1,387 @@
+# Пакет D модуля wiki — план реализации
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** закрыть маркеры #94 T6.1–T6.5, T8.2, T8.3, T9.3 и показать скачанные картинки в тексте страницы «Вики» (sdlc-hub#135).
+
+**Architecture:** точечные правки модуля `wiki`: перевод HTML (`convert.py`), постановка `wiki_sync` (`commands.py`),
+вложения (`attachments.py`, `api.py`), MCP (`mcp.py`); во фронте — режим «показать» у скачивания вложения и хранилище
+картинок страницы (`download.ts`, `PageView.tsx`). Схема базы и контракт с агентом не меняются.
+
+**Tech Stack:** Python 3.13 (uv), pytest, BeautifulSoup + markdownify; React 19 + TypeScript, Vitest, Testing Library.
+
+**Ветка:** `feat/135-wiki-package-d` (worktree `.wt/wiki-d`).
+
+**Spec:** `openspec/changes/wiki-package-d/` (proposal.md, design.md — решения 1–10, specs/wiki, specs/mcp, specs/web-app).
+
+## Global Constraints
+
+- Только хаб `sdlc-hub`; eva-agent и jira-agent не меняются, `SCHEMA_VERSION` не меняется.
+- Граница ядра: в `src/sdlc_hub/core/` правок нет (проверяют `tests/test_registry.py`).
+- Тексты ошибок и комментарии — по-русски, в стиле соседнего кода.
+- Расширения картинок: `.png .jpg .jpeg .gif .webp .bmp` без учёта регистра; SVG — не картинка.
+- Пробел → `%20`, `(` → `%28`, `)` → `%29` — только во внешних адресах ссылок и картинок.
+- Зелёным считается только весь набор: в конце `make check` (pytest + lint и тесты фронта).
+- Соединения SQLite в тестах — через фикстуры `open_db`/`conn`, иначе явный `close()`.
+
+## Review Focus
+
+1. Ссылка на страницу, внутри которой и картинка-вложение, и текст (`Схема`) — вложение перед ссылкой, текст ссылки «Схема». Тест в Task 1.
+2. Внешняя ссылка с уже закодированным адресом (`%20` в `href`) не кодируется повторно (`%2520`). Тест в Task 1.
+3. Повтор упавшей синхронизации, когда идущих синхронизаций нет, проходит как раньше. Тест в Task 2.
+4. Вложение `ready` с файлом на месте — `fetch` отвечает 200 `ready` без нового пакета (T8.2 не ломает обычный путь). Тест в Task 3.
+5. Смена страницы, пока картинка грузится: поздний ответ `content` не кладёт картинку на новую страницу, objectURL старой отозваны. Тест в Task 5.
+
+---
+
+### Task 1: Перевод HTML — T6.1–T6.5
+
+**Files:**
+- Modify: `src/sdlc_hub/modules/wiki/convert.py` (`_Converter.__init__`, `convert_img`, `convert_a`, `_label`, новые `_href`, `_split_marks`)
+- Test: `tests/test_wiki_convert.py`
+
+**Interfaces:**
+- Produces: `convert.to_markdown(html, attachments, links) -> (str, list[dict])` — сигнатура прежняя.
+
+- [ ] **Step 1: Написать падающие тесты** (константы `FILE_REF`, `THUMB_REF`, `IMG_REF`, `FILE_URL` уже в файле; `IMG_URL = "https://eva.example.test" + IMG_REF`, `FILE = {"ref": FILE_REF, "url": FILE_URL, "name": "model.xlsx"}`, `THUMB = {"ref": THUMB_REF, "url": FILE_URL, "name": "model.xlsx"}`, `IMG = {"ref": IMG_REF, "url": IMG_URL, "name": "scheme.png"}`, `LINK = {"ref": "project/Document/DOC-1", "code": "DOC-1"}`)
+
+```python
+def test_thumbnail_in_wrapper_keeps_link(): # T6.1
+ md, atts = convert.to_markdown(f'
` | `[\[📎 x.png](attachment:@0)](page:DOC-1)` — ссылка в ссылке |
+| T6.3 | два `attachments` с одним `ref` | побеждает последний (`dict` по `ref`) |
+| T6.4 | `док` | `[док](http://ex.com/a b(c).html)` — не ссылка |
+| T6.5 | `путь C:\` | `[путь C:\](page:DOC-1)` — `\]` экранирует скобку |
+
+T8.2: `request_fetch` отвечает `ready` по полю `state`, а `GET …/content` при пропавшем файле — 409 «запросите
+скачивание»: тупик. T8.3: `POST /wiki/sync` проверяет `active_sync`, а `POST /batches` и `POST /commands/{id}/retry`
+проходят только `commands.check_batch`, где этой проверки нет. T9.3: `mcp.py` склеивает шапку `page`, строки `tree`,
+`search` и кандидатов из значений Eva без нормализации переводов строк.
+
+Владелец 27.10.2026 согласился с предложенным поведением по всем восьми маркерам и добавил картинки в тексте страницы
+«Вики»: показ только после нажатия, уже скачанные — сразу.
+
+## Decisions
+
+1. **T6.1 — предок, а не родитель.** `convert_img` ищет ближайшего предка `` (`el.find_parent("a")`), а не только
+ `el.parent`. Если `href` этого `` — вложение и картинка — то же вложение (совпадает `url` записей) или вообще не
+ вложение, картинка не выводится: ссылку выведет ``. Картинка — другое вложение (миниатюра файла Y внутри ссылки
+ на файл X) выводит свою ссылку, а `convert_a` для вложения X сохраняет маркеры вложений из `text` перед своей
+ ссылкой (то же правило, что в решении 2): Y не теряется.
+2. **T6.2 — вложение перед ссылкой на страницу.** В `convert_a` для ссылки на документ (`code` найден): если в `text`
+ (уже сконвертированное содержимое) есть маркеры вложений (`_MARK`), они выносятся перед ссылкой: результат —
+ `<ссылки вложений> [<остаток текста или код>](page:<код>)`. Остаток — `text` без фрагментов `[📎 …<маркер>`;
+ пустой после `strip()` — код. Через `_label` как сейчас. Внешняя ссылка (`super().convert_a`) с картинкой-вложением
+ внутри — то же правило: вложение перед ссылкой, текст ссылки — остаток, пустой — адрес. Ссылка на вложение внутри
+ ссылки на вложение уже покрыта решением 1.
+3. **T6.3 — первая запись.** `_by_ref` и `_links` собираются с `setdefault`: первая запись по `ref` побеждает (порядок
+ агента — порядок документа).
+4. **T6.4 — кодирование адреса.** Для внешних ссылок и картинок (ветка `super().convert_a`/`convert_img`) адрес
+ проходит `_href(url)`: пробел → `%20`, `(` → `%28`, `)` → `%29`; прочие символы не трогаются (уже закодированное не
+ кодируется повторно). Ссылки `page:`/`attachment:` не затрагиваются — в них таких символов нет.
+5. **T6.5 — хвостовая черта.** `_label` после текущих замен удваивает нечётную серию `\` в конце строки (одна `\`
+ в конце → `\\`). То же в тексте внешней ссылки, если markdownify не экранировал её сам; проверять тестом обе ветки.
+6. **T8.2 — проверка файла в `request_fetch`.** `request_fetch(conn, attachment_id, author, files_dir)`: при `state =
+ ready` и `files.size(files_dir, row["file"]) is None` вложение идёт по ветке «поставить скачивание» (state
+ `fetching`, новый пакет). Маршрут `h_attachment_fetch` передаёт `hub.files_dir`; MCP `attachment` ходит через этот
+ же маршрут и поведение получает без правок. `GET /wiki/pages/{code}` и `GET /wiki/attachments/{id}` по-прежнему
+ отдают `state` из базы (проверка файла на каждом чтении — лишние обращения к диску).
+7. **T8.3 — проверка в `check_batch`.** Для каждой `wiki_sync` в пакете: если у проекта есть команда `wiki_sync` в
+ `queued`/`claimed` с тем же `params.root`, — `CommandError` «у проекта <метка> уже идёт синхронизация корня
`
+- **THEN** в `index.md` — `[📎 scheme.png](attachment:
`, `scheme.png` — вложение
+- **THEN** в тексте `[📎 scheme.png](attachment:<script> a@b