Модуль wiki, агенты модулей, поля проектов (#91) #92
@ -192,22 +192,41 @@ jira безвреден.
|
||||
неудачи) прошло больше `wiki_auto_sync_hours` (настройка модуля, по умолчанию 24, `0` — выключено) и у проекта нет
|
||||
пакета `wiki_sync` в работе.
|
||||
|
||||
Хаб не ставит пакет, пока предыдущий `wiki_sync` проекта в работе: отвечает 409 с id пакета, MCP показывает его
|
||||
состояние.
|
||||
`POST /wiki/sync` и фоновая работа не ставят пакет, пока предыдущий `wiki_sync` проекта в работе: ответ 409 с id
|
||||
пакета, MCP показывает его состояние.
|
||||
|
||||
**Смена и сброс корня** не упираются в это правило. `PATCH` отменяет ещё не выданные (`queued`) пакеты `wiki_sync`
|
||||
проекта. При новом корне он ставит новый пакет; уже выданный агенту пакет доживает. Отчёт `done` по команде, у которой
|
||||
`params.root` не равен текущему корню проекта (сменён или сброшен), отбрасывается: копия и данные не меняются, команда
|
||||
`done` с пометкой в `result.discarded = "корень сменился"`. Типичный случай: корень проставили до установки eva-agent,
|
||||
потом исправили опечатку.
|
||||
|
||||
**Агент** (контракт; решения внутри агента — его change):
|
||||
1. Берёт корень `CmfDocument.get` и все страницы поддерева, как `collect_subtree` в `eva_wiki_export.py`.
|
||||
2. По каждой странице берёт `text`.
|
||||
3. Отправляет страницы пачками `POST /agent/wiki/pages {command_id, pages: [{code, eva_id, title, parent_code,
|
||||
orderno, url, html, attachments: [{url, name}]}]}`. В пачке не больше 50 страниц и не больше 4 МБ тела.
|
||||
4. Отчитывается `done` с `result = {root_title, codes: [<все коды дерева в порядке обхода>], eva_calls}`.
|
||||
3. Разбирает ссылки страницы. Это делает агент, а не хаб: только он знает `eva.base_url`.
|
||||
- **Вложение** — `<img src>`/`<a href>` на хост Eva с путём по правилу из Context.
|
||||
- **Ссылка на страницу** — ссылка на хост Eva с кодом `DOC-<цифры>` в адресе.
|
||||
- По каждой ссылке агент шлёт:
|
||||
- `ref` — значение атрибута ровно как в HTML, по нему хаб находит место замены;
|
||||
- `url` — абсолютный адрес (только у вложения);
|
||||
- `name` — `alt` или `title` картинки, текст ссылки, иначе имя файла из пути;
|
||||
- `code` — у ссылки на страницу.
|
||||
4. Отправляет страницы пачками `POST /agent/wiki/pages {command_id, pages: [{code, eva_id, title, parent_code,
|
||||
orderno, url, html, attachments: [{ref, url, name}], links: [{ref, code}]}]}`. В пачке не больше 50 страниц и не
|
||||
больше 4 МБ тела.
|
||||
5. Отчитывается `done` с `result = {root_title, codes: [<все коды дерева в порядке обхода>], eva_calls}`.
|
||||
6. В `wiki_fetch` скачивает только адреса на хосте `eva.base_url`, иначе `failed` «чужой хост». Так токен Eva не уходит
|
||||
на чужой адрес.
|
||||
|
||||
**Хаб.**
|
||||
- Пачки складываются в `wiki_sync_stage` без изменения копии.
|
||||
- Отчёт `done` применяется одной транзакцией (`CommandHooks.on_result`):
|
||||
- HTML переводится в Markdown;
|
||||
- Markdown-копия собирается в `wiki/.<label>.new/`, затем атомарно подменяет `wiki/<label>/` (переименование;
|
||||
старая копия удаляется после подмены);
|
||||
- **Приём пачки.** HTML каждой страницы сразу переводится в Markdown, ссылки заменяются по `ref`. Вместо `id`
|
||||
вложения ставится заглушка, её заполняет применение. Результат кладётся в `wiki_sync_stage`, копия не меняется.
|
||||
Перевод идёт вне транзакции записи (markdownify на десятках МБ занимает секунды) и не держит блокировку базы, в
|
||||
которой ждут `claim` jira-agent и веб.
|
||||
- **Отчёт `done`.** Сначала, вне транзакции, Markdown-копия собирается из стадии в `wiki/.<label>.new/` с
|
||||
предварительно выделенными `id` вложений. Затем одной короткой транзакцией (`CommandHooks.on_result`):
|
||||
- каталог атомарно подменяется: переименование, старая копия удаляется после подмены;
|
||||
- `wiki_page` и FTS пишутся заново;
|
||||
- для `wiki_attachment` при той же паре «адрес + страница» сохраняются `id` и скачанный файл, новые пары
|
||||
добавляются, пропавшие удаляются;
|
||||
@ -225,8 +244,8 @@ jira безвреден.
|
||||
|
||||
Безопасное название — как `safe_name` скрипта; при совпадении у соседей хаб добавляет `_2`, `_3`.
|
||||
|
||||
**HTML → Markdown** делает хаб: зависимость `markdownify`, ATX-заголовки. Ссылки:
|
||||
- **картинка или файл Eva** (тот же хост и путь по правилу из Context) заменяется на `[📎 <имя>](attachment:<id>)`:
|
||||
**HTML → Markdown** делает хаб: зависимость `markdownify`, ATX-заголовки. Ссылки (классифицирует агент, см. выше):
|
||||
- **картинка или файл Eva** заменяется на `[📎 <имя>](attachment:<id>)`:
|
||||
по `id` инструмент `attachment` и веб скачивают файл;
|
||||
- **ссылка на страницу Eva с кодом `DOC-<цифры>`** заменяется на `[<текст>](page:<код>)`: по коду её открывает
|
||||
инструмент `page`, а в вебе она ведёт на страницу вики, если та есть в дереве проекта;
|
||||
@ -333,7 +352,10 @@ jira безвреден.
|
||||
|
||||
### 16. Порядок работ
|
||||
|
||||
1. Ядро: виды агентов (решения 1–7) — jira-agent v14 работает. Живая проверка: kickstart, claim от v14 проходит.
|
||||
1. Ядро: виды агентов (решения 1–7) — jira-agent v14 работает. Живой проверки посередине нет: launchd запускает хаб
|
||||
из основного checkout, а частичная v7 на живой базе сломала бы последующие шаги миграции. Совместимость с v14
|
||||
проверяется тестом: снимок схемы v6 с досками и токеном → миграция → `claim`, `GET /agent/settings`,
|
||||
`/agent/state` с прежним токеном, формой и ответами v14. Живая проверка — после merge.
|
||||
2. Ядро: поля проектов (решение 8) и снятие долга.
|
||||
3. Модуль wiki в хабе: данные, синхронизация с имитацией агента в тестах, вложения, HTTP, MCP.
|
||||
4. Веб.
|
||||
@ -397,3 +419,16 @@ jira безвреден.
|
||||
вики.
|
||||
11. **Ежедневная синхронизация — фоновой работой хаба** (решение 10). Обоснование: прецедент — автообновление
|
||||
зеркала jira. Цена ошибки — отключение настройкой `wiki_auto_sync_hours = 0`.
|
||||
12. **Одна живая проверка — после merge, без промежуточной** (решение 16; builder check). Обоснование: частичная v7 на
|
||||
живой базе ломает последующие шаги, а launchd смотрит в основной checkout. Цена ошибки — несовместимость с v14
|
||||
всплывёт после выкатки; страхуют тест миграции на снимке v6 и откат на копию базы.
|
||||
13. **HTML → Markdown при приёме пачки, вне транзакции** (решение 10; builder check). Обоснование: перевод десятков МБ
|
||||
под `BEGIN IMMEDIATE` блокирует `claim` jira-agent и веб. Цена ошибки — стадия в базе крупнее (Markdown вместо
|
||||
HTML — обычно меньше).
|
||||
14. **Ссылки классифицирует агент, хаб заменяет по `ref`** (решение 10; builder check). Обоснование: адрес Eva знает
|
||||
только агент, хабу он не нужен. Цена ошибки — контракт `pages` меняется в обоих репозиториях.
|
||||
15. **`wiki_fetch` только на хост `eva.base_url`** (решение 10; builder check). Обоснование: токен Eva не уходит на
|
||||
чужой адрес. Цена ошибки — вложение на другом хосте открывается только ссылкой.
|
||||
16. **Смена корня отменяет невыданные `wiki_sync`, поздний `done` старого корня отбрасывается** (решение 10; builder
|
||||
check). Обоснование: корень правят, пока eva-agent ещё не установлен; копия старого дерева не должна встать под
|
||||
новый корень. Цена ошибки — лишняя синхронизация.
|
||||
|
||||
@ -25,12 +25,18 @@ SHALL удалять копию проекта, его страницы, инд
|
||||
label`. Её SHALL ставить: `POST /wiki/sync {project}`, задание или смена корня, фоновая работа хаба — по каждому
|
||||
проекту с корнем, если с последней успешной или неудачной синхронизации прошло больше `wiki_auto_sync_hours`
|
||||
(настройка модуля, по умолчанию 24; `0` — выключено). Пока у проекта есть пакет `wiki_sync` не в терминальном статусе,
|
||||
новый не ставится: `POST /wiki/sync` отвечает 409 `sync_in_progress` с `batch_id` текущего.
|
||||
новый не ставится: `POST /wiki/sync` отвечает 409 `sync_in_progress` с `batch_id` текущего. Смена или сброс корня
|
||||
SHALL отменять невыданные (`queued`) пакеты `wiki_sync` проекта и при новом корне ставить новый; отчёт `done` по
|
||||
команде, чей `root` не равен текущему корню проекта, SHALL отбрасываться без изменения копии и данных
|
||||
(`result.discarded = "корень сменился"`).
|
||||
|
||||
Агент `wiki` SHALL прислать все страницы поддерева корня (включая корень) пачками `POST /agent/wiki/pages {command_id,
|
||||
pages}` — каждая страница `{code, eva_id, title, parent_code, orderno, url, html, attachments: [{url, name}]}`, в
|
||||
пачке не больше 50 страниц, — и отчитаться `done` с `result = {root_title, codes, eva_calls}`, где `codes` — коды всех
|
||||
страниц дерева в порядке обхода. Хаб SHALL складывать пачки во временную стадию команды, не трогая копию. Пачка по
|
||||
pages}` — каждая страница `{code, eva_id, title, parent_code, orderno, url, html, attachments: [{ref, url, name}],
|
||||
links: [{ref, code}]}`, где `attachments` — ссылки и картинки на файлы Eva, `links` — ссылки на документы Eva, `ref` —
|
||||
значение атрибута `src`/`href` ровно как в `html`, `url` — абсолютный адрес, `name` — `alt`/`title`, текст ссылки или
|
||||
имя файла; в пачке не больше 50 страниц, — и отчитаться `done` с `result = {root_title, codes, eva_calls}`, где
|
||||
`codes` — коды всех страниц дерева в порядке обхода. Хаб SHALL при приёме пачки переводить HTML в Markdown вне
|
||||
транзакции записи и складывать результат во временную стадию команды, не трогая копию. Пачка по
|
||||
команде не в `claimed` или не `wiki_sync` — 409; неверная форма страницы — 422 `bad_pages` с кодом страницы и полем.
|
||||
|
||||
По отчёту `done` хаб SHALL одной операцией заменить копию проекта (см. «Markdown-копия вики»), страницы, индекс поиска и
|
||||
@ -57,6 +63,14 @@ pages}` — каждая страница `{code, eva_id, title, parent_code, or
|
||||
- **WHEN** в прошлой копии были DOC-1, DOC-2, DOC-3, новая синхронизация вернула DOC-1, DOC-3
|
||||
- **THEN** каталога DOC-2 нет, поиск его не находит, его вложения удалены
|
||||
|
||||
#### Scenario: Корень исправлен, пока агент не установлен
|
||||
- **WHEN** у `AWPCA` корень DOC-12 и пакет `wiki_sync` в `queued`; `PATCH /projects/AWPCA {wiki_root: "DOC-21"}`
|
||||
- **THEN** прежний пакет `cancelled`, поставлен `wiki_sync {root: DOC-21}`
|
||||
|
||||
#### Scenario: Поздний отчёт по старому корню
|
||||
- **WHEN** `wiki_sync {root: DOC-12}` выдан агенту, корень сменён на DOC-21, агент отчитался `done`
|
||||
- **THEN** копия и страницы `AWPCA` не изменились, команда `done` с `result.discarded`
|
||||
|
||||
#### Scenario: Повторный запрос синхронизации
|
||||
- **WHEN** пакет `wiki_sync` проекта `AWPCA` выполняется, вызван `POST /wiki/sync {project: AWPCA}`
|
||||
- **THEN** 409 `sync_in_progress` с `batch_id` текущего пакета, нового пакета нет
|
||||
@ -69,7 +83,7 @@ pages}` — каждая страница `{code, eva_id, title, parent_code, or
|
||||
корне копии — `_tree.json`, список `{code, title, depth, path}` в порядке обхода. Копия SHALL собираться рядом
|
||||
(`wiki/.<метка>.new/`) и подменять прежнюю переименованием; незавершённую подмену хаб SHALL доводить при старте.
|
||||
|
||||
HTML страницы SHALL переводиться в Markdown (заголовки `#`); ссылка или картинка на файл Eva (тот же хост, путь с
|
||||
HTML страницы SHALL переводиться в Markdown (заголовки `#`); ссылка или картинка на файл Eva (по списку `attachments` агента: тот же хост, путь с
|
||||
`files`, `file`, `attachments`, `attachment`, `download`, `media` или `upload`) SHALL заменяться на
|
||||
`[📎 <имя>](attachment:<id>)`, где `id` — строка вложения; ссылка на документ Eva с кодом `DOC-<цифры>` — на
|
||||
`[<текст>](page:<код>)`; прочие ссылки остаются. Сырой HTML в копию не попадает.
|
||||
@ -89,7 +103,8 @@ HTML страницы SHALL переводиться в Markdown (заголов
|
||||
`ready`. Агент `wiki` SHALL скачать файл с токеном Eva, отказаться от файла больше предела хранилища ядра (10 МБ) с
|
||||
ошибкой «файл больше 10 МБ — откройте в Eva», загрузить файл `POST /agent/files` и отчитаться `done {file, size}`. Хаб
|
||||
SHALL проверить, что файл есть в `files/` и размер совпадает, и перевести вложение в `ready`; иначе команда и вложение
|
||||
`failed`. Файлы вложений в `ready` SHALL считаться ссылками для уборки `files/`. `GET /wiki/attachments/{id}` отдаёт
|
||||
`failed`. Адрес не на хосте Eva из конфига агента агент SHALL отвергать без запроса (`failed` «чужой хост»).
|
||||
Файлы вложений в `ready` SHALL считаться ссылками для уборки `files/`. `GET /wiki/attachments/{id}` отдаёт
|
||||
`{id, name, page_code, url, state, size, error}`, `GET /wiki/attachments/{id}/content` — содержимое (`ready`) или 409
|
||||
`not_ready`.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user