Перейти к содержанию

Справочник

Кому это? Тому, кто спрашивает, что проверка ловит, что печатает и зачем вообще существует. Когда читать? При выборе проверки или когда одна из них только что сработала. Как включить — таблица в гайде; все ключи — конфигурация.


По разделу на ситуацию, с тем выводом, который инструмент печатает на самом деле, — ничего нарисованного. В каждом названа проверка, которую надо включить, и откуда взялось правило; рассуждение о модели целиком — в стандарте.

Проверка Падает, когда
proof файл, тест или команда из задокументированного утверждения исчезли
tracks трек ссылается на удалённый хендофф
tasks отмеченная галочка не называет проверку
queue пункт, объявленный проходящим, падает при перезапуске
locked коммит агента тронул файлы, которые его оценивают
cold-start свежий клон не может установиться и проверить себя
clean-exit сессия оставила мусор или ничего не записала
instructions файл инструкций вышел за лимит строк
release манифест, changelog и теги расходятся

1. README описывает то, чего не существует

Откуда: Лекция 03 — репозиторий как источник правды. Не из курса: сам синтаксис маркеров, он вырос из продакшн-репозиториев.

Унаследованный репозиторий или агент, задокументировавший свои намерения.

Вы один раз пишете утверждение и прикрепляете к нему доказательство:

Суммы округляются по валюте, а не по строке.   <!-- proof: docs/<файл>.md -->
Проверить самому: `make verify`.               <!-- proof: make <цель> -->

(Настоящий маркер называет настоящий путь; угловые скобки выше нужны только для того, чтобы примеры на этой странице не проверялись как утверждения.) Удалите документ или переименуйте цель — и сборка об этом скажет:

FAIL  proof markers
  README.md:31  docs/ARCHITECTURE.md
      no such file
  README.md:32  make verify
      no make command named "verify"

Включить: docs. Документы, которым нельзя расходиться с кодом, добавьте в docs.mustCarryProof — они обязаны нести хотя бы один маркер, чтобы переписывание не могло незаметно выбросить доказательство вместе с утверждением.

2. «У меня работает» — и только там

Откуда: Лекции 03 и 10 — репозиторий как источник правды и реальный прогон как доказательство.

Онбординг, новая сессия агента, чистый раннер CI.

cold-start клонирует ваш репозиторий в пустой каталог и запускает те команды, которые ваша же документация даёт новичку. Без кэшей, без перенесённого окружения, без того, что есть только на машине, где это собиралось.

FAIL  cold start
  the clone ran: npm ci && npm test
    npm ci failed: package-lock.json is not committed

Включить: coldStart, перечислив requiredFiles, entryDocs и commands, которые выполняет новичок.

10. Ключ, цвет или импорт не на своём месте

Откуда: не из курса. Оба репозитория, из которых выросла эта библиотека, написали это правило руками и по-разному — потому что объявить его было негде.

Правило живёт в чьей-то голове, в скрипте или в комментарии на ревью, которого в этот раз никто не написал.

Один репозиторий запрещает service-role-ключ где-либо под app/: он обходит row-level security, поэтому использование на клиенте — это утечка данных в одежде обычного импорта. Он же запрещает захардкоженные цвета в компонентах, потому что дизайн-токены живут в одном файле. Другой запрещает маркеры-заглушки в опубликованном контенте. Три правила, одна форма: этот шаблон, не в этих файлах, по этой причине.

FAIL  boundaries
  app/dashboard/page.tsx:14  service_role
      the service-role key bypasses row-level security; it belongs on the server

Причина обязательна, и в ней весь смысл. Граница, печатающая «совпало /service_role/», говорит, что случилось; следующему человеку нужно знать, что делать вместо этого.

Включить: boundaries со списком правил из pattern, paths и reason (плюс allow для того единственного законного места). Этот репозиторий применяет одно к себе: импорт в src/, который не node:-встроенный и не относительный, — это runtime-зависимость, которую его же ограничения запрещают. Раньше это была проза, которую ревьюер должен был помнить, теперь — строка, которая падает.


11. Число качества, которое тихо просело

Откуда: не из курса. Оба репозитория, из которых выросла эта библиотека, изобрели это правило независимо и развели его руками.

Эвалы по-прежнему идут. Число каждый месяц чуть ниже, и ни один месяц не тот, в который это кто-то замечает.

Один репозиторий держит evals/thresholds.json — recall, groundedness, валидность цитат, у каждой свой пол — и роняет CI, когда оценка падает ниже. У другого гейт на обоснованность с проходным баллом. Оба держат файл с полами вне досягаемости агента, и это несущая половина: цикл, который может опустить себе проходной балл, оценивает сам себя.

FAIL  thresholds
  evals/results.json:1  recall_at_5
      0.71 is below the floor of 0.8 declared in evals/thresholds.json
    fix:  raise the score. Lowering the floor to pass is the move this check exists to catch

Она не считает ваши метрики. Ваша команда пишет файл результатов, а проверка читает и сравнивает. Метрика, у которой есть пол, но которую никто не измерил, тоже падает: шаг подсчёта, который не запускался, — это не шаг подсчёта, который прошёл.

Включить: thresholds, назвав results, floors и command, которая создаёт результаты. Если репозиторий уже объявил locked.paths, а файла с полами среди них нет, проверка об этом скажет. Только полы: метрика, где меньше значит лучше, — то же правило зеркально, а придумывать направление на нуле реальных случаев было бы гаданием.


3. Фича, которая занимает четыре сессии

Откуда: Лекция 05 — непрерывность между сессиями. Форма хендоффа не из курса.

Контекст умирает в конце каждой сессии; следующая выводит его заново или заново решает уже решённый вопрос.

Живая работа лежит в specs/TRACKS.md — по строке на трек, каждая указывает на handoff.md, где написано, что загрузить, чего не загружать, где работа остановилась и какой первый шаг. Следующая сессия получает это на старте, а не перечитывает репозиторий:

$ harnessimo brief
== specs/TRACKS.md (live work tracks — load a track's handoff first) ==
- Checkout totals — [handoff](specs/0007-checkout/handoff.md) — active, next: T3 currency rounding
- Hosted deploy — none — blocked (on an API token)

Индекс проверяется машиной, потому что handoff, который врёт, хуже, чем его отсутствие: трек без статуса или ссылка на удалённый handoff роняют гейт.

Включить: tracks.

4. «Готово», которое перестало быть правдой

Откуда: Лекции 08 и 09 — списки фич как примитивы и преждевременное объявление победы.

Задача действительно была закончена в марте. В мае её сломало что-то постороннее, а на доске по-прежнему «готово».

У каждого элемента очереди есть своя команда проверки. passing пишет только инструмент и только после того, как эта команда вернула 0, — а --reverify перезапускает их все в CI:

FAIL  queue
  "checkout-totals" claims passing but its verification fails now
    command: npm test -- checkout
    fix:  fix the regression, or the claim was never true

Поправить state руками — не короткий путь, а ровно то, что эта проверка и ловит.

Включить: queue.

5. Агент, который правит собственный экзамен

Откуда: Не из курса. Locked-поверхности выросли из продакшена, где агент правил скрипт, который его же оценивал.

Самый быстрый способ сделать красную сборку зелёной — поменять определение зелёного.

Назовите поверхности, которые задают успех: workflow'ы CI, файл ограничений, пороги эвалов. Коммит с трейлером агента, который их трогает, роняет сборку:

FAIL  locked surfaces
  a1b2c3d  Co-Authored-By: Claude  touched .github/workflows/ci.yml
    fix:  a human makes this change, or the baseline records why it moved

Это детекция дрейфа в CI, а не песочница: она ловит честный случай, который и является частым.

Включить: locked, с paths, baseline и вашим agentTrailer.

6. Долгий прогон без присмотра

Откуда: Лекция 12 — чистое состояние на выходе из сессии.

Вы его запускаете и идёте спать.

clean-exit читает то, что сессия на самом деле изменила, и не пропускает два способа плохо закончить, не упав: мусор, оставленный в коде (TODO, debugger, .only( — маркеры выбираете вы), и файл прогресса, который остался нетронутым, пока вокруг поменялись сотни строк.

FAIL  clean exit
  src/checkout/totals.ts:88        debugger
  .harness/4-state/PROGRESS.md     unchanged while 412 lines of code moved
    fix:  write down where this got to, or the next session starts blind

Включить: cleanExit. Порог progressThreshold не даёт правке в одну строку уронить проверку.

7. «А что этот репозиторий вообще гарантирует?»

Откуда: Лекция 04 — один огромный файл инструкций не работает; честность doctor — собственное правило этого проекта.

Новый контрибьютор, ревью или вы сами через полгода.

$ harnessimo doctor
  enforced      proof markers    docs claims resolve to real files, tests and commands
  enforced      work tracks      the track index resolves and every track carries a status
  not enforced  queue            no queue section in harnessimo.config.json

Проверка, которую вы не настроили, выводится как not enforced — там же и тем же весом. Харнес, преувеличивающий собственное покрытие, — это тот самый провал, ради предотвращения которого он существует.

8. Версия означает разное в разных местах

Откуда: Не из курса и ниоткуда больше: этот репозиторий опубликовал три версии дальше собственного последнего тега.

Бейдж говорит одно, реестр отдаёт другое, и оба правы относительно себя.

Это не гипотетический случай: пока писался этот инструмент, три версии уехали в npm через ручной запуск workflow, а собственные теги репозитория остановились двумя релизами раньше. Никто не заметил, потому что никто не проверял самое дублируемое утверждение, какое делает проект.

FAIL  release
  CHANGELOG.md:1  v0.4.3
      0.4.3 is described as released and has no v0.4.3 tag
    why:  a version published outside the release flow leaves the repository behind
    fix:  cut the release, or remove the entry if it never shipped

Включить: release, указав манифест, changelog и префикс тега. Он читает версию из манифеста, записи из changelog и теги из git; версия, которую никто не записал, запись не на верхней позиции и выпущенная версия без тега — всё это падает.


9. Сессия дорогая, и никто не считает

Долгие прогоны агента, где большая часть бюджета уходит до того, как что-то закончено.

Самая крупная устранимая статья расходов в долгой сессии — один и тот же файл, прочитанный дважды. Второе чтение стоит всей своей длины снова и не сообщает модели ничего, чего у неё уже нет, — и об этом никто не отчитывается, поэтому никто это и не чинит.

$ harnessimo budget
harnessimo budget — this session (estimated at 4 bytes per token)

  read          38 file(s), ~184k tokens
  re-read        9 file(s), ~41k tokens — 22% of everything read
  largest     src/pipeline.ts, read 3×, ~7k each

  fix:  a re-read is a session that lost its place. `harnessimo guard read <path>`
        refuses the second read of a file that has not changed.

Подключённый как хук на использование инструмента, guard отвечает до того, как чтение произойдёт: первый раз — можно, второй без изменений — нет, изменился — снова можно. Диапазон не равен целому файлу, а --override всегда побеждает — и попадает в счёт, чтобы мешающее правило было видно в отчёте, а не в чьём-то раздражении.

Включить: tokens. Это не десятая проверка: девять отвечают на вопрос «закончено ли», а эта срабатывает в момент работы. doctor показывает её отдельно именно поэтому, и check её не запускает — гейт завершённости, зависящий от состояния сессии, был бы гейтом, который никто не сможет воспроизвести.


Сессия целиком

$ harnessimo brief
== specs/TRACKS.md (live work tracks — load a track's handoff first) ==
- Checkout totals — [handoff](specs/0007-checkout/handoff.md) — active, next: T3 currency rounding

== work queue ==
active: checkout-totals — an order total matches the sum of its lines, in every currency
  verify with: harnessimo queue verify checkout-totals

== enforced here ==
proof, tracks, tasks, queue, coldStart, cleanExit

# ... агент работает ...

$ harnessimo queue verify checkout-totals
running: npm test -- checkout
  ✓ 12 tests passed
checkout-totals: passing — evidence recorded

$ git commit -m "feat(checkout): per-currency rounding (0007)"
harnessimo: proof markers ok · tracks ok · task gate ok · queue ok
[main 4f1a2b9] feat(checkout): per-currency rounding (0007)

Коммит прошёл, потому что прошли проверки, а не потому, что кто-то сказал, что готово.


Дальше: что взято из OpenSpec, Spec Kit, BMAD и остальных · внедрение в существующий репозиторий