Files
project-maps/agent-sync/MAP.md
T

8.0 KiB
Raw Blame History

agent-sync

Назначение

Транспорт и протокол обмена задачами/статусами/артефактами между агентами инфраструктуры servaki через Nextcloud (WebDAV, n.servaki.online, папка /_agents/). Не замена git (Gitea git1.servaki.online — канон кода/спек), а второй слой для крупного/оперативного: сборки, дампы, статусы-хартбиты, файловая очередь inbox/processing/done между агентами (laptop-agent, lilia/les, claude-agent).

Ядро — один переносимый POSIX-скрипт ncx.sh (git-bash на ПК + Linux-ВМ), работающий поверх curl + WebDAV. Секреты (app-password) хранятся вне git в ~/.servaki-secrets/nextcloud.env.

  • Основной язык: POSIX shell (sh)
  • Суммарный LOC по коду: ~197 (весь код — ncx.sh, 197 строк; остальное — Markdown-доки и .env.example)

Архитектура

Каталогов src/* нет — плоский репо. Модули = функции внутри ncx.sh (диспетчер main → подкоманды → WebDAV-примитивы → утилиты).

graph TD
  ENV["nextcloud.env<br/>(секреты, вне git)"] --> NCX
  subgraph ncx.sh
    MAIN["main() — диспетчер CLI"]
    MAIN --> INIT[cmd_init]
    MAIN --> LS[cmd_ls]
    MAIN --> PUT[cmd_put]
    MAIN --> GET[cmd_get]
    MAIN --> MKDIR[cmd_mkdir]
    MAIN --> SEND[cmd_send_task]
    MAIN --> CLAIM[cmd_claim]
    MAIN --> DONE[cmd_done]
    MAIN --> STATUS[cmd_status]
    MAIN --> SELF[cmd_selftest]

    NEED["_need_creds()<br/>DAV/ROOT URL"]
    CURL["_curl() — curl -K - (stdin auth)"]
    SHA["_sha256()"]
    MKCOL["_mkcol / _mkdirp (MKCOL)"]
    EXISTS["_exists (PROPFIND)"]
    MOVE["_move_noover (MOVE Overwrite:F)"]

    INIT --> NEED --> CURL
    SEND --> PUT
    PUT --> SHA
    PUT --> MKCOL
    GET --> EXISTS
    GET --> SHA
    CLAIM --> LS
    CLAIM --> MOVE
    CLAIM --> PUT
    DONE --> PUT
    STATUS --> PUT
  end
  NCX[ncx.sh] -->|WebDAV/HTTPS| NC["Nextcloud n.servaki.online<br/>/_agents/"]

Entry-points / маршруты

HTTP-сервера/роутов нет — это WebDAV-клиент (исходящие вызовы к Nextcloud). Публичный интерфейс — CLI-подкоманды. Все ходят через _curl (curl --fail-with-body -K -) к NC_BASE/remote.php/dav/files/<user>/_agents/....

Команда Функция WebDAV-метод(ы) Назначение
ncx init cmd_init MKCOL создать структуру _agents/ под своего агента
ncx ls <path> cmd_ls PROPFIND Depth:1 листинг каталога
ncx put <local> <remote> cmd_put PUT (+GET верификация) залить файл + sha256-сайдкар, сверить целостность
ncx get <remote> <local> cmd_get GET, PROPFIND скачать + сверить sha256
ncx mkdir <path> cmd_mkdir MKCOL создать каталог рекурсивно
ncx send-task <to> <local.md> cmd_send_task PUT положить задачу в tasks/<to>/inbox
ncx claim [agent] cmd_claim MOVE Overwrite:F атомарно забрать 1 задачу inbox→processing
ncx done <task> [result] cmd_done PUT, DELETE processing→done + результат + аудит
ncx status <local.md> cmd_status PUT опубликовать хартбит status/<agent>-status.md
ncx selftest cmd_selftest — (оффлайн) проверка окружения без сети

Ключевые цепочки вызовов

  1. Публикация файла (put): cmd_put → _sha256 (локальная сумма) → _mkdirp(MKCOL) → _curl -T (PUT тела) → PUT сайдкара .sha256 → скачать назад в tmp → сверить sha256 → _die при расхождении. Гарантия целостности больших бинарей.
  2. Отправка задачи (send-task): cmd_send_task → _mkdirp tasks/<to>/inbox → cmd_put (тело задачи с YAML-шапкой в inbox агента-получателя).
  3. Атомарный захват (claim): cmd_claim → cmd_ls inbox → фильтр .md → цикл _move_noover (MOVE inbox→processing, Overwrite: F); код 201=захвачено (exactly-once), 412=уже занято → аудит-маркер в audit/<agent>/ → GET тела в ./_ncx-work/. Первый забравший выигрывает, гонок нет.
  4. Завершение (done): cmd_done → дописать result/done_by/done_at в локальный файл → cmd_put в done/ → DELETE из processing/ → аудит-маркер.
  5. Хартбит (status): cmd_status → cmd_put в status/<agent>-status.md (single-writer на файл → без конфликтов синка).

Тех-долг

Ниже — предположения по эвристике (греп/чтение одного файла). Точность — через codebase-memory-mcp.

  • Dead-code кандидаты: явных не найдено — все _*-примитивы и cmd_* достижимы из main(); _exists используется в cmd_get, _move_noover — в cmd_claim. (предположение)
  • Дубли/расхождение доков: структура /_agents/ описана дважды и по-разному: README.md/ncx.sh = inbox|processing|done + audit/, а AGENT-SYNC-NEXTCLOUD.md = только inbox|done + shared-memory/. Второй документ помечен как «предложение схемы» и частично устарел относительно кода. (предположение)
  • Хрупкая логика аудита в cmd_claim: fallback между /tmp/ncx-audit.$$ и ./.ncx-audit.$$ через двойную проверку -f — легко рассинхронизировать; кандидат на упрощение. (предположение)
  • cmd_claim в pipe-подоболочке (... | while read): return 0 выходит из подоболочки, не из функции — семантика «одна задача за вызов» может вести себя неожиданно при нескольких задачах. (предположение)
  • shared-memory/ упомянут в доке, но cmd_init его не создаёт — рассинхрон спеки и кода. (предположение)

TODO для Лилии (codebase-memory-mcp)

  • Построить точный call-graph ncx.sh (функция→функция, включая косвенные вызовы через main case).
  • Подтвердить/опровергнуть dead-code (реальная достижимость _exists, аудит-fallback, поведение return в subshell cmd_claim).
  • Cross-service links — зафиксировать связи: n.servaki.online (85.208.87.14, Nextcloud 33.0.5), git1.servaki.online (Gitea, репо german/agent-sync), домены *.servaki.online; агенты-контрагенты laptop-agent / lilia(les) / claude-agent; упоминание репо cascade (git-канон). Проверить реальные обращения из других наших репо к ncx/_agents/.
  • Снять снапшот graph.db.zst и связать с этим MAP.md.
  • Сверить расхождение схемы /_agents/ между README.md и AGENT-SYNC-NEXTCLOUD.md, пометить актуальную.