Слой записей
Область версии: эта страница излагает нормативный слой записей v6, на котором строится текущий стандарт DWP 7.0.0. Канонические источники в релизе
v7.9.0:V6_CONTRACT.mdиV6_LIFECYCLE.md. Если эта страница расходится с этими файлами, приоритет у файлов. Планы v5 сохраняют слой состояния плана и никогда не мигрируются неявно.
Версия 6.0.0, расширена в 7.0.0. Статус: стабильная. Слой записей заменяет повествовательное завершение записями: контракт — это источник полномочий, журнал — память, запись выполняют вспомогательные утилиты (helpers), а каждый генерируемый файл — это проекция. Ключевые слова MUST, MUST NOT, SHOULD, SHOULD NOT и MAY следует трактовать так, как описано в RFC 2119.
Модель в одной строке
План — это два авторских артефакта и одна защищённая последовательность. Markdown-план (README.md и файлы задач) описывает, что будет сделано. Контракт результата (contract.json) определяет, что считается выполненным и что плану разрешено делать. Журнал (journal.ndjson) фиксирует, что произошло на самом деле. state.json и views/ регенерируются из журнала и MUST NOT редактироваться вручную; если сгенерированный файл расходится с журналом, побеждает журнал, а файл регенерируется.
Определение поколения
Папка плана является планом линии v6 тогда и только тогда, когда она содержит manifest.json, чей указатель contract разрешается, contract.json или цепочку ревизий contracts/. Определение MUST опираться на эти артефакты, а не на версию установленного пакета: текущий пакет может содержать планы v5, а более старый пакет может встретить план v6.
URL schema контракта задаёт его поколение, и манифест, и каждое событие журнала повторяют его:
| Поколение | Контракт | События журнала | Манифест | Добавляет |
|---|---|---|---|---|
| v6 | plan-contract/v6 |
journal-event/v6 |
plan-manifest/v6 |
— |
| v7 | plan-contract/v7 |
journal-event/v7 |
plan-manifest/v7 |
parallel_safe и событие delegation (Делегирование) |
Новые планы, созданные пакетом 7.x, по умолчанию имеют поколение v7; явный запрос v6 по-прежнему материализует контракт v6. План никогда не меняет поколение, а журнал, смешивающий поколения, MUST быть отклонён. Оба поколения проецируются в одну и ту же форму plan-snapshot/v6.
Контракт результата
Один контракт на план, соответствующий схеме своего поколения. Он содержит формулировку результата и определение успеха, критерии приёмки, задачи с их предпосылками, затронутой поверхностью и намерением gate, инварианты уровня плана, область действия (разрешённые пути, классы команд, запрещённые операции), ресурсный конверт, ограничения планирования, разрешения и запись об авторизации.
- Идентичность.
contract_id— это SHA-256 канонических байтов контракта без поля идентификатора. Каждая запись, созданная по контракту, ссылается на него. - Неизменяемость. После начала выполнения контракт MUST NOT меняться. Изменённый контракт — это новая ревизия в
contracts/, ссылающаяся на родительскую, с непрерывной нумерацией ревизий и заново зафиксированными полномочиями. - Стабильные идентификаторы. Критерии (
AC-*), инварианты (INV-*) и задачи (T-*) MUST быть уникальными, а записи ссылаются на идентификаторы, а не на позиции в списках. Граф задач MUST быть ациклическим, и каждое намерение gate MUST ссылаться на объявленный критерий. - Разрешения. Предоставленные и непредоставленные возможности MUST быть непересекающимися подмножествами закрытого набора:
gate_command_exec,fs_write_plan_scope,fs_write_repo_scope,git_operations,network_access,host_adapter_metering,agent_delegation,context_export. - Авторизация. Механизм — строго
plan_authorship(человек написал или просмотрел план до выполнения) либоpre_authorization(постоянное разрешение с указанным конвертом, как в режиме доверия). Оба проходят gate одинаково; различаются только зафиксированные полномочия. - Закрываемость. Каждый критерий MUST быть закрываемым: критерий, который проверяет gate задачи, закрывается доказательством
observedот этого gate или подписью человекаassertedв соответствии с классами доказательств, которые он принимает. Черновой критерий, не принимающий ни один из них, отклоняется.
Материализация
План материализуется поставляемой утилитой (ledger.py materialize), а не вручную, строго в следующем порядке; каждый шаг идемпотентен и возобновляем:
manifest.jsonс указателем на контракт, записывается первым, чтобы поколение плана можно было определить, даже если материализация прервана.contract.json, провалидированный и адресуемый по содержимому.- Событие журнала
approval, ссылающееся на идентификатор контракта и дайджест markdown-плана.
Только это событие одобрения открывает gate начала задачи. Скопированный вручную контракт без него отклоняется при старте задачи, а манифест, чей указатель не совпадает с материализуемым контрактом, отклоняется, а не переписывается.
Журнал
journal.ndjson допускает только добавление: один замкнутый JSON-объект на строку, никогда не редактируется и не удаляется. Исправление — это более позднее событие. Каждое событие содержит схему, тип, строго возрастающий seq, временную метку, план, contract_id и действующее лицо (helper, agent, host_adapter или human). Каталог событий охватывает старты задач, одобрения, запуски gate, наблюдения, адаптации, поправки, вмешательства, выборки ресурсов, контрольные пары, выборы планировщика, отказы, рендеринг представлений, согласования и восстановления журнала; v7 добавляет события делегирования. Каждый отказ сам фиксируется.
Классы доказательств
События, несущие доказательства, фиксируют метку доверия:
- observed — проверку выполнила сама поставляемая утилита с объявленными рабочим каталогом, окружением, таймаутом и захваченным выводом. Доказательства gate класса observed выпускает только исполнитель gate (
ledger.py gate); агент, который лишь записывает сообщённый им результат, этого сделать не может. - imported — получено из сопоставленного внешнего источника с указанием происхождения, например мигрированная запись gate v5, чей указатель на доказательство разрешается.
- asserted — заявлено без независимого подтверждения.
Каждый критерий объявляет, какие классы он принимает, поэтому критерий, принимающий только observed, никогда не закроется по заявлению. Контрольные суммы устанавливают побайтовую идентичность, а не семантическую истинность; слой записей проверяет структуру и происхождение и не доказывает семантику продукта.
Подписание человеком
Критерий, который должен оценить человек, закрывается через ledger.py signoff --criterion <AC> --evidence-path <artifact> --authority <who>. Подпись фиксируется как asserted, ссылается на артефакт, на котором основана, учитывается только внутри окна доказательств объявляющей задачи и закрывает только критерий, принимающий asserted. Агент никогда не подписывает за человека. Записи с действующим лицом-человеком, сделанные вне материализации, несут явный маркер полномочий (заметку, написанную человеком и зафиксированную по пути и дайджесту, или интерактивное подтверждение); журнал не может аутентифицировать человека, поэтому маркер делает заявление проверяемым, а не наблюдаемым.
Контролируемые критерии
Критерий, объявленный как контроль регрессии или различения, закрывается только различающей контрольной парой: проверка не проходит на исходной ревизии и проходит на новой. Пара, проходящая на обеих сторонах, фиксируется как неразличающая и никогда не округляется в пользу прохождения; грязное исходное состояние или недоступная старая сторона фиксируются как недоступный контроль и никогда не синтезируются.
Выполнение и завершение
Диспетчеризация выполняется детерминированным планировщиком (scheduler.py ready), а ledger.py start отклоняет задачу с незавершёнными предпосылками. Каждый старт задачи фиксирует отпечаток рабочего дерева, и доказательства переиспользуются только для той же задачи и того же критерия при эквивалентном отпечатке.
Инварианты действуют на уровне плана. Каждый объявленный инвариант соблюдается на протяжении всего плана и оценивается на каждой границе как наблюдение (INV-<id>: pass или INV-<id>: fail: <reason>). Свойство, которое должны соблюдать только некоторые задачи, — это критерий приёмки этих задач, а не инвариант.
Завершение выводится, а не объявляется. ledger.py complete отказывает и фиксирует отказ, пока у какого-либо критерия нет принятых доказательств внутри окна или у какого-либо инварианта нет свежей успешной оценки. Снимок показывает задачу завершённой ровно тогда, когда это подтверждают записи.
Адаптации и поправки
Изменения во время выполнения — это предложения планировщику, ограниченные закрытым набором: split, reorder, insert, change_strategy и retry. Адаптация MUST NOT удалять требование, ослаблять или подменять приёмку, расширять область действия или разрешения, тратить сверх конверта или отмечать невыполненный сценарий как завершённый.
Изменение области действия, критериев приёмки, разрешений или конверта — это поправка к контракту: ledger.py amend подготавливает пересмотренный контракт как следующую ревизию, фиксирует поправку вместе с критериями, чьи прежние доказательства она аннулирует, требует нового одобрения с маркером полномочий человека и только затем переключает действующий контракт. Прерванная поправка возобновляется с первого недостающего шага; авторство плана никогда не переносится на ревизию.
Квитанции, представления и экспорт
outcomes.py receipt пересчитывает результат плана по записям, поэтому он меняется при изменении записей; он никогда не пишется вручную. views.py render регенерирует человекочитаемые представления; представление, отредактированное человеком, попадает в отчёт и никогда не перезаписывается молча, а согласование само фиксируется. Поскольку .dwp/ находится в gitignore, ledger.py export --dest <dir> упаковывает журнал, снимок, цепочку контрактов и каждый цитируемый артефакт доказательств для долговременного хранения или для другого хоста.
Поверхности только для чтения и возобновление
status и verify никогда не пишут в план линии v6; они сообщают результаты через чистые команды и сгенерированные проекции. Возобновляющий хост восстанавливается в фиксированном порядке (осмотр, валидация, проекция, рендеринг с зафиксированными полномочиями) и рассматривает устаревший отпечаток как аннулированное доказательство, которое нужно перезапустить, а не как переиспользуемый результат. Журнал никогда не воспроизводится как контекст разговора: работа возобновляется через цикл execute с манифестом контекста для каждой задачи.
Сосуществование и миграция
Планы v5 и линии v6 MAY сосуществовать в одном .dwp/plans/, и каждый работает в своём поколении на протяжении всей жизни. Единственный путь от v5 к v6 — явная миграция с предварительным просмотром (migrate_v6.py, запускается через refine) с проверенной резервной копией и откатом; мигрированная история v5 получает класс imported, если её доказательства разрешаются, и asserted в противном случае, но никогда observed. Обратной миграции нет.
Связанные страницы
- Ресурсы и возможности — манифест контекста, ресурсный конверт, возможности хоста и реестр аддонов.
- Делегирование — что v7 добавляет к этому слою.
- Состояние плана — сохранённый слой состояния v5.