devcontour-harness 0.1.0-alpha.6 → 0.1.0-alpha.7
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 +20 -2
- package/docs/quickstart.md +1 -1
- package/docs/release-notes/0.1.0-alpha.7.md +71 -0
- package/docs/review-probes.md +79 -0
- package/docs/upgrade.md +42 -25
- package/lib/agents/cli-adapter.js +8 -1
- package/lib/agents/inspect.d.ts +56 -2
- package/lib/agents/inspect.js +264 -14
- package/lib/agents/review-probe.d.ts +50 -0
- package/lib/agents/review-probe.js +211 -46
- package/lib/contracts/execution.d.ts +213 -7
- package/lib/contracts/execution.js +67 -3
- package/lib/contracts/published.d.ts +49 -1
- package/lib/control/review.js +9 -5
- package/lib/engine/budget.d.ts +3 -3
- package/lib/engine/engine.d.ts +28 -2
- package/lib/engine/runner.js +20 -12
- package/lib/environment/process.d.ts +8 -0
- package/lib/environment/process.js +8 -2
- package/lib/storage/document.d.ts +56 -4
- package/lib/verification/gates.d.ts +22 -0
- package/lib/verification/gates.js +64 -23
- package/package.json +1 -1
- package/schemas/execution-document.schema.json +190 -4
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.7` — предварительный выпуск (alpha). Договоры
|
|
9
9
|
> `v1alpha1` могут измениться между alpha-версиями; закрепляйте точную версию.
|
|
10
10
|
> Файл → ревью плана → кандидат → интеграция → принятие → результат JSON, с
|
|
11
11
|
> ограниченным восстановлением, повторным использованием кандидата, бюджетами,
|
|
@@ -27,7 +27,7 @@ Headless-движок исполнения инженерных поручени
|
|
|
27
27
|
Из npm — точная версия (воспроизводимо) или последняя alpha по тегу:
|
|
28
28
|
|
|
29
29
|
```sh
|
|
30
|
-
npm install --save-exact devcontour-harness@0.1.0-alpha.
|
|
30
|
+
npm install --save-exact devcontour-harness@0.1.0-alpha.7 # точная версия
|
|
31
31
|
# или: npm install --save-exact devcontour-harness@alpha # текущая alpha
|
|
32
32
|
npx harness --version
|
|
33
33
|
```
|
|
@@ -117,6 +117,24 @@ PASS» нет. Адаптеры хоста реализуют порты `Execut
|
|
|
117
117
|
`devcontour-harness/schemas/<имя>.schema.json`. Декларации используют типы
|
|
118
118
|
Node.js: TypeScript-потребителю нужен `@types/node` (или `skipLibCheck`).
|
|
119
119
|
|
|
120
|
+
## Выпуск 0.1.0-alpha.7
|
|
121
|
+
|
|
122
|
+
Исправление учёта команд reviewer в `inspection` ревью кода. Подробно —
|
|
123
|
+
[заметки выпуска](docs/release-notes/0.1.0-alpha.7.md).
|
|
124
|
+
|
|
125
|
+
- `inspection` собирается controller из событий runtime и журнала проверок
|
|
126
|
+
`run_check` одного вызова reviewer: запуски probe теперь засчитываются, а
|
|
127
|
+
команда с ненулевым кодом — выполнение, а не `diff-only`
|
|
128
|
+
([review-probes](docs/review-probes.md#итог-inspection-что-reviewer-действительно-выполнил)).
|
|
129
|
+
- Старт probe подтверждается на границе исполнения; отказ до старта, отменённый
|
|
130
|
+
до запуска вызов и резерв бюджета выполнением не считаются. Уже отменённый
|
|
131
|
+
вызов больше не запускает команду.
|
|
132
|
+
- Gates, бюджеты, правила находок и принятия не менялись: `inspection` по-прежнему
|
|
133
|
+
не влияет на решение.
|
|
134
|
+
|
|
135
|
+
Записи alpha.6 читаются без пересчёта; состояние с новыми записями `inspection`
|
|
136
|
+
alpha.6 не читает — откат только через копию ([upgrade](docs/upgrade.md)).
|
|
137
|
+
|
|
120
138
|
## Выпуск 0.1.0-alpha.6
|
|
121
139
|
|
|
122
140
|
Ядро работает как прежде; всё новое подключается явно. Подробно —
|
package/docs/quickstart.md
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# devcontour-harness 0.1.0-alpha.7
|
|
2
|
+
|
|
3
|
+
Исправление учёта фактически выполненных команд reviewer в `inspection` ревью
|
|
4
|
+
кода. Gates, `maxAttempts`, бюджеты попыток и повторов, правила находок, защиты
|
|
5
|
+
worktree и принятие target ref не менялись: `inspection` по-прежнему описывает
|
|
6
|
+
evidence и не влияет на решение.
|
|
7
|
+
|
|
8
|
+
## Что исправлено
|
|
9
|
+
|
|
10
|
+
- **Проверки reviewer не учитывались.** На пилоте alpha.6 reviewer запускал
|
|
11
|
+
проверки через `run_check` (в том числе объявленные gates), а `inspection`
|
|
12
|
+
оставался `diff-only` с пустым списком команд: учитывались только shell-события
|
|
13
|
+
Codex. Теперь итог собирает controller из событий runtime и журнала
|
|
14
|
+
`probes.jsonl` одного вызова reviewer; самоотчёт модели по-прежнему ничего не
|
|
15
|
+
подтверждает.
|
|
16
|
+
- **Ненулевой код выхода превращал выполнение в `diff-only`.** Режим зависел от
|
|
17
|
+
наличия команды с кодом 0. Теперь `mode: commands` — любая подтверждённая
|
|
18
|
+
выполненная команда; провал теста — исход, а не отсутствие выполнения.
|
|
19
|
+
- **Уже отменённый вызов проверки запускал команду.** Слушатель отмены на уже
|
|
20
|
+
отменённом сигнале не срабатывал, и команда шла до таймаута. Теперь такой
|
|
21
|
+
вызов — `cancelled` без запуска.
|
|
22
|
+
- **Код и вывод терялись при сбое после исхода** (уборка временных каталогов,
|
|
23
|
+
сохранение evidence gate): исход сохраняется как `error`/`environment` с
|
|
24
|
+
кодом и выводом.
|
|
25
|
+
- **Короткий секрет портил разбор событий Codex** и служебные значения
|
|
26
|
+
записи: события разбираются из немаскированного потока только в памяти,
|
|
27
|
+
маскируются поля текста до обрезки; сохраняемые журналы маскированы, как и
|
|
28
|
+
раньше.
|
|
29
|
+
|
|
30
|
+
## Граница старта
|
|
31
|
+
|
|
32
|
+
Запуск probe засчитывается по признаку `started`, полученному на границе
|
|
33
|
+
исполнения `runCheck`: без песочницы — порождение процесса, в песочнице — метка,
|
|
34
|
+
которую обёртка создаёт перед `exec`. Отказ до старта, исчерпанный бюджет,
|
|
35
|
+
неизвестный gate, отменённый до запуска вызов, резерв `start` и `abandoned`
|
|
36
|
+
выполнением не считаются; они перечислены в `inspection.excluded`.
|
|
37
|
+
|
|
38
|
+
## Изменения договора
|
|
39
|
+
|
|
40
|
+
Только добавления и nullable — подробно в
|
|
41
|
+
[review-probes](../review-probes.md#итог-inspection-что-reviewer-действительно-выполнил):
|
|
42
|
+
|
|
43
|
+
- `inspection.source`: новые значения `controller-probes`,
|
|
44
|
+
`runtime-and-controller`;
|
|
45
|
+
- `inspection.commands[].exitCode` может быть `null`; новые необязательные
|
|
46
|
+
`origins`, `status`, `failure`, `gate`, `note`;
|
|
47
|
+
- новые необязательные `inspection.context`, `total`, `excluded`,
|
|
48
|
+
`excludedTotal`, `invalid`;
|
|
49
|
+
- строки исхода `probes.jsonl` и `review.json.probes`: `started`, `scope`,
|
|
50
|
+
`exitCode`, `note`;
|
|
51
|
+
- `runCheck` возвращает `started` и принимает `onStart`; `command()` —
|
|
52
|
+
`onSpawn`, `onRawStdout`.
|
|
53
|
+
|
|
54
|
+
Полный `inspection` в `run-result` не добавлен; публичные схемы, кроме
|
|
55
|
+
`execution-document`, не менялись.
|
|
56
|
+
|
|
57
|
+
## Совместимость
|
|
58
|
+
|
|
59
|
+
alpha.7 читает состояние alpha.6 без преобразования и без пересчёта прежних
|
|
60
|
+
`inspection`, digest и решений. Направление одностороннее: строгая схема alpha.6
|
|
61
|
+
не принимает новые значения `source`, `exitCode: null` и новые поля, поэтому
|
|
62
|
+
откат с alpha.7 — только восстановлением копии состояния, сделанной до
|
|
63
|
+
обновления ([upgrade](../upgrade.md)). Потребителю, разбирающему `inspection`,
|
|
64
|
+
нужно принять новые значения enum и nullable `exitCode`; признак выполнения —
|
|
65
|
+
`mode`.
|
|
66
|
+
|
|
67
|
+
## Проверка выпуска
|
|
68
|
+
|
|
69
|
+
`npm run check` (lint, typecheck, schemas, build, весь набор тестов, package
|
|
70
|
+
smoke) на macOS arm64, Node.js 24.3.0. Матрица приёмки IN01–IN20; независимая
|
|
71
|
+
приёмка другой моделью воспроизвела IN01–IN19 собственными прогонами.
|
package/docs/review-probes.md
CHANGED
|
@@ -85,6 +85,85 @@ To run a declared gate, call run_check with exactly {"gate":"domain"}, {"gate":"
|
|
|
85
85
|
оценивает движок; probe не записывает evidence gate, не ставит технический PASS и не двигает
|
|
86
86
|
target ref.
|
|
87
87
|
|
|
88
|
+
## Итог `inspection`: что reviewer действительно выполнил
|
|
89
|
+
|
|
90
|
+
`review.json.inspection` и `EvidenceRecord.inspection` ревью кода — один и тот же объект. Его
|
|
91
|
+
собирает controller для **одного вызова reviewer** из двух наблюдений: событий runtime этого
|
|
92
|
+
вызова (Codex `item.completed`/`command_execution`) и журнала проверок `probes.jsonl` этого
|
|
93
|
+
вызова. Самоотчёт модели (`execution.commands`, `reproduction.executed`, runId в тексте) ничего
|
|
94
|
+
не подтверждает.
|
|
95
|
+
|
|
96
|
+
- `mode: commands` — подтверждена хотя бы одна выполненная команда; `reason: null`. Ненулевой
|
|
97
|
+
код, таймаут или отмена после старта и ошибка среды после старта выполнение не отменяют.
|
|
98
|
+
- `mode: diff-only` — подтверждённых выполнений нет; `commands: []`, `reason` объясняет.
|
|
99
|
+
- `commands` — не PASS: тесты могли упасть, gates и вердикт оценивает движок. Принятие по-прежнему
|
|
100
|
+
зависит только от обязательных gates и валидного вердикта; `commands` не лечит невалидный ответ,
|
|
101
|
+
изменённое дерево или проваленный gate, а неуспешный probe сам не создаёт находку.
|
|
102
|
+
|
|
103
|
+
### Граница старта
|
|
104
|
+
|
|
105
|
+
Запуск probe засчитывается по признаку `started` из `runCheck`: без песочницы — процесс порождён
|
|
106
|
+
(событие `spawn`), в песочнице — обёртка создала метку старта перед `exec` (запуск самой обёртки
|
|
107
|
+
не считается). Признак отмечается на границе и переживает исключение после неё.
|
|
108
|
+
|
|
109
|
+
| Событие | В `commands` |
|
|
110
|
+
| ----------------------------------------------------------------------------------------- | ------------ |
|
|
111
|
+
| Команда завершилась с любым кодом | да |
|
|
112
|
+
| `timeout`/`cancelled` после старта (код `null`, частичный вывод) | да |
|
|
113
|
+
| `error`/`environment` после старта (сеть закрыта песочницей, EPERM, сбой записи evidence) | да |
|
|
114
|
+
| `failed`/`report`: код 0, JUnit отсутствует или испорчен | да |
|
|
115
|
+
| Неизвестный gate, бюджет исчерпан, нет executable, отказ песочницы или scratch до старта | нет |
|
|
116
|
+
| Вызов отменён до запуска (`cancelled`, команда не исполнялась) | нет |
|
|
117
|
+
| Только резерв `start`, `abandoned`, битая строка, объект без формы исхода | нет |
|
|
118
|
+
|
|
119
|
+
Незасчитанные записи перечислены в `inspection.excluded` с причиной; полная диагностика — в
|
|
120
|
+
`review.json.probes` и журнале.
|
|
121
|
+
|
|
122
|
+
### Форма
|
|
123
|
+
|
|
124
|
+
| Смысл | JSON path | Тип и значения |
|
|
125
|
+
| ------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
126
|
+
| Источник итога | `source` | `codex-events`, `unavailable` (прежние), `controller-probes`, `runtime-and-controller` |
|
|
127
|
+
| Вызов reviewer | `context` | `{attempt, phase: candidate\|integration, sha, call}`; `attempt` — ID попытки, не runId probe |
|
|
128
|
+
| Все подтверждённые операции | `total` | целое ≥ 0 |
|
|
129
|
+
| Происхождение команды | `commands[].origins[]` | `{type: "runtime", runtime, item: string\|null}` или `{type: "controller", runId}` |
|
|
130
|
+
| Код выхода | `commands[].exitCode` | целое или `null` (неизвестен: таймаут, отмена, старая проекция без кода) |
|
|
131
|
+
| Исход | `commands[].status` | `completed`/`failed` (runtime); `passed`/`failed`/`timeout`/`cancelled`/`error` (probe) |
|
|
132
|
+
| Неуспех не в коде | `commands[].failure` | `environment`, `report` |
|
|
133
|
+
| Gate | `commands[].gate` | ID объявленного gate |
|
|
134
|
+
| Пояснение controller | `commands[].note` | строка ≤ 2000 |
|
|
135
|
+
| Не засчитано | `excluded[]` | `{runId, status, reason}`, `reason`: `not-started`, `legacy-unconfirmed`, `foreign-scope`, `unknown-status`, `unfinished`, `abandoned`; не более 100, полное число — `excludedTotal` |
|
|
136
|
+
| Строки журнала без формы исхода | `invalid` | целое ≥ 0 |
|
|
137
|
+
|
|
138
|
+
Пределы: не более 100 команд; `command` ≤ 12000 символов; `output` ≤ 4000 (stdout и stderr через
|
|
139
|
+
перевод строки, при нехватке места — хвосты обоих примерно поровну); `note` ≤ 2000. Потоки probe
|
|
140
|
+
в журнале по-прежнему ограничены хвостом 8000 с маркером `…`. Порядок: команды runtime в порядке
|
|
141
|
+
потока, затем запуски probe в порядке журнала; при превышении сохраняются последние 100, а
|
|
142
|
+
`mode` вычисляется по всему набору. Пользовательский текст маскируется до обрезки; перечисления и
|
|
143
|
+
идентификаторы controller не маскируются.
|
|
144
|
+
|
|
145
|
+
### Идентичность и область
|
|
146
|
+
|
|
147
|
+
Операция одна только при надёжной идентичности: один runId probe; один item ID в потоке runtime;
|
|
148
|
+
явная структурированная связь наблюдения runtime с runId probe (origin `controller` у команды
|
|
149
|
+
runtime) — тогда у операции оба происхождения. Одинаковый argv с разными runId — две операции;
|
|
150
|
+
совпадение текста, вывода или замаскированных аргументов не склеивает.
|
|
151
|
+
|
|
152
|
+
Каждый исход в журнале несёт `scope: {attempt, phase, sha, call}`. Запись с явно чужими
|
|
153
|
+
попыткой, фазой, SHA или вызовом (или gate с чужими `phase`/`sha`) не засчитывается
|
|
154
|
+
(`excluded`, `foreign-scope`). `call-2` не получает команд `call-1`, integration — команд
|
|
155
|
+
candidate; общий бюджет проверок логического ревью по-прежнему считается по журналам всех вызовов.
|
|
156
|
+
|
|
157
|
+
### Старые записи
|
|
158
|
+
|
|
159
|
+
Прежние `inspection` (без новых полей, в том числе противоречивые `diff-only` с командой) и
|
|
160
|
+
evidence без `inspection` читаются как есть; чтение не пересчитывает итог, digest и решение.
|
|
161
|
+
Для отдельной агрегации старых данных: завершённые события runtime засчитываются как раньше;
|
|
162
|
+
записи probe без `started` со статусом `passed`/`failed` — выполнение (код и вывод, если их нет,
|
|
163
|
+
остаются неизвестными: `exitCode: null`, пустой `output`); `error`/`timeout`/`cancelled` без
|
|
164
|
+
подтверждения старта не засчитываются (`legacy-unconfirmed`) — это ограничение старых данных.
|
|
165
|
+
Явный `started: false` главнее правила старых записей.
|
|
166
|
+
|
|
88
167
|
## Рецепт: путь отчёта из переменной controller
|
|
89
168
|
|
|
90
169
|
Gate пригоден для probe, если команда пишет JUnit в `HARNESS_REPORT_PATH` (или
|
package/docs/upgrade.md
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
## Версии
|
|
9
9
|
|
|
10
|
-
| Что
|
|
11
|
-
| --------------- | ---------------------------------------------------------------------------
|
|
12
|
-
| Пакет
|
|
13
|
-
| Публичный API
|
|
14
|
-
| Политика
|
|
15
|
-
| Состояние
|
|
16
|
-
| Отчёты и корпус | `version: 1` (отчёт свойств, договор проверки, корпус, receipt среды)
|
|
10
|
+
| Что | Правило |
|
|
11
|
+
| --------------- | --------------------------------------------------------------------------- || --------------------
|
|
12
|
+
| Пакет | `0.1.0-alpha.N`; выпущенная версия неизменяема (тот же номер — те же байты) |
|
|
13
|
+
| Публичный API | `devcontour-harness/v1alpha1` |
|
|
14
|
+
| Политика | `policyVersion: 1` |
|
|
15
|
+
| Состояние | `stateVersion: 1` |
|
|
16
|
+
| Отчёты и корпус | `version: 1` (отчёт свойств, договор проверки, корпус, receipt среды) |
|
|
17
17
|
|
|
18
18
|
Для `0.x`: patch — совместимые исправления; minor — отдельно описанные
|
|
19
19
|
изменения договора, включая несовместимые. Неизвестная версия входа, политики
|
|
@@ -21,19 +21,20 @@
|
|
|
21
21
|
|
|
22
22
|
## Матрица форматов
|
|
23
23
|
|
|
24
|
-
| Состояние, записанное… | Читает 0.1.0-alpha.1 | Читает 0.1.0-alpha.2 | Читает 0.1.0-alpha.6 | Пишет поверх | Примечание
|
|
25
|
-
| ------------------------------------------------------------------------------ | ------------------------ | ------------------------ | -------------------- | ------------ |
|
|
26
|
-
| standalone `stateVersion: 1` версией alpha.1 | да | да | да | да | одна база SQLite: документ, события, локальные записи
|
|
27
|
-
| хост, центральная база | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | данные не переносятся; новые поля необязательны
|
|
28
|
-
| хост, базы компонентов | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | нужна копия всех баз при остановленных writers
|
|
29
|
-
| alpha.2 после штатной остановки controller | да | да | да | да | роль controller снята — нового поля в состоянии нет
|
|
30
|
-
| alpha.2 с живой или брошенной ролью controller | **нет**, отказ до записи | да | да | — | роль хранит `engineVersion`; строгая схема alpha.1 его не знает → откат через копию
|
|
31
|
-
| alpha.4 с совместной проверкой | **нет**, отказ до записи | **нет**, отказ до записи | да | — | проверка хранит `engineVersion`; прежние версии его не знают → откат через копию
|
|
32
|
-
| alpha.6 standalone с записями ревью нового протокола или доставкой `uncertain` | **нет**, отказ до записи | **нет**, отказ до записи | да | — | `reviewRound`, `findings[].id/status`, статус доставки `uncertain`; alpha.4/alpha.5 отказывают `STATE_VERSION_UNSUPPORTED` до записи → откат через копию
|
|
33
|
-
| alpha.6, хост DevContour (адаптер alpha.4) | — | — | да (через адаптер) | да | адаптер DevContour alpha.4 открывает такое состояние без отказа и пишет роль controller и события; новые поля сохраняются → для отката всё равно копия
|
|
34
|
-
|
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
| Состояние, записанное… | Читает 0.1.0-alpha.1 | Читает 0.1.0-alpha.2 | Читает 0.1.0-alpha.6 | Читает 0.1.0-alpha.7 | Пишет поверх | Примечание |
|
|
25
|
+
| ------------------------------------------------------------------------------ | ------------------------ | ------------------------ | ----------------------- | -------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
26
|
+
| standalone `stateVersion: 1` версией alpha.1 | да | да | да | да | да | одна база SQLite: документ, события, локальные записи |
|
|
27
|
+
| хост, центральная база | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | данные не переносятся; новые поля необязательны |
|
|
28
|
+
| хост, базы компонентов | да (через адаптер) | да (через адаптер) | да (через адаптер) | да (через адаптер) | да | нужна копия всех баз при остановленных writers |
|
|
29
|
+
| alpha.2 после штатной остановки controller | да | да | да | да | да | роль controller снята — нового поля в состоянии нет |
|
|
30
|
+
| alpha.2 с живой или брошенной ролью controller | **нет**, отказ до записи | да | да | да | — | роль хранит `engineVersion`; строгая схема alpha.1 его не знает → откат через копию |
|
|
31
|
+
| alpha.4 с совместной проверкой | **нет**, отказ до записи | **нет**, отказ до записи | да | да | — | проверка хранит `engineVersion`; прежние версии его не знают → откат через копию |
|
|
32
|
+
| alpha.6 standalone с записями ревью нового протокола или доставкой `uncertain` | **нет**, отказ до записи | **нет**, отказ до записи | да | да | — | `reviewRound`, `findings[].id/status`, статус доставки `uncertain`; alpha.4/alpha.5 отказывают `STATE_VERSION_UNSUPPORTED` до записи → откат через копию |
|
|
33
|
+
| alpha.6, хост DevContour (адаптер alpha.4) | — | — | да (через адаптер) | да (через адаптер) | да | адаптер DevContour alpha.4 открывает такое состояние без отказа и пишет роль controller и события; новые поля сохраняются → для отката всё равно копия |
|
|
34
|
+
| alpha.7 с новым `inspection` ревью кода | не проверялось | не проверялось | **нет** (строгая схема) | да | — | новые значения `source`, `exitCode: null`, `origins`/`context`/`excluded`; строгая схема alpha.6 их не принимает, поведение прежних версий при открытии не проверялось → откат через копию |
|
|
35
|
+
| неизвестная `stateVersion` | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет | `STATE_VERSION_UNSUPPORTED`, exit 4 |
|
|
36
|
+
|
|
37
|
+
Столбец alpha.2 относится и к alpha.3; alpha.4 и alpha.5 читают все строки, кроме неизвестной `stateVersion` и строк alpha.6 с новыми полями (standalone — отказ до записи) и строки alpha.7. Каждая следующая версия добавляет сюда свой столбец. Отказ неизвестного
|
|
37
38
|
формата до записи проверяют тесты совместимости пакета
|
|
38
39
|
<!-- repo-only -->(`tests/compatibility.test.ts`)<!-- /repo-only -->.
|
|
39
40
|
|
|
@@ -135,6 +136,22 @@ recovery.
|
|
|
135
136
|
(новое согласование). Встроенные профили alpha.5 побайтно прежние; новые
|
|
136
137
|
профили — новые id (`npm-ci`, `pnpm-frozen`, `go-gotestsum`, `python-uv`).
|
|
137
138
|
|
|
139
|
+
### alpha.7: учёт выполненных команд reviewer
|
|
140
|
+
|
|
141
|
+
Формат `stateVersion: 1` прежний. `inspection` в `review.json` и evidence ревью кода получает
|
|
142
|
+
новые значения и необязательные поля ([review-probes](review-probes.md#итог-inspection-что-reviewer-действительно-выполнил)):
|
|
143
|
+
`source` — также `controller-probes` и `runtime-and-controller`; `commands[].exitCode` может
|
|
144
|
+
быть `null`; новые `commands[].origins/status/failure/gate/note`, `context`, `total`,
|
|
145
|
+
`excluded`, `excludedTotal`, `invalid`. Строки исхода в `probes.jsonl` несут `started` и
|
|
146
|
+
`scope`; `review.json.probes` — `exitCode`, `started`, `scope`, `note`.
|
|
147
|
+
|
|
148
|
+
Направление совместимости одностороннее: alpha.7 читает записи alpha.6 и ранее без
|
|
149
|
+
пересчёта; строгая схема alpha.6 не принимает новый `source`, `exitCode: null` и новые поля,
|
|
150
|
+
поэтому состояние с такими записями alpha.6 не читает. Потребителю, разбирающему
|
|
151
|
+
`inspection`, нужно принять новые значения `source`, nullable `exitCode` и необязательные
|
|
152
|
+
поля; признак выполнения — `mode`, а не наличие кода 0. Откат — как для alpha.6: только
|
|
153
|
+
восстановлением копии состояния, сделанной до обновления.
|
|
154
|
+
|
|
138
155
|
## Перед обновлением
|
|
139
156
|
|
|
140
157
|
1. **Остановить записывающих.** Запретить новые выдачи (`harness pause`),
|
|
@@ -176,11 +193,11 @@ recovery.
|
|
|
176
193
|
|
|
177
194
|
## Откат
|
|
178
195
|
|
|
179
|
-
| Ситуация
|
|
180
|
-
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
181
|
-
| Изменения исходников до выкатки
|
|
182
|
-
| Только пакет, формат данных совместим | Остановить writers → вернуть прежнюю версию (архив или точную версию npm), зависимость и lock → `harness doctor` → возобновить
|
|
183
|
-
| Новая версия уже изменила формат
|
|
196
|
+
| Ситуация | Действие |
|
|
197
|
+
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- || --------------------
|
|
198
|
+
| Изменения исходников до выкатки | Вернуться к проверенной паре коммитов/версий в отдельном checkout или revert-коммитами; страховочную ветку не переписывать |
|
|
199
|
+
| Только пакет, формат данных совместим | Остановить writers → вернуть прежнюю версию (архив или точную версию npm), зависимость и lock → `harness doctor` → возобновить |
|
|
200
|
+
| Новая версия уже изменила формат | Остановить writers → восстановить согласованную копию вместе с совместимой версией пакета → сверить Git refs и артефакты (ниже); простого понижения версии мало |
|
|
184
201
|
|
|
185
202
|
### Сверка Git после восстановления базы
|
|
186
203
|
|
|
@@ -279,9 +279,16 @@ export function cliAdapter(runtime, options = {}) {
|
|
|
279
279
|
diagnostics: { exitCode: null, reason: redact(reason).slice(0, 500), log: logPath },
|
|
280
280
|
});
|
|
281
281
|
let result;
|
|
282
|
+
// События runtime для inspection разбираются до маскирования (иначе
|
|
283
|
+
// короткий секрет портит `item.completed`), текст полей маскируется
|
|
284
|
+
// при разборе; сырой поток только в памяти и не сохраняется.
|
|
285
|
+
let raw = '';
|
|
282
286
|
try {
|
|
283
287
|
result = await command(argv, r.cwd, {
|
|
284
288
|
contain: { dirs: review ? [] : r.sandbox.writable },
|
|
289
|
+
...(review
|
|
290
|
+
? { onRawStdout: (text) => void (raw = (raw + text).slice(-2_000_000)) }
|
|
291
|
+
: {}),
|
|
285
292
|
onOutput: (stream, text) => {
|
|
286
293
|
if (logged >= 10_000_000)
|
|
287
294
|
return;
|
|
@@ -333,7 +340,7 @@ export function cliAdapter(runtime, options = {}) {
|
|
|
333
340
|
model,
|
|
334
341
|
runtimeVersion: version,
|
|
335
342
|
usage,
|
|
336
|
-
...(review ? { inspection: inspectReview(runtime,
|
|
343
|
+
...(review ? { inspection: inspectReview(runtime, raw, redact) } : {}),
|
|
337
344
|
};
|
|
338
345
|
const diagnostics = (why) => ({
|
|
339
346
|
exitCode: result.code,
|
package/lib/agents/inspect.d.ts
CHANGED
|
@@ -1,6 +1,60 @@
|
|
|
1
1
|
import type { EvidenceRecord } from '../contracts/index.ts';
|
|
2
|
+
import { type ProbeJournal } from './review-probe.ts';
|
|
2
3
|
type ReviewInspection = NonNullable<EvidenceRecord['inspection']>;
|
|
4
|
+
export type InspectionContext = NonNullable<ReviewInspection['context']>;
|
|
5
|
+
/** Пределы итога: число команд и длины сохраняемых строк (docs/review-probes.md). */
|
|
6
|
+
export declare const inspectionLimits: {
|
|
7
|
+
readonly commands: 100;
|
|
8
|
+
readonly command: 12000;
|
|
9
|
+
readonly output: 4000;
|
|
10
|
+
readonly note: 2000;
|
|
11
|
+
readonly excluded: 100;
|
|
12
|
+
};
|
|
3
13
|
export declare const unobservedReview: () => ReviewInspection;
|
|
4
|
-
/**
|
|
5
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Что reviewer действительно выполнил — по событиям runtime, а не по словам
|
|
16
|
+
* модели. Завершённая команда — выполнение при любом коде выхода: ненулевой
|
|
17
|
+
* код — исход проверки, а не признак того, что её не было. Повтор события
|
|
18
|
+
* того же item ID — одна команда.
|
|
19
|
+
*/
|
|
20
|
+
export declare function inspectReview(runtime: string, output: string, redact?: (text: string) => string): ReviewInspection;
|
|
21
|
+
/**
|
|
22
|
+
* Итог `inspection` одного вызова reviewer: события runtime этого вызова и
|
|
23
|
+
* журнал проверок controller этого вызова. Самоотчёт модели (`execution`,
|
|
24
|
+
* `reproduction.executed`, runId в тексте) сюда не входит.
|
|
25
|
+
*
|
|
26
|
+
* Операция одна, если совпадает надёжная идентичность: runId запуска
|
|
27
|
+
* controller, item ID runtime внутри его потока или явная структурированная
|
|
28
|
+
* связь наблюдения runtime с runId controller (origin `controller` у команды
|
|
29
|
+
* runtime). Совпадение текста, вывода или замаскированных аргументов
|
|
30
|
+
* операции не склеивает.
|
|
31
|
+
*
|
|
32
|
+
* Порядок: команды runtime в порядке потока, затем запуски controller в
|
|
33
|
+
* порядке журнала; при превышении предела сохраняются последние
|
|
34
|
+
* {@link inspectionLimits.commands}, `total` — число всех подтверждённых.
|
|
35
|
+
* Mode — по всему набору. Пользовательский текст маскируется до обрезки;
|
|
36
|
+
* перечисления и идентификаторы controller не маскируются.
|
|
37
|
+
*/
|
|
38
|
+
export declare function reviewInspection(input: {
|
|
39
|
+
/** Наблюдение runtime (ответ адаптера); нет — runtime его не дал. */
|
|
40
|
+
runtime?: ReviewInspection;
|
|
41
|
+
/** Журнал проверок controller этого вызова или сохранённая проекция `review.json.probes`. */
|
|
42
|
+
journal?: ProbeJournal;
|
|
43
|
+
context: InspectionContext;
|
|
44
|
+
redact?: (text: string) => string;
|
|
45
|
+
}): ReviewInspection;
|
|
46
|
+
/**
|
|
47
|
+
* Маскирование сохранённого inspection: только свободный текст (`command`,
|
|
48
|
+
* `output`, `note`, `reason`) и с обрезкой до пределов после маски — замена
|
|
49
|
+
* секрета может удлинить строку. Перечисления, origins, контекст и
|
|
50
|
+
* идентификаторы controller не маскируются — короткий секрет, совпавший с
|
|
51
|
+
* их частью, не делает запись невалидной.
|
|
52
|
+
*/
|
|
53
|
+
export declare function redactInspection(inspection: ReviewInspection, redact: (text: string) => string): ReviewInspection;
|
|
54
|
+
/**
|
|
55
|
+
* Сохранённая проекция `review.json.probes` (alpha.6 и ранее: без кода, вывода и
|
|
56
|
+
* признака старта) как журнал для {@link reviewInspection}. Пересчёт старого
|
|
57
|
+
* состояния не выполняется: это вход для отдельной агрегации старых данных.
|
|
58
|
+
*/
|
|
59
|
+
export declare function journalFromProjection(probes: unknown): ProbeJournal;
|
|
6
60
|
export {};
|