docs(observatory): record claim-v3 repair and preserved queue history

This commit is contained in:
DCCONSTRUCTIONS
2026-09-03 00:00:08 +03:00
parent 43f1cdc862
commit 80fc0058cb
3 changed files with 181 additions and 0 deletions
@@ -38,6 +38,22 @@ durable queue содержит10 failed и1 succeeded/not-required, live leases0
и нарушения идемпотентности старых claim IDs; затем verified-cache projection.
Не повышать бесконечно лимит и не чистить receipts вслепую.
**Ремонт claim-пути выполнен, 23:54 МСК.** Backend и оба текущих control agents
переведены на claim/v3: пустой poll не создаёт receipt; реальная выдача получает
durable grant с прежними ownership/retry guards. Все 50000 legacy receipts,
11 jobs и остальные старые таблицы сохранены побайтно на уровне canonical row
hashes. Новый положительный ledger имеет отдельный конечный лимит50000;
старый лимит не поднят, общий storage bound128MiB прежний.16 Worker→Mac idle
probes PASS, обычные polls204, v3 rows0, agent restarts0.126 focused tests,
Ruff/mypy PASS. Канонический8000/PID57796 работает; модели/UI не запускались.
Изменена только schema version в реально импортируемом transport-модуле;
compute packages/registries сохранены. Старые agents stopped/restart=no
оставлены для rollback. Source of truth транспорта — pinned create declarations
отдельного control release, не прежний package launcher.
[Отчёт и rollback](../experiments/perception/OBSERVATORY_RECORDED_CLAIM_REPAIR_2026-09-02.md).
Следующий шаг: verified published-cache projection. Этап1 по-прежнему открыт;
готовый cache/selector/progress и полный расчёт записей ещё не доказаны.
- Сверить каталог, очередь, публикацию и просмотр для текущих M4.9T5 и LAB V1.
- Связать готовность с точной исходной записью и immutable RunDefinition,
включающей image/model/config/adapter/result-contract identities.
@@ -63,6 +63,24 @@ complete recorded-analysis execution are still pending. This increment does not
mark stage 1 or the full workflow complete. Tests cover concurrent admission,
durability, changed source/profile, failure retry and HTTP 409 duplicate handling.
## Second increment: bounded non-binding idle claims
Claim/v3 is active on the backend and both current Worker006 control agents.
Idle polls do not persist receipts; actual grants are durable and share the
request-ID namespace with preserved v2 history. Repeating a non-binding v3 idle
request may later acquire work, unlike an old persisted v2 empty receipt.
The 50,000-row legacy ledger remains intact; a separate 50,000-positive-grant
budget does not change the shared 128 MiB database/WAL/SHM storage bound.
Only the imported gateway's request schema literal changes in two pinned child
images. Compute package identities and model images remain unchanged. The exact
control-agent create declarations, separate from executor package declarations,
are now the durable runtime source; old agents remain stopped for rollback.
126 focused tests and 16 real empty-capability Worker-to-backend probes passed.
All pre-existing queue row hashes are unchanged. This repairs dispatch polling,
not published-cache verification or full recorded-workflow acceptance.
See the [repair evidence and rollback boundary](../../experiments/perception/OBSERVATORY_RECORDED_CLAIM_REPAIR_2026-09-02.md).
## Boundaries
No Synology deployment, hardware actuation, motor integration, new capture,
@@ -0,0 +1,147 @@
# Observatory recorded claim repair — 2026-09-02
## Результат и граница
Восстановлен control-путь очереди для обоих текущих Worker006 agents. Backend
и агенты используют versioned claim/v3: пустой опрос не создаёт receipt,
фактическая выдача остаётся долговечной и идемпотентной. Это второй инкремент
нового этапа 1, **не** завершение cache/selector/progress или полного LAB-run.
Модели, compute packages, записи, результаты, их identities и mounts не менялись.
Модельных заданий не создано. Оба агента — диспетчеры; два работающих агента
не означают два параллельных вычислительных профиля. GPU authority не добавлена.
Код: `cabd308` (queue/API/client), `0041e9f` (actual import-path guard),
`43f1cdc` (exact Docker layer). Plan: [актуальные четыре этапа](../../docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md).
## Причина и контракт
Старый журнал достиг 50 000 receipts: 49 985 пустых опросов и 15 выдач.
Каждый новый idle poll занимал запись; quota проверялась до поиска работы.
Работающие v2-агенты получали 503 и периодически перезапускались после
исчерпания своего transport-failure budget.
- v2 semantics сохранены, включая прежний NULL-result для старого request ID.
- v3 idle — non-binding observation; после idle тот же ID может позднее
получить работу. Явный пустой capability tuple гарантированно не получает job.
- Выданный grant сохраняется в новой `observatory_recorded_claim_grants_v3`.
Повтор возвращает тот же grant либо stale-claim error; другая capability
inventory/claimant с тем же выданным ID отвергается.
- Старый и новый журналы проверяются в одной сериализованной транзакции:
новый протокол не обходится повтором через старый.
- Старый лимит 50 000 не увеличен, строки не удалены. Введён **отдельный**
конечный бюджет 50 000 реальных v3 grants. Общий storage bound SQLite/WAL/SHM
остаётся 128 MiB. Это не бесконечное хранилище: заполнение положительного
журнала требует отдельного архивного lifecycle, а не слепой чистки.
- Authenticated GET `/api/v1/worker/observatory/recorded-jobs/claim-readiness`
показывает оба бюджета, job-state counts и open live leases. Это готовность
очереди, не доказательство GPU/model readiness. UI-проекция ещё не менялась.
## Точный Worker cutover
Обновлён только реально импортируемый файл:
`/opt/nodedc/installed-lab/src/k1link/observatory/worker_http_transport.py`.
Before SHA: `c3d82ffd482a29b17c68d1fb5603e82924766abc0080137d3a0a6130f92ccdce`.
After SHA: `81bdc27f374cd91358f0eb58603e3e1f53e1f3017bf158d269e75affa4567293`.
Содержательное изменение — одна строка schema version v2→v3.
| Контрольный агент | Parent image | Новый transport image |
| --- | --- | --- |
| installed LAB | `5ad7d95baac6…` | `1b1e335916c1c3d77888b7537331e9d775d078957c4ac0f82e91852301725390` |
| M4.9 | `d00274a2a76e…` | `7aa6ccd2ddba4ebb0c07d793e5331539a2e13b07961c269439d5b79762328194` |
Полные parent digests, container IDs, create bodies, mounts, argv, environment,
resource/restart policies и rollback pointers сохранены в release evidence.
Каждый новый image содержит точные прежние RootFS layers плюс один слой с
изменённым transport-файлом и metadata его каталогов. Model/executor images
в package registries остаются прежними; транспортный образ не выдаётся за
новую версию вычислительного профиля.
Два первых apply были остановлены до service cutover:
1. Первоначальный путь указывал на неиспользуемую v1-копию в базовом слое
`/opt/nodedc/mission-core/src`. Хеш совпадал с этой копией, но её protocol
literal — нет. Проверка фактического `module.__file__` подтвердила v2 в
installed-lab overlay. Ошибочная промежуточная гипотеза о работающем v1
опровергнута; реальные контейнеры до финального apply не заменялись.
2. Замена одного байта с сохранением size/mtime не попала в Docker snapshot
diff. После обновления file mtime обнаружен ровно ожидаемый файл.
Добавлен регрессионный тест. Ни пустой diff, ни неверный import path не
принимались как успешный образ.
## Приёмка
- 126 focused tests PASS: legacy/v3 queue, full quota, concurrent retries,
expired grants, capability mismatch, API auth, gateway, Worker service,
recorded submit, portable catalog, publication/retry и migration guards.
- Ruff PASS на изменённом коде/тестах; mypy PASS на трёх source modules.
Единственный warning — существующая Starlette/httpx deprecation.
- 16 настоящих v3 пустых запросов: по 8 из каждого нового агента через его
установленный gateway → локальный proxy → Worker tunnel → canonical8000.
Capabilities пустые; job/model execution невозможны в этих probes.
- Последние100 фоновых Worker polls после cutover:100×204, ошибок0; оба новых
контейнера running, restart count 0, restart=unless-stopped, GPU requests=null.
- Queue snapshot в 23:54 МСК: legacy=50 000, v3=0, jobs=11 (10 failed,
1 succeeded/not-required), live=0. Все строки пяти прежних таблиц
совпали с before snapshot по SHA-256. Ни выдачи, ни jobs, ни reconciliation
history не потеряны.
- Canonical8000 обновлён, PID57796; `/api/health` HTTP200. Начальный health
polling ошибочно обращался к несуществующему `/api/v1/health`; это ошибка
диагностического URL, не отказ сервиса. Правильный endpoint проверен отдельно.
- GPU/model benchmarks, frontend build и полный recorded run не выполнялись.
Ollama/Frigate остаются exited/restart=no. Временные containers и один
диагностический image удалены; остановленные rollback agents сохранены.
## Evidence и воспроизводимость
Worker release:
`D:\NDC_MISSIONCORE\runtime\services\observatory-claim-transport\ec3bf17908c6d0c167156ad93e2edb3d8a3bd914a0b0a66aa5b0de6957bf2496`.
Plan SHA: `ec3bf17908c6d0c167156ad93e2edb3d8a3bd914a0b0a66aa5b0de6957bf2496`.
Migration script SHA: `4b07693fec563ef755002d29345528e501f703974b5c7090470962d51eb460b2`.
Worker receipt file SHA: `c8f72fc5aad9d7aae6a12391304ec268ee8c0d0f80a1100e41e4638a0d56b771`.
Installed-agent declaration SHA:
`9a4832496a7b9de1d079eda31d1d9c67d1543a266808df3d8e69bca1cb1f4a40`.
M49-agent declaration SHA:
`644ed2a4ef6daac0efd9023c77c94d9f2081cd8895fc49019b11922a9c70f1d8`.
Local evidence (не Git): `.runtime/observatory-claims-v3-l9ock9/`.
Before SQLite backup SHA:
`428783a40ba000676da3a2de270cbfb3b2fb0685e7f489303b0e05a6ee4bf9f9`.
After SQLite snapshot SHA:
`934a28e890a318077e25184c5e1f6ff7efc7c1acb8da6a12a9600fea99d490f1`.
Legacy rows SHA:
`a5291155f9c74e552f05a8a856cd120270f5b5132e7ac9a5ed53605f4a743bbe`.
Job rows SHA:
`34205296fe1e335657de9d70890e28ccc16eec5120f6d1ffa1fde15f60d58a0f`.
SQLite file hashes различаются ожидаемо из-за добавленной таблицы; row hashes
прежних таблиц совпадают. Backup содержит реальные operational records и не
должен попадать в Git.
## Durable runtime и откат
Новый источник истины для **контрольных агентов** — точные
`*-declaration.json` в release выше: полный Docker create body и pinned image.
Package manifests остаются источником истины для вычислений. Прежний
`Start-ObservatoryInstalledLabWorker.ps1` с предположением agent image =
package executor image не использовать для замены transport overlay: он
потребует reconciliation. Docker restart policy уже сохраняет новые контейнеры
при обычном перезапуске; реальный reboot в этом инкременте не выполнялся.
Предшественники сохранены:
`ndc-observatory-installed-lab-worker-agent-v2-rollback-810212622de9`,
`ndc-observatory-m49-worker-agent-v2-rollback-b30b41d9e2e2`;
оба stopped/restart=no. Не запускать их рядом с новой версией. Перед откатом
повторно доказать отсутствие активного/queued/reconciliation/live work, остановить
только соответствующий новый агент, проверить точный predecessor ID из declaration,
вернуть имя и прежнюю restart policy. v2 снова упрётся в заполненный legacy ledger:
это аварийный возврат прежнего состояния, не работоспособное решение.
Не восстанавливать SQLite backup поверх новых jobs/grants. Backend rollback
не должен игнорировать появившиеся v3 grants: сначала отдельная reconciliation,
сохранение актуальной БД и контроль владельцев. Автоматического отката со
стиранием поздней работы нет.
Следующий инкремент этапа 1: verified published-cache projection по exact source
и definition, затем селектор/прогресс этапа 2. Реальный полный расчёт профиля и
повторный просмотр без inference остаются обязательной отдельной приёмкой.