Харнесс нужен для одного: чтобы агент работал сам, долго и с пользой — часами и сутками, доводя задачи до результата, который человеку не нужно перепроверять руками.
Границы правды — не цель, а метод внутри этой задачи. Он выбран не из любви к строгости: без проверяемого свидетельства автономная работа деградирует в правдоподобный шум, и чем дольше агент работает, тем дороже каждая ошибка. На короткой задаче «объявил готово, а не готово» раздражает; на суточной — обнуляет весь результат. А доверие человека — ресурс: если результат перепроверяют вручную, автономии нет, есть дорогой черновик.
Свой контур, собранный с нуля, без обёрток вокруг чужого агента:
- своё ядро Linux 6.18.60 (
core-rs/kernel/):tinyconfig, без модулей и SMP, с пространствами имён, cgroups, Landlock и ужесточениями; - комната: ядро грузится в QEMU,
init— свой бинарь на Rust. Внутри нет shell и coreutils;initсам монтируетdev,proc,sys, проверяет возможности и ведёт журнал; - цикл (
core-rs/src/loopmod.rs): модель отвечает одной строкой —TOOL <имя> <аргумент>,DONE <итог>илиBLOCKED <почему>; цикл разбирает ответ, исполняет инструмент и пишет событие в журнал. У прогона есть бюджет по шагам, времени и деньгам; - инструменты:
search(со сводкой «в каких файлах сколько совпадений»),list,read <файл> [строка](с продолжением),writeвнутри рабочего каталога,seal,netprobe; все ограничены каталогом, выдача — по критерию; - мост наружу (
bin/bridge.py) — единственное место, где живёт ключ провайдера; комната говорит с ним plain HTTP, TLS и ключ остаются на хосте; - три слоя проверки: форма (порядок событий), опора (ответ должен делить с журналом конкретное
слово — цифру, путь, id), приёмка (
bin/accept.py: критерий объявлен до прогона, лежит на хосте и проверяет вынесенный из комнаты журнал); - продолжение после обрыва: журнал читается до первой невалидной записи, состояние восстанавливается, прогон продолжается с того же места; нечитаемый хвост отрезается с записью об этом (ADR-0051);
- метрики собственной работы (
bin/judge_metrics.py): ложное «готово»,pass@1,pass^2, цена принятого результата; - 27 гейтов (
bin/hs.py gates), из них два с полноценным отрицательным контролем — «автономия» и «решения».
| показатель | значение |
|---|---|
утверждений: ядро 17, учётных 202 (всего 219), покрытие 1.00, CHECKED_ANCHORED |
|
| что считается ядром | lab/core-claims.txt, проверяется гейтом «ядро утверждений» |
| гейтов | 27, зелёные |
| записанных отказов | 34 (F-0001…F-0034) |
| ложных «готово» | 0 из 22 заявлений (false_completion_rate = 0.00) |
pass@1 / pass^2 |
0.56 / 0.61 по 39 прогонам |
| прогонов без заявления | 17; из 26 разобранных молчаний 15 — зацикливание на одном файле |
| MuSiQue (внешняя разметка) | 6 задач: до верного ответа дошли 2, стабильно принята 1 |
| отказ на неразрешимой задаче | 0 из 6 → 1 из 3 после того, как BLOCKED попал в подсказку |
Короткая формула: проверяет хорошо, работает плохо. Ложных «готово» прибор не пропускает, но и принятых результатов даёт мало — половина прогонов заканчивается молчанием, а две трети молчаний это тупик в одном файле. Для автономной работы это главный дефект, важнее любого улучшения проверки.
- Не работающий продукт. Нет релиза и нет выполненного внешнего задания.
- Не доказательство, что «плоскость свидетельств» — единственно верное ядро. Это выбранная предпосылка (ADR-0029), и она оправдана целью, а не сама собой.
- Не «умнее». Разница не в правильности ответов, а в том, что остаётся, чем проверить, и что сказано о границах.
- Не полная изоляция. Нет shell, инструменты не выходят из каталога, фильтр syscall ставится, если ядро умеет, и об этом честно пишется в журнал. Это не защита от целевого обхода.
- Не «задача решена». Приёмка проверяет объявленные условия; если критерий неполон, PASS этого не покажет.
Границы — NOT-CLAIMED.md; отброшенное — docs/eliminations.md; отказы — lab/failures/.
ядро 6.18.60 ──> init (Rust) ──> цикл ──> инструменты (search/list/read/write/seal)
│ │
│ └─ журнал HSJ1: запись с CRC, границы коммита, хвост не чинится
└─ песочница: namespaces, Landlock, seccomp (если ядро умеет)
│
хост: мост (ключ, TLS) <── plain HTTP ── комната
приёмка (accept/) <── журнал, вынесенный на диск
метрики (judge_metrics) ← те же журналы
bin/ гейты и проверки (hs.py), мост, приёмка, метрики, доказательства
core-rs/ ядро, init, цикл, песочница, модели; сборка и прогоны в QEMU
accept/ критерии приёмки (в комнату не попадают)
docs/ ADR, журнал решений, обзор сверху, реестр исключённого
lab/ гипотезы, отказы, склад решений (adoptions.json), правила автономии
research/ склады источников и данных, артефакты прогонов
CLAIMS.md реестр утверждений: тип свидетельства, команда проверки, границы
NOT-CLAIMED.md что сознательно не утверждаем
python bin/hs.py gates # 27 гейтов: секреты, утверждения, ссылки, автономия, решения
python bin/hs.py selftest # негативные тесты самого инструмента
python bin/judge_metrics.py # ложное «готово», pass@1, pass^2, цена принятого
python bin/silence_report.py # почему прогон закончился без заявления
python bin/check_autonomy.py --paths CITATION.cff # должен дать exit 1
python bin/check_adoptions.py --self-test # 5 отказов на 5 подложенных дефектов
python bin/accept.py accept/room-claims-statistics-v3.json <журнал.bin>
Прогон в своём ядре:
pwsh core-rs/run.ps1
pwsh core-rs/accept-run.ps1 -Mode loop-bridge -Kernel vmlinuz-own-net -Net -Task "..."
Чтение не связано с решением — значит, бесполезно. Поэтому цикл из шести шагов, и каждый шаг оставляет артефакт:
- Склад — источник попадает в
research/REFS-INDEX.md,DATA-LINKS.mdилиHARNESSES-INDEX.mdв тот же день, со статусом[Ч]читал /[А]только описание /[?]не открывал. - Вопрос, а не тема — «как у них решён выход из тупика», а не «посмотрим, что есть».
- Разбор —
research/<NAME>-REVIEW.md: что механизм делает, какая цена, где доверенная граница и что у них слабее нас. - Решение — строка в
lab/adoptions.json(иdocs/CATALOG.md): берём / не берём / отложить, с причиной. - Гипотеза — в
lab/registry.json, с ожидаемым исходом и отрицательным контролем. - Внедрение и проверка — код, тест, прогон; нет эффекта → пишется отказ (
F-0033,F-0034,C-0215).
Правило исполняется гейтом «решения»: механизм нельзя внедрить, если в складе нет строки с
источником и отрицательным контролем. Гейт проверен отрицательным контролем самого себя
(--self-test: пять подложенных дефектов → пять отказов). Это защита от «правил по памяти» —
случая, когда описанного механизма в источнике не оказывается.
Текущий склад: 45 источников литературы, 38 ссылок на данные, 9 харнессов; 7 решений (5 внедрено, 1 отклонено, 1 отложено).
Порядок выведен из цели, а не из интереса:
- Выход из тупика в цикле — счётчик бесплодных обращений к одному пути; после N смена файла,
после M — принудительный
BLOCKED. Подсказкой это не лечится (C-0215), нужен механизм. clarify: спросить вместо угадывать — статусneeds-inputи критерий, который его засчитывает.- Длинная работа — пять обрывов подряд, бюджет кампании (
max_total_steps/allowance/wall_clock) со статусомbudget-campaign. - Метрика полезности —
accepted_per_hour,accepted_per_dollar,useful_work_share. - Хуки на хосте — проверка до действия, когда появятся внешние эффекты.
- Отрицательный контроль для всех 27 гейтов (сейчас два из 27).
Ожидаемый эффект шага 1: доля молчаний падает, pass@1 растёт, false_completion_rate
остаётся 0.00. Это и есть доказательство, что мы усилили эффективность, а не ослабили проверку.
Полный обзор — docs/TOP-REVIEW.md. Состояние для аудита — docs/AUDIT-STATE.md.
- Число без команды — не результат. У каждой цифры рядом команда и артефакт.
- Отрицательный результат остаётся.
docs/eliminations.md,lab/failures/, отклонённые решения в складе — не свалка. - Каждый отчёт содержит раздел «что это не доказывает».
Подробнее — AGENTS.md. Реестр утверждений — CLAIMS.md. Границы — NOT-CLAIMED.md.
О названии. herness — от «her» и «harness»: то, что впрягает в работу не вообще, а под
конкретного человека, с его границами.