devcontour-harness 0.1.0-alpha.16 → 0.1.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -2
- package/docs/architecture.md +119 -3
- package/docs/contracts.md +3 -0
- package/docs/quickstart.md +1 -1
- package/docs/release-notes/0.1.0-alpha.17.md +86 -0
- package/docs/release-notes/0.1.0-alpha.18.md +48 -0
- package/docs/release-notes/0.1.0-alpha.19.md +96 -0
- package/docs/review-probes.md +9 -3
- package/docs/review-protocol.md +9 -0
- package/docs/upgrade.md +17 -15
- package/lib/agents/cli-adapter.js +14 -10
- package/lib/agents/review-probe.d.ts +9 -0
- package/lib/agents/review-probe.js +23 -1
- package/lib/agents/schemas.d.ts +206 -0
- package/lib/agents/schemas.js +37 -1
- package/lib/agents/usage.d.ts +22 -0
- package/lib/agents/usage.js +112 -6
- package/lib/cli.js +7 -1
- package/lib/contracts/cli.d.ts +60 -2
- package/lib/contracts/diagnosis.d.ts +3 -1
- package/lib/contracts/diagnosis.js +2 -0
- package/lib/contracts/events.d.ts +33 -0
- package/lib/contracts/events.js +7 -0
- package/lib/contracts/execution.d.ts +105 -8
- package/lib/contracts/execution.js +71 -1
- package/lib/contracts/failure.d.ts +17 -3
- package/lib/contracts/failure.js +4 -2
- package/lib/contracts/planning.js +2 -2
- package/lib/contracts/policy.d.ts +1 -1
- package/lib/contracts/ports.d.ts +6 -0
- package/lib/contracts/primitives.d.ts +13 -0
- package/lib/contracts/primitives.js +15 -0
- package/lib/contracts/profiles.js +2 -2
- package/lib/contracts/published.d.ts +62 -3
- package/lib/contracts/repair-policy.d.ts +7 -0
- package/lib/contracts/repair-policy.js +17 -0
- package/lib/contracts/review.d.ts +14 -2
- package/lib/contracts/review.js +20 -1
- package/lib/contracts/work.js +3 -3
- package/lib/control/base-move.js +2 -2
- package/lib/control/harness.d.ts +3 -3
- package/lib/control/harness.js +7 -2
- package/lib/control/recovery.d.ts +1 -1
- package/lib/control/workflow.js +6 -0
- package/lib/engine/budget.d.ts +1 -1
- package/lib/engine/engine.d.ts +53 -14
- package/lib/engine/engine.js +132 -9
- package/lib/engine/failure.d.ts +1 -1
- package/lib/engine/failure.js +1 -1
- package/lib/engine/property-recovery.d.ts +1 -0
- package/lib/engine/property-recovery.js +4 -1
- package/lib/engine/repair.d.ts +26 -0
- package/lib/engine/repair.js +83 -1
- package/lib/engine/runner.d.ts +18 -1
- package/lib/engine/runner.js +261 -42
- package/lib/environment/git-trust.d.ts +36 -0
- package/lib/environment/git-trust.js +174 -0
- package/lib/environment/isolation.d.ts +103 -1
- package/lib/environment/isolation.js +340 -5
- package/lib/environment/process.d.ts +5 -0
- package/lib/environment/process.js +20 -1
- package/lib/explain/state.js +4 -2
- package/lib/index.d.ts +6 -2
- package/lib/index.js +8 -2
- package/lib/integrations/connector/config.js +2 -2
- package/lib/projections/stop.d.ts +1 -1
- package/lib/projections/stop.js +16 -0
- package/lib/storage/document.d.ts +58 -10
- package/lib/verification/already-satisfied.d.ts +44 -0
- package/lib/verification/already-satisfied.js +49 -0
- package/lib/verification/confirm.js +2 -2
- package/lib/verification/gate-scope.d.ts +36 -0
- package/lib/verification/gate-scope.js +97 -0
- package/lib/verification/gates-at.d.ts +67 -0
- package/lib/verification/gates-at.js +173 -0
- package/lib/verification/gates.d.ts +17 -1
- package/lib/verification/gates.js +87 -9
- package/lib/verification/requirements.js +6 -1
- package/package.json +1 -1
- package/schemas/execution-document.schema.json +160 -4
- package/schemas/plan-draft.schema.json +2 -2
- package/schemas/run-event.schema.json +26 -0
- package/schemas/stop-diagnosis.schema.json +2 -0
- package/schemas/work-graph.schema.json +2 -2
- package/schemas/work-order.schema.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Headless-движок исполнения инженерных поручени
|
|
|
5
5
|
интеграция с принятой веткой через compare-and-swap и машинный результат с SHA
|
|
6
6
|
и доказательствами.
|
|
7
7
|
|
|
8
|
-
> Статус: `0.1.0-alpha.
|
|
8
|
+
> Статус: `0.1.0-alpha.19` — предварительный выпуск (alpha). Договоры
|
|
9
9
|
> `v1alpha1` могут измениться между alpha-версиями; закрепляйте точную версию.
|
|
10
10
|
> Файл → ревью плана → кандидат → интеграция → принятие → результат JSON, с
|
|
11
11
|
> ограниченным восстановлением, повторным использованием кандидата, бюджетами,
|
|
@@ -28,7 +28,7 @@ Headless-движок исполнения инженерных поручени
|
|
|
28
28
|
Из npm — точная версия (воспроизводимо) или последняя alpha по тегу:
|
|
29
29
|
|
|
30
30
|
```sh
|
|
31
|
-
npm install --save-exact devcontour-harness@0.1.0-alpha.
|
|
31
|
+
npm install --save-exact devcontour-harness@0.1.0-alpha.19 # точная версия
|
|
32
32
|
# или: npm install --save-exact devcontour-harness@alpha # текущая alpha
|
|
33
33
|
npx harness --version
|
|
34
34
|
```
|
|
@@ -123,6 +123,32 @@ PASS» нет. Адаптеры хоста реализуют порты `Execut
|
|
|
123
123
|
`devcontour-harness/schemas/<имя>.schema.json`. Декларации используют типы
|
|
124
124
|
Node.js: TypeScript-потребителю нужен `@types/node` (или `skipLibCheck`).
|
|
125
125
|
|
|
126
|
+
## Выпуск 0.1.0-alpha.19
|
|
127
|
+
|
|
128
|
+
Провал gate интеграции после зелёного кандидата повторяется один раз
|
|
129
|
+
(`recheck`; контрпример свойства или корпуса — нет); области gates до
|
|
130
|
+
`GATE_SCOPE_LIMIT`; дешевле такты очереди. Песочница: каталоги IDE внутри
|
|
131
|
+
`node_modules` открыты, запреты `.git` явные, git хоста сверяет checkout
|
|
132
|
+
(`hostGitArgs`) и снимает исполняемые настройки, защищённые пути сверяются
|
|
133
|
+
после gate, класс `environment` — только по журналу ядра. Подробно и с
|
|
134
|
+
известными пробелами — [заметки выпуска](docs/release-notes/0.1.0-alpha.19.md).
|
|
135
|
+
|
|
136
|
+
## Выпуск 0.1.0-alpha.18
|
|
137
|
+
|
|
138
|
+
`runGatesAt` исполняет gates с предпосылками профиля: явный `dependsOn` или,
|
|
139
|
+
в профиле без него, более ранние check gates (установка); общий с попыткой
|
|
140
|
+
порядок `orderedScope`; все провалы — сразу; `dependsOn: []` — без
|
|
141
|
+
предпосылок. Подробно — [заметки выпуска](docs/release-notes/0.1.0-alpha.18.md).
|
|
142
|
+
|
|
143
|
+
## Выпуск 0.1.0-alpha.17
|
|
144
|
+
|
|
145
|
+
Меньше слепых повторов: reviewer называет класс входов, два отказа ревью по
|
|
146
|
+
одному свойству и классу — пробел приёмки с остановкой; отказы окружения не
|
|
147
|
+
тратят попытки (свой предел), штатная остановка возвращает работу в очередь,
|
|
148
|
+
`completed: false` повторяется с черновика; пустой результат принимается
|
|
149
|
+
только с механическим основанием (иначе `needs-lead`), `runGatesAt` проверяет
|
|
150
|
+
gates на закреплённом SHA; стоимость вызова учитывается по всему потоку. Подробно — [заметки выпуска](docs/release-notes/0.1.0-alpha.17.md).
|
|
151
|
+
|
|
126
152
|
## Выпуск 0.1.0-alpha.16
|
|
127
153
|
|
|
128
154
|
Отказ по файлу эталонного набора — только по строковому литералу, без ложных
|
package/docs/architecture.md
CHANGED
|
@@ -185,6 +185,49 @@ runtime-граф пакета.
|
|
|
185
185
|
- **Покрытие gates.** `uncoveredGates` засчитывает только evidence попыток под
|
|
186
186
|
текущим основанием политики: тот же ID gate с другой командой — другая
|
|
187
187
|
проверка.
|
|
188
|
+
- **Пауза по классу отказа.** Отказ класса с `blocksQueue`
|
|
189
|
+
(`provider-auth`, `environment`) в той же транзакции ставит паузу
|
|
190
|
+
`runtime` и добавляет класс в `pauseFailures`: новых выдач нет ни одной
|
|
191
|
+
задаче. Отказ окружения до кандидата (`blocked`) попытку не засчитывает.
|
|
192
|
+
Снимает паузу `clearFailure([класс])` — его вызывает восстановление,
|
|
193
|
+
назначившее повтор (у DevContour — цикл board workflow, той же транзакцией,
|
|
194
|
+
что повтор), — или `resume` человека; выдача возвращается, когда в списке не
|
|
195
|
+
осталось классов. Поэтому разовый отказ окружения под циклом восстановления
|
|
196
|
+
останавливает выдачу только до его следующего шага, а без цикла пауза стоит
|
|
197
|
+
до решения человека. Пауза человека этим не снимается.
|
|
198
|
+
- **Gates на SHA вне попытки.** `runGatesAt` исполняет названные gates
|
|
199
|
+
компонента на закреплённом SHA так же, как integration поручения:
|
|
200
|
+
отдельное рабочее дерево, снимки зависимостей, ресурсы, lifecycle и
|
|
201
|
+
prepare, окружение фазы `integration`, песочница и `runGate`. Область —
|
|
202
|
+
названные gates и предпосылки каждого (`standaloneScope`), порядок — тот же
|
|
203
|
+
`orderedScope`, что у попытки. Предпосылки (`gatePrerequisites`): у gate с
|
|
204
|
+
объявленным `dependsOn` (в том числе пустым — режим графа) — замыкание по
|
|
205
|
+
`dependsOn`; у gate без поля `dependsOn` (профиль в режиме порядка массива)
|
|
206
|
+
— все более ранние gates вида `check` с их предпосылками: установка,
|
|
207
|
+
сборка, статические проверки. Более ранние test gates не добавляются;
|
|
208
|
+
каждый gate посещается один раз. Задаче эти предпосылки называть
|
|
209
|
+
по-прежнему приходится явно: её область исполняется как записана. Провал
|
|
210
|
+
gate не останавливает проверку. Пропускается только gate, чья явная
|
|
211
|
+
предпосылка (`dependsOn`) не прошла; провал неявной (раннего check gate)
|
|
212
|
+
тесты не пропускает — названы оба (`failures`). Evidence (`test`,
|
|
213
|
+
`integration`, этот SHA) пишется через запись хоста до следующего gate;
|
|
214
|
+
дерево обязано остаться на SHA без изменений.
|
|
215
|
+
- **Пустой результат.** Исполнитель, не изменивший ни файла, не получает
|
|
216
|
+
отказ сразу: кандидат — сама база (без коммита), gates поручения идут на
|
|
217
|
+
ней, а reviewer обеих фаз получает схему ответа с обязательным
|
|
218
|
+
`alreadySatisfied` (gates области задачи — хотя бы один test gate и все
|
|
219
|
+
проверки договоров поручения — и основание). Подтверждения reviewer мало:
|
|
220
|
+
нужно механическое основание, которое находит controller
|
|
221
|
+
(`alreadySatisfiedVerdict`): договор проверки поручения, все gates которого
|
|
222
|
+
в области задачи и названы, или зависимость поручения, чей принятый
|
|
223
|
+
результат входит в SHA, а собственный кандидат изменил файлы области записи
|
|
224
|
+
поручения. Без основания — `needs-lead` (остановка, решение ведущего): общий
|
|
225
|
+
зелёный тест на базе новой работы не доказывает. Без годного подтверждения,
|
|
226
|
+
при отклонении ревью или красном gate на базе — `empty-result`. С
|
|
227
|
+
основанием поручение принимается без нового коммита; основание пишется в
|
|
228
|
+
evidence ревью (`alreadySatisfied.basis`), и `engine.finish` повторяет
|
|
229
|
+
правило целиком по записанному, сверяя основание по зависимости с её
|
|
230
|
+
принятой попыткой.
|
|
188
231
|
- **Область записи.** Изменения вне `writeScope`, защищённых путей и
|
|
189
232
|
закреплённого контекста отклоняют попытку до интеграции.
|
|
190
233
|
- **Gates.** Тестовый gate принимается по свежему непустому отчёту без
|
|
@@ -217,11 +260,32 @@ runtime-граф пакета.
|
|
|
217
260
|
исполнение, завершено) сохраняется и переживает рестарт; владелец задания
|
|
218
261
|
fenced. Упавшее поручение повторяется только по записанному классу отказа:
|
|
219
262
|
в пределах повторов одинакового отпечатка для класса, попыток поручения
|
|
220
|
-
(`maxAttempts`) и бюджета восстановлений задания (`repairBudget`).
|
|
263
|
+
(`maxAttempts`) и бюджета восстановлений задания (`repairBudget`). Отказ
|
|
264
|
+
окружения или провайдера (и истёкшее владение) попытку поручения не
|
|
265
|
+
засчитывает, даже после кандидата: о работе он ничего не говорит; повторы
|
|
266
|
+
таких отказов ограничены паузой выдачи, пределом одинаковых отпечатков,
|
|
267
|
+
`repairBudget` и своим пределом на поручение (`MAX_NEUTRAL_FAILURES` = 3,
|
|
268
|
+
счётчик `neutralFailures`): на нём `retry` без сброса, выдача и
|
|
269
|
+
восстановление отказывают; сброс человека обнуляет счётчик. Попытка, прерванная штатной остановкой (`Runner.stop`),
|
|
270
|
+
не падает: черновик сохраняется, попытка помечается `interrupted:
|
|
271
|
+
shutdown`, поручение возвращается в очередь (`ready`) без траты попытки и
|
|
272
|
+
без паузы по классу; после снятия паузы остановки она продолжается с
|
|
273
|
+
кандидата или черновика. Интегрированная попытка так не возвращается.
|
|
274
|
+
Решение и
|
|
221
275
|
списание бюджета — одна транзакция с повтором. Отказ провайдера, отмена,
|
|
222
276
|
неизвестный класс и устаревшая база — остановка с причиной. Восстановление
|
|
223
277
|
снимает только свою причину паузы; паузу человека не снимает. Режим
|
|
224
|
-
`operator` автоматических повторов не делает.
|
|
278
|
+
`operator` автоматических повторов не делает. Тексты отказов ревью от
|
|
279
|
+
попытки к попытке разные, поэтому сверх отпечатка считается и названное:
|
|
280
|
+
два отказа ревью подряд по одному необъявленному свойству с тем же классом
|
|
281
|
+
входов (`classified`; класс сравнивается без регистра и лишних пробелов) —
|
|
282
|
+
пробел приёмки (`acceptanceGap`), остановка с `gap` и причиной для ведущего
|
|
283
|
+
вместо третьей слепой попытки. Совпадение только свойства или только класса
|
|
284
|
+
(`unboundProperties`, `inputClasses`) — слабее: общий класс бывает у разных
|
|
285
|
+
дефектов, поэтому нужно три отказа подряд.
|
|
286
|
+
Счёт — как у эпизода свойства: отказ окружения его не меняет, отказ gate,
|
|
287
|
+
другое название или новое основание поручения обрывают серию. Объявленные
|
|
288
|
+
свойства ведёт эпизод разбора.
|
|
225
289
|
- **Переиспользование кандидата.** После отказа окружения или по времени,
|
|
226
290
|
когда кандидат уже был, повтор берёт его вместо новой реализации, только
|
|
227
291
|
если совпадают все основания: постановка, контракты, политика, runtime и
|
|
@@ -398,7 +462,11 @@ runtime-граф пакета.
|
|
|
398
462
|
reviewer — получает последние 20 входов с ожиданием, наблюдением и командой.
|
|
399
463
|
Это диагностика: gate не расширяет и корпусом не становится без
|
|
400
464
|
подтверждения эталоном; обязательный корпус от ограничения реестра не
|
|
401
|
-
зависит.
|
|
465
|
+
зависит. Блокирующая находка со входом называет и нарушенное свойство или
|
|
466
|
+
критерий (`property`), и класс входов (`inputClass`) — генератор или
|
|
467
|
+
семейство, к которому относится пример. Класс записывается в реестр и на
|
|
468
|
+
отклонённую попытку (`inputClasses`); следующий writer получает задачу
|
|
469
|
+
чинить класс, а не экземпляр.
|
|
402
470
|
- **Контекст плана и согласование.** Снимок контекста хранится по digest, а
|
|
403
471
|
действующим становится только вместе с согласованием графа
|
|
404
472
|
(`approval.context`). Пока новый снимок на ревью, после его отклонения,
|
|
@@ -478,6 +546,16 @@ executable. Live smoke — отдельный opt-in с явно заданны
|
|
|
478
546
|
прежнего владельца, истёкший lease и второй controller ничего не меняют.
|
|
479
547
|
- **Точные SHA.** PASS gate и ревью относится к конкретному candidate или
|
|
480
548
|
integration SHA; доказательство другой фазы или другого SHA не засчитывается.
|
|
549
|
+
- **Повтор провала интеграции.** Если собственный gate поручения прошёл на
|
|
550
|
+
кандидате, но упал на integration, controller один раз на кандидата повторяет
|
|
551
|
+
его на том же integration SHA до того, как засчитать отказ `gate`. Обе записи
|
|
552
|
+
остаются; у повтора `recheck: {of, outcome}` — ссылка на первую запись и
|
|
553
|
+
исход: `flaky` (повтор прошёл, первый провал вызван средой, например бюджетом
|
|
554
|
+
времени под нагрузкой) или `confirmed` (отказ засчитывается как прежде). Лог
|
|
555
|
+
повтора — в `integration/recheck/`; замер — стадия `integration-recheck:<gate>`.
|
|
556
|
+
Провал, в отчёте которого названо проваленное свойство или случай корпуса,
|
|
557
|
+
не повторяется: это найденный контрпример, и удачный второй запуск
|
|
558
|
+
недетерминированной проверки его не отменяет.
|
|
481
559
|
- **Атомарная приёмка.** Продвижение target ref — compare-and-swap внутри
|
|
482
560
|
транзакции приёмки. Чужой коммит в target ref не теряется: попытка начнётся
|
|
483
561
|
от новой базы. Падение между update-ref и записью принятия восстанавливается
|
|
@@ -487,6 +565,44 @@ executable. Live smoke — отдельный opt-in с явно заданны
|
|
|
487
565
|
- **Изоляция.** Режим `os` реально ограничивает процессы writer, reviewer и
|
|
488
566
|
gates; без механизма песочницы команда не запускается — тихого перехода к
|
|
489
567
|
запуску без неё нет. Зависшие процессы останавливаются вместе с потомками.
|
|
568
|
+
Обязательные запреты записи sandbox-runtime (конфигурация shell и git,
|
|
569
|
+
`.git/hooks`, `.mcp.json`, `.claude/commands|agents`, каталоги IDE)
|
|
570
|
+
действуют на весь checkout проверки, а не только на её рабочий каталог.
|
|
571
|
+
Исключение одно: каталоги IDE (`.idea`, `.vscode`) внутри `node_modules`
|
|
572
|
+
открыты — пакеты их публикуют, а IDE дерево зависимостей как конфигурацию
|
|
573
|
+
проекта не открывает. На Linux srt пропускает `node_modules` сам; на macOS
|
|
574
|
+
srt запускается из каталога проверки, а запреты задаются явно: каталоги IDE
|
|
575
|
+
закрыты в корне и в каждом подкаталоге существующих каталогов до глубины 3
|
|
576
|
+
(кроме `node_modules`), прочие имена — на любой глубине. Новый каталог
|
|
577
|
+
глубже существующего уровня этим не закрыт — граница подхода (srt на Linux
|
|
578
|
+
закрывает только уже существующие пути). Файл `.git` рабочего дерева,
|
|
579
|
+
перенаправления обычного `.git` (`commondir`, `gitdir`, `config.worktree`) и
|
|
580
|
+
вложенные `.git` на любой глубине тоже закрыты (на Linux — только
|
|
581
|
+
существующий файл `.git`). Дерево больше предела перечисления — отказ
|
|
582
|
+
проверки классом `environment`, а не молча урезанные запреты.
|
|
583
|
+
- **Сверка защищённых путей.** Запреты песочницы проверяют только путь
|
|
584
|
+
операции: каталог, собранный в `node_modules` и перенесённый в дерево
|
|
585
|
+
проекта, ими не закрыт. До и после каждого gate и вокруг работы исполнителя
|
|
586
|
+
сравнивается снимок защищённых имён вне `node_modules` (каталоги IDE,
|
|
587
|
+
конфигурация shell и git, `.claude`, `.git`); новое или изменённое — класс
|
|
588
|
+
`scope-violation` с путями в сообщении.
|
|
589
|
+
- **Классификация отказов песочницы.** Отказ — класс `environment` только
|
|
590
|
+
тогда, когда журнал ядра macOS подтвердил отказ обязательного запрета внутри
|
|
591
|
+
дерева проверки: команда начинается с уникального токена, и записи srt этой
|
|
592
|
+
проверки отличаются от чужих. Текст вывода свидетельством не служит, запись
|
|
593
|
+
вне дерева — ошибка кода (`gate`). На Linux такого свидетельства нет, и
|
|
594
|
+
отказ остаётся `gate`.
|
|
595
|
+
- **Git хоста над деревом проверки.** Каждый вызов git хоста сначала сверяет,
|
|
596
|
+
куда git придёт: файл `.git` дерева, созданного `worktree add`, не изменён;
|
|
597
|
+
gitdir и общий каталог лежат вне дерева и согласованы; `commondir`/`gitdir`
|
|
598
|
+
в обычном `.git` и вложенный репозиторий внутри известного дерева — отказ
|
|
599
|
+
(`scope-violation` в gate). Поверх — `-c core.fsmonitor=false -c
|
|
600
|
+
core.hooksPath=/dev/null -c protocol.ext.allow=never`: hooks репозитория при
|
|
601
|
+
коммитах harness не исполняются.
|
|
602
|
+
- **Чего ещё нет.** Регрессионных тестов в песочнице для запретов `.git`, для
|
|
603
|
+
сверки после переноса каталога и для отказа по пределу перечисления пока
|
|
604
|
+
нет: эти пути покрыты только тестами SBX01–SBX05 и модульными тестами
|
|
605
|
+
`git-trust`.
|
|
490
606
|
- **Секреты.** Значения секретов маскируются во всём сохраняемом: логах,
|
|
491
607
|
артефактах ревью, evidence, событиях и результате.
|
|
492
608
|
- **Бюджеты.** Проверяются до вызова модели в той же транзакции, что и запись
|
package/docs/contracts.md
CHANGED
|
@@ -615,6 +615,9 @@ manifestDigest, impact?, evidence[], error?}`. Смена любого SHA де
|
|
|
615
615
|
`moveBase`/`fencedRefMove`, `runGate`/`runCheck` (и разбор отчёта
|
|
616
616
|
`junitSummary`, `prepareReportPath`, `sandboxBlockedHosts`), `unprovenReason`,
|
|
617
617
|
`ReviewProbes`, маскирование (`redactor`, `redactDeep`, `redactError`),
|
|
618
|
+
git хоста над checkout с чужим кодом (`hostGitArgs`, `assertTrustedCheckout`,
|
|
619
|
+
`UntrustedCheckoutError`, `gitHardening`, учёт деревьев `rememberWorktree`/
|
|
620
|
+
`forgetWorktree`/`worktreeKey`/`worktreeAddPath`, `resetGitTrust` для тестов),
|
|
618
621
|
корпус (`CorpusStore`, подтверждение случая `submitCase` с `ConfirmContext`),
|
|
619
622
|
ограниченный разбор по свойству (`analyzeRecovery`, `applyCases`,
|
|
620
623
|
`recoveryBrief`; назначение хоста — модель и профиль ведущего — передаётся
|
package/docs/quickstart.md
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# devcontour-harness 0.1.0-alpha.17
|
|
2
|
+
|
|
3
|
+
Меньше слепых повторов и ручных сбросов. Включает всё из
|
|
4
|
+
[0.1.0-alpha.16](0.1.0-alpha.16.md). Gates, правила находок, изоляция,
|
|
5
|
+
принятие target ref и `maxAttempts` не менялись; формат состояния получил
|
|
6
|
+
необязательные поля (ниже, «Совместимость»).
|
|
7
|
+
|
|
8
|
+
## Что нового
|
|
9
|
+
|
|
10
|
+
- **Класс входов в находке ревью.** Блокирующая находка со входом называет
|
|
11
|
+
нарушенное свойство или критерий (`reproduction.property`) и класс входов
|
|
12
|
+
(`reproduction.inputClass`) — генератор или семейство, а не экземпляр. Поле
|
|
13
|
+
обязательно в схеме ответа runtime; ответ прежней формы без него
|
|
14
|
+
разбирается. Класс пишется в реестр воспроизведений и на отклонённую
|
|
15
|
+
попытку (`inputClasses`, пары `classified`); следующий writer получает
|
|
16
|
+
задачу чинить класс.
|
|
17
|
+
- **Пробел приёмки.** `repairDecision` останавливает поручение с полем `gap`
|
|
18
|
+
и причиной для ведущего, когда два отказа ревью подряд называют одно и то
|
|
19
|
+
же необъявленное свойство с тем же классом входов (класс без регистра и
|
|
20
|
+
лишних пробелов). Совпадение только свойства или только класса требует
|
|
21
|
+
трёх отказов подряд: общий класс бывает у разных дефектов. Отказ
|
|
22
|
+
окружения серию не меняет; отказ gate, другое название и новое основание
|
|
23
|
+
поручения её обрывают. `explain` показывает то же. Объявленные свойства
|
|
24
|
+
по-прежнему ведёт эпизод разбора.
|
|
25
|
+
- **Отказы окружения не тратят попытки.** Отказ окружения или провайдера и
|
|
26
|
+
истёкшее владение не засчитываются в `maxAttempts`, и после кандидата.
|
|
27
|
+
Предел у них свой: `MAX_NEUTRAL_FAILURES` = 3 на поручение (счётчик
|
|
28
|
+
`neutralFailures`); на нём `retry` без сброса, выдача и восстановление
|
|
29
|
+
отказывают, сброс человека обнуляет счётчик.
|
|
30
|
+
- **Штатная остановка не роняет работу.** `Runner.stop` помечает свои
|
|
31
|
+
попытки: прерванная сохраняет черновик, получает `interrupted: shutdown`,
|
|
32
|
+
а поручение возвращается в очередь (`ready`) без траты попытки и без паузы
|
|
33
|
+
по классу отказа; после снятия паузы остановки следующая попытка
|
|
34
|
+
продолжает с кандидата или черновика. Интегрированная попытка так не
|
|
35
|
+
возвращается: это обычный отказ, хост получает `hooks.failed`.
|
|
36
|
+
- **Класс отказа `unfinished`.** `completed: false` исполнителя был
|
|
37
|
+
`unknown` и останавливал работу без повтора, с сохранённым черновиком.
|
|
38
|
+
Теперь это `unfinished`: повтор (предел одинаковых — 2) продолжает с
|
|
39
|
+
черновика (`continuedFrom.kind: unfinished`) в пределах `maxAttempts` и
|
|
40
|
+
`repairBudget`; для эпизода свойства отказ нейтрален.
|
|
41
|
+
- **Пустой результат только с механическим основанием.** Пустая реализация
|
|
42
|
+
больше не отклоняется сразу: кандидат — сама база, gates задачи идут на
|
|
43
|
+
ней, оба ревью отвечают схемой с обязательным `alreadySatisfied` (gates
|
|
44
|
+
области задачи — хотя бы один test gate и все gates договоров проверки
|
|
45
|
+
поручения — и основание). Принятие требует ещё механического основания,
|
|
46
|
+
которое находит controller: договор проверки поручения со всеми gates в
|
|
47
|
+
области задачи, или зависимость, чей принятый результат входит в
|
|
48
|
+
проверяемый SHA и чей кандидат менял файлы области записи поручения.
|
|
49
|
+
Основание пишется в evidence ревью (`alreadySatisfied.basis`). Без него —
|
|
50
|
+
новый класс отказа `needs-lead`: остановка без повтора, решение ведущего.
|
|
51
|
+
`engine.finish` повторяет правило целиком по записанным данным.
|
|
52
|
+
- **`runGatesAt`.** Именованные gates компонента (с предпосылками) на
|
|
53
|
+
закреплённом SHA вне попытки — тем же путём, что интеграция задачи: свой
|
|
54
|
+
worktree, снимки зависимостей, ресурсы, lifecycle и prepare, окружение
|
|
55
|
+
интеграции, песочница проверок; каждый evidence — через callback хоста,
|
|
56
|
+
первый провал останавливает прогон, дерево должно остаться прежним.
|
|
57
|
+
- **Учёт стоимости по всему потоку.** Адаптер CLI разбирает stdout по
|
|
58
|
+
строкам по мере поступления и хранит только поля телеметрии (последний
|
|
59
|
+
`result` claude, `turn.completed` codex, первая названная модель): цена
|
|
60
|
+
длинного вызова больше не теряется за пределом хвоста вывода. Разбор
|
|
61
|
+
ограничен по памяти и не бросает исключений из обработчика вывода.
|
|
62
|
+
- **Отчёт свойств в пробах ревьюера.** Проба gate получает путь отчёта
|
|
63
|
+
свойств в scratch controller (`HARNESS_PROPERTY_REPORT`,
|
|
64
|
+
`DEVCONTOUR_PROPERTY_REPORT` — та же переменная, что у движка) и сохраняет
|
|
65
|
+
копию отчёта как evidence пробы; отчёт-ссылка отклоняется.
|
|
66
|
+
|
|
67
|
+
## Совместимость
|
|
68
|
+
|
|
69
|
+
Новые необязательные поля попытки (`interrupted`, `inputClasses`,
|
|
70
|
+
`classified`), поручения (`neutralFailures`), записи воспроизведения
|
|
71
|
+
(`inputClass`), evidence ревью (`alreadySatisfied`) и классы отказа
|
|
72
|
+
`unfinished` и `needs-lead`; в схемах данных CLI это единственные
|
|
73
|
+
аддитивные изменения перечней. Прежние записи не меняются.
|
|
74
|
+
Строгие схемы прежних версий новых значений не знают: после первой записи
|
|
75
|
+
alpha.17 откат — только через копию. Изменение поведения: тесты хоста,
|
|
76
|
+
ждавшие засчитанную попытку после отказа окружения или `failed` после
|
|
77
|
+
штатной остановки, нужно обновить. Матрица — [upgrade](../upgrade.md).
|
|
78
|
+
|
|
79
|
+
## Проверка выпуска
|
|
80
|
+
|
|
81
|
+
`npm run check` на macOS arm64, Node.js 24.3. Новые тесты на fixture runtime
|
|
82
|
+
и реальных Git-фикстурах (`repair`, `reproductions`, `runner` T14,
|
|
83
|
+
`explain-engine`, `network-recovery`, `reuse`, `usage`, `probe-gates`,
|
|
84
|
+
`already-satisfied`, `gates-at`); каждый новый тест обнаруживает свой мутант
|
|
85
|
+
реализации. Закрепление схем данных CLI (H3-01) сверяет байты H2 без
|
|
86
|
+
аддитивных значений `unfinished` и `needs-lead`. Живые модели не вызывались.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# devcontour-harness 0.1.0-alpha.18
|
|
2
|
+
|
|
3
|
+
Проверка gates на закреплённом SHA исполняет их с теми предпосылками, на
|
|
4
|
+
которые опирается профиль. Включает всё из [0.1.0-alpha.17](0.1.0-alpha.17.md).
|
|
5
|
+
Формат состояния, gates попыток, правила находок, изоляция, принятие target
|
|
6
|
+
ref и `maxAttempts` не менялись.
|
|
7
|
+
|
|
8
|
+
## Что нового
|
|
9
|
+
|
|
10
|
+
- **Предпосылки проверки вне задачи.** `runGatesAt` брал только явные
|
|
11
|
+
`dependsOn`. В профиле, который опирается на порядок массива (установка
|
|
12
|
+
первой, без `dependsOn`), проверка одного test gate шла без установки и
|
|
13
|
+
падала на отсутствующих модулях, хотя задачи проходили: их область называла
|
|
14
|
+
установку явно. Теперь область проверки — названные gates и предпосылки
|
|
15
|
+
каждого (`standaloneScope`), порядок — тот же `orderedScope`, что у попытки
|
|
16
|
+
(прежний внутренний `ordered` runner, без изменения поведения).
|
|
17
|
+
Предпосылки (`gatePrerequisites`): у gate с объявленным `dependsOn` —
|
|
18
|
+
замыкание по `dependsOn`; у gate без поля `dependsOn` — все более ранние
|
|
19
|
+
gates вида `check` со своими предпосылками. Более ранние test gates не
|
|
20
|
+
добавляются. Каждый gate посещается один раз, поэтому `dependsOn` на более
|
|
21
|
+
поздний gate вместе с неявным ребром не зацикливается. Область задачи
|
|
22
|
+
по-прежнему исполняется как записана.
|
|
23
|
+
- **Явный `dependsOn: []` — без предпосылок.** Объявленный пустой
|
|
24
|
+
`dependsOn` — режим графа: неявных предпосылок нет. Порядок массива
|
|
25
|
+
действует только для gate без поля.
|
|
26
|
+
- **Все провалы сразу.** Провал gate больше не останавливает проверку:
|
|
27
|
+
исполняются все названные gates, результат перечисляет каждый непрошедший
|
|
28
|
+
(`failures`; `failure` — первый, как раньше). Пропускается только gate,
|
|
29
|
+
чья явная предпосылка (`dependsOn`, `explicitPrerequisites`) не прошла, — он
|
|
30
|
+
назван с этой причиной. Провал неявной предпосылки (раннего check gate) не
|
|
31
|
+
скрывает исход тестов: исполняются и названы оба. Evidence по-прежнему
|
|
32
|
+
пишется через запись хоста и привязано к SHA.
|
|
33
|
+
|
|
34
|
+
## Совместимость
|
|
35
|
+
|
|
36
|
+
Формат состояния не меняется. `GatesAtResult` получает поле `failures`;
|
|
37
|
+
хост, ждавший остановки на первом провале, получает теперь все исполненные
|
|
38
|
+
gates. Новые экспорты: `orderedScope`, `gatePrerequisites`,
|
|
39
|
+
`explicitPrerequisites`, `standaloneScope`. Матрица — [upgrade](../upgrade.md).
|
|
40
|
+
|
|
41
|
+
## Проверка выпуска
|
|
42
|
+
|
|
43
|
+
Затронутые тесты на реальных Git-фикстурах (`gates-at`: профиль в порядке
|
|
44
|
+
массива с установкой первой и без `dependsOn`, петля через неявное ребро,
|
|
45
|
+
пустой `dependsOn`, цепочки двух и трёх уровней, смешанная цепочка, провал
|
|
46
|
+
неявной предпосылки; `runner` T01, T09); каждый новый тест обнаруживает свой
|
|
47
|
+
мутант реализации. Полный `npm run check` перед публикацией выполняет
|
|
48
|
+
ведущий. Живые модели не вызывались.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# devcontour-harness 0.1.0-alpha.19
|
|
2
|
+
|
|
3
|
+
Меньше трения в цикле исполнения и жёстче граница песочницы: провал
|
|
4
|
+
интеграции, вызванный средой, повторяется один раз, установка зависимостей
|
|
5
|
+
не падает на каталогах IDE внутри `node_modules`, а git хоста не исполняет
|
|
6
|
+
конфигурацию, которую записал чужой код. Включает всё из
|
|
7
|
+
[0.1.0-alpha.18](0.1.0-alpha.18.md). `maxAttempts`, правила находок и
|
|
8
|
+
принятие target ref не менялись.
|
|
9
|
+
|
|
10
|
+
## Что нового
|
|
11
|
+
|
|
12
|
+
### Цикл исполнения
|
|
13
|
+
|
|
14
|
+
- **Ограниченный повтор провала интеграции.** Собственный gate поручения,
|
|
15
|
+
прошедший на кандидате и упавший на integration, повторяется один раз на
|
|
16
|
+
кандидата на том же integration SHA, прежде чем засчитать отказ `gate`.
|
|
17
|
+
Обе записи остаются; у повтора `recheck: {of, outcome}` — ссылка на первую
|
|
18
|
+
запись и исход `flaky` (повтор прошёл) или `confirmed` (провал
|
|
19
|
+
засчитывается как прежде). Лог повтора — в `integration/recheck/`, замер —
|
|
20
|
+
стадия `integration-recheck:<gate>`. Удачный повтор принимает кандидата без
|
|
21
|
+
новой реализации. Кандидат, переиспользованный следующей попыткой, второго
|
|
22
|
+
повтора не получает; движок отклоняет второй повтор в попытке и исход,
|
|
23
|
+
не согласованный с записью.
|
|
24
|
+
- **Контрпример не повторяется.** Провал, в отчёте которого названо
|
|
25
|
+
проваленное свойство или случай корпуса, не повторяется: удачный второй
|
|
26
|
+
запуск недетерминированной проверки не отменяет найденного входа.
|
|
27
|
+
- **Шире области gates.** Область gates задачи, поручения, потребителя и
|
|
28
|
+
основания ревью вмещает до `GATE_SCOPE_LIMIT` (100, предел gates профиля)
|
|
29
|
+
вместо 20; превышение — понятный отказ с величиной и исправлением.
|
|
30
|
+
Константа экспортируется.
|
|
31
|
+
- **Дешевле такты.** `expire()` без истёкших попыток не открывает транзакцию
|
|
32
|
+
записи; такт очереди читает активные попытки через необязательный быстрый
|
|
33
|
+
путь `ExecutionView.activeAttempts`. Завершённое задание workflow сообщает
|
|
34
|
+
израсходованные попытки стадий, а не сброшенный счётчик.
|
|
35
|
+
|
|
36
|
+
### Песочница
|
|
37
|
+
|
|
38
|
+
- **Каталоги IDE внутри `node_modules` открыты.** Пакеты публикуют `.idea/`,
|
|
39
|
+
и установка в чистом дереве падала с EPERM при любом коде. На macOS srt
|
|
40
|
+
запускается из служебного каталога проверки, а обязательные запреты
|
|
41
|
+
задаются явно на весь checkout: конфигурация shell, git, MCP и Claude,
|
|
42
|
+
`.git/hooks`, `.git/config` — на любой глубине; `.idea`/`.vscode` — в
|
|
43
|
+
корне и в каждом существующем подкаталоге до глубины 3, кроме
|
|
44
|
+
`node_modules`. Linux не меняется (srt пропускает `node_modules` сам).
|
|
45
|
+
- **Явные запреты `.git`.** На macOS закрыты файл `.git` рабочего дерева,
|
|
46
|
+
перенаправления обычного `.git` (`commondir`, `gitdir`, `config.worktree`)
|
|
47
|
+
и вложенные `.git` на любой глубине; на Linux — существующий файл `.git`.
|
|
48
|
+
Дерево больше предела перечисления — отказ класса `environment`, а не
|
|
49
|
+
молча урезанные запреты.
|
|
50
|
+
- **Git хоста над деревом проверки (`git-trust`).** Каждый вызов git хоста
|
|
51
|
+
сначала сверяет, куда git придёт: файл `.git` дерева, созданного
|
|
52
|
+
`worktree add`, не изменён; gitdir и общий каталог лежат вне дерева и
|
|
53
|
+
согласованы. Перенаправленный `gitdir`/`commondir` в обычном `.git` и
|
|
54
|
+
вложенный репозиторий внутри известного дерева — отказ
|
|
55
|
+
(`UntrustedCheckoutError`, в gate — `scope-violation`). Поверх —
|
|
56
|
+
`-c core.fsmonitor=false -c core.hooksPath=/dev/null -c protocol.ext.allow=never`:
|
|
57
|
+
hooks репозитория при коммитах harness не исполняются. Экспорт для хоста:
|
|
58
|
+
`hostGitArgs`, `assertTrustedCheckout`, `UntrustedCheckoutError`,
|
|
59
|
+
`gitHardening`, `rememberWorktree`, `forgetWorktree`, `worktreeKey`,
|
|
60
|
+
`worktreeAddPath`, `resetGitTrust` (для тестов).
|
|
61
|
+
- **Сверка защищённых путей после gate.** Запреты песочницы видят только
|
|
62
|
+
путь операции, и каталог, собранный в `node_modules` и перенесённый в
|
|
63
|
+
дерево проекта, ими не закрыт. Вокруг каждого gate и работы исполнителя
|
|
64
|
+
сравнивается снимок защищённых имён вне `node_modules`; новое или
|
|
65
|
+
изменённое — `scope-violation` с путями в сообщении.
|
|
66
|
+
- **Класс `environment` — только по журналу ядра.** Отказ песочницы
|
|
67
|
+
классифицируется как сбой среды, только когда журнал ядра macOS подтвердил
|
|
68
|
+
отказ обязательного запрета внутри дерева проверки (команда проверки
|
|
69
|
+
помечена уникальным токеном). Текст вывода (EPERM) свидетельством не
|
|
70
|
+
служит; запись вне дерева и любой отказ на Linux остаются `gate`.
|
|
71
|
+
|
|
72
|
+
## Известные пробелы
|
|
73
|
+
|
|
74
|
+
- Регрессионные тесты в настоящей песочнице для запретов `.git`, для сверки
|
|
75
|
+
защищённых путей после переноса каталога и для отказа по пределу
|
|
76
|
+
перечисления не написаны (решение владельца проекта). Эти пути покрыты
|
|
77
|
+
тестами SBX01–SBX05 и модульными тестами `git-trust`.
|
|
78
|
+
- Запреты на Linux и запуск/остановка наблюдения за журналом ядра тестами не
|
|
79
|
+
покрыты.
|
|
80
|
+
- Поэтому два мутанта этих путей (D1, D2) выживают.
|
|
81
|
+
|
|
82
|
+
## Совместимость
|
|
83
|
+
|
|
84
|
+
Формат состояния: новое необязательное поле `recheck` у evidence gate и в
|
|
85
|
+
событии `attempt.gate`, области gates длиннее 20. Прежние версии
|
|
86
|
+
отклоняют такое состояние строгой схемой → откат через копию. Хост, у
|
|
87
|
+
которого хуки gate или writer меняют защищённые имена, получит
|
|
88
|
+
`scope-violation`. Матрица — [upgrade](../upgrade.md).
|
|
89
|
+
|
|
90
|
+
## Проверка выпуска
|
|
91
|
+
|
|
92
|
+
Затронутые тесты (`runner`, `engine`, `repair`, `planning-schema`,
|
|
93
|
+
`cli-h3-contract`, `probe-gates`, `review-inspection-runner`, `git-trust`,
|
|
94
|
+
`sandbox-install`, `boundaries`), lint, typecheck и `schemas:check`. Полный
|
|
95
|
+
`npm run check` перед публикацией выполняет ведущий. Живые модели не
|
|
96
|
+
вызывались.
|
package/docs/review-probes.md
CHANGED
|
@@ -29,13 +29,19 @@ To run a declared gate, call run_check with exactly {"gate":"domain"}, {"gate":"
|
|
|
29
29
|
3. Если путь отчёта зашит в argv (см. ниже) — не запускает, возвращает ошибку среды с рецептом.
|
|
30
30
|
4. Создаёт каталог evidence `<каталог ревью>/probe-runs/<runId>/` (вне дерева, без перезаписи) и
|
|
31
31
|
уникальный scratch `dc-probe-report-*` во временном каталоге системы.
|
|
32
|
-
5. Выставляет `HARNESS_REPORT_PATH` и `DEVCONTOUR_REPORT_PATH` = `<scratch>/<id>.xml`,
|
|
33
|
-
|
|
32
|
+
5. Выставляет `HARNESS_REPORT_PATH` и `DEVCONTOUR_REPORT_PATH` = `<scratch>/<id>.xml`,
|
|
33
|
+
`DEVCONTOUR_PROPERTY_REPORT` = `<scratch>/<id>.property.json` (то же имя, что у gate движка),
|
|
34
|
+
`CI=1`; у `test` gate ещё `TURBO_FORCE=true` и `GOFLAGS=… -count=1`, как у gate движка.
|
|
35
|
+
Проверка, которая пишет отчёт свойств по пути из переменной, под probe пишет его в scratch, а
|
|
36
|
+
не получает EPERM в дереве только для чтения. `DEVCONTOUR_SEED`, `DEVCONTOUR_PROPERTIES` и
|
|
37
|
+
`DEVCONTOUR_CORPUS` probe не выставляет: генеративные gate он не исполняет.
|
|
34
38
|
6. Запускает команду в песочнице: запись — только в scratch и `TMPDIR`; дерево, `.git`,
|
|
35
39
|
каталог controller и прежние `.reports/*.xml` закрыты на запись.
|
|
36
40
|
7. Читает отчёт: symlink, жёсткая ссылка, путь вне scratch — `unsafe` (не читается); файл старше
|
|
37
41
|
запуска — `stale`; не JUnit или без testcases — `corrupt`; нет файла — `missing`.
|
|
38
|
-
8. Сохраняет замаскированную копию отчёта (`<id>.xml`),
|
|
42
|
+
8. Сохраняет замаскированную копию отчёта (`<id>.xml`), отчёта свойств, если он записан
|
|
43
|
+
(`<id>.property.json`, `gate.propertyReport` = `{path, scope: "probe-only"}`: движок его не
|
|
44
|
+
читает), журнал (`<id>.log`) и `run.json`, затем
|
|
39
45
|
удаляет scratch. Таймаут и отмена (`notifications/cancelled`) останавливают процессы проверки,
|
|
40
46
|
evidence сохраняется тоже.
|
|
41
47
|
|
package/docs/review-protocol.md
CHANGED
|
@@ -121,6 +121,15 @@ DevContour хранит `Evidence` как есть; все новые поля
|
|
|
121
121
|
логического ревью). Непринятый результат содержит и записи невалидных
|
|
122
122
|
вызовов (`review.protocol: invalid` с их причинами).
|
|
123
123
|
|
|
124
|
+
- `alreadySatisfied` — у записи ревью попытки без изменений (кандидат —
|
|
125
|
+
база): gates и основание, которыми reviewer подтвердил, что приёмка уже
|
|
126
|
+
выполнена. Поле ответа reviewer `alreadySatisfied` (`null` — нет
|
|
127
|
+
подтверждения) входит в схему только для такой попытки; обычное ревью
|
|
128
|
+
отвечает прежней схемой. Одобрение без годного подтверждения записывается
|
|
129
|
+
непрошедшим, отказ попытки — `empty-result`; без механического основания
|
|
130
|
+
(`basis`: договор проверки или зависимость, изменившая область записи) —
|
|
131
|
+
`needs-lead`.
|
|
132
|
+
|
|
124
133
|
## 6. Записи alpha.5 (legacy)
|
|
125
134
|
|
|
126
135
|
Запись ревью без `reviewRound` — запись прежней версии. Её находки (у
|