devcontour-harness 0.1.0-alpha.13 → 0.1.0-alpha.18
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 +48 -2
- package/docs/architecture.md +77 -3
- package/docs/contracts.md +100 -0
- package/docs/quickstart.md +1 -1
- package/docs/release-notes/0.1.0-alpha.14.md +69 -0
- package/docs/release-notes/0.1.0-alpha.15.md +62 -0
- package/docs/release-notes/0.1.0-alpha.16.md +36 -0
- 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/review-probes.md +9 -3
- package/docs/review-protocol.md +9 -0
- package/docs/upgrade.md +16 -14
- 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/contracts/checks.d.ts +119 -0
- package/lib/contracts/checks.js +64 -1
- package/lib/contracts/cli.d.ts +30 -0
- package/lib/contracts/diagnosis.d.ts +3 -1
- package/lib/contracts/diagnosis.js +2 -0
- package/lib/contracts/events.d.ts +12 -0
- package/lib/contracts/execution.d.ts +109 -5
- package/lib/contracts/execution.js +58 -0
- package/lib/contracts/failure.d.ts +17 -3
- package/lib/contracts/failure.js +4 -2
- package/lib/contracts/published.d.ts +67 -1
- package/lib/contracts/repair-policy.d.ts +7 -0
- package/lib/contracts/repair-policy.js +17 -0
- package/lib/contracts/review.d.ts +12 -0
- package/lib/contracts/review.js +19 -0
- package/lib/control/harness.d.ts +2 -2
- package/lib/control/harness.js +2 -1
- package/lib/control/recovery.d.ts +26 -1
- package/lib/engine/engine.d.ts +41 -14
- package/lib/engine/engine.js +92 -8
- 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 +7 -0
- package/lib/engine/runner.js +207 -34
- package/lib/explain/state.js +4 -2
- package/lib/index.d.ts +6 -4
- package/lib/index.js +6 -4
- package/lib/projections/stop.d.ts +1 -1
- package/lib/projections/stop.js +16 -0
- package/lib/storage/document.d.ts +48 -8
- package/lib/verification/acceptance.js +2 -1
- package/lib/verification/already-satisfied.d.ts +44 -0
- package/lib/verification/already-satisfied.js +49 -0
- package/lib/verification/checks.d.ts +28 -0
- package/lib/verification/checks.js +270 -22
- package/lib/verification/corpus.d.ts +50 -0
- 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 +5 -0
- package/lib/verification/gates.js +20 -5
- package/lib/verification/property.d.ts +9 -0
- package/lib/verification/property.js +11 -2
- package/lib/verification/self-check.js +12 -12
- package/package.json +1 -1
- package/schemas/contract-document.schema.json +161 -0
- package/schemas/execution-document.schema.json +134 -0
- package/schemas/run-event.schema.json +4 -0
- package/schemas/stop-diagnosis.schema.json +2 -0
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` — запись прежней версии. Её находки (у
|
package/docs/upgrade.md
CHANGED
|
@@ -21,20 +21,22 @@
|
|
|
21
21
|
|
|
22
22
|
## Матрица форматов
|
|
23
23
|
|
|
24
|
-
| Состояние, записанное…
|
|
25
|
-
|
|
|
26
|
-
| standalone `stateVersion: 1` версией alpha.1
|
|
27
|
-
| хост, центральная база
|
|
28
|
-
| хост, базы компонентов
|
|
29
|
-
| alpha.2 после штатной остановки controller
|
|
30
|
-
| alpha.2 с живой или брошенной ролью controller
|
|
31
|
-
| alpha.4 с совместной проверкой
|
|
32
|
-
| alpha.6 standalone с записями ревью нового протокола или доставкой `uncertain`
|
|
33
|
-
| alpha.6, хост DevContour (адаптер alpha.4)
|
|
34
|
-
| alpha.7 с новым `inspection` ревью кода
|
|
35
|
-
|
|
|
36
|
-
|
|
37
|
-
|
|
24
|
+
| Состояние, записанное… | Читает 0.1.0-alpha.1 | Читает 0.1.0-alpha.2 | Читает 0.1.0-alpha.6 | Читает 0.1.0-alpha.7 | Читает 0.1.0-alpha.8 | Читает 0.1.0-alpha.9 | Читает 0.1.0-alpha.10 | Читает 0.1.0-alpha.11 | Читает 0.1.0-alpha.12 | Читает 0.1.0-alpha.13 | Читает 0.1.0-alpha.14 | Читает 0.1.0-alpha.15 | Читает 0.1.0-alpha.16 | Читает 0.1.0-alpha.17 | Читает 0.1.0-alpha.18 | Пишет поверх | Примечание |
|
|
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
|
+
| alpha.14 с договором проверки `reference` или `gates` обязательства | не проверялось | не проверялось | не проверялось | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | да | да | да | да | да | — | контракт хранится строгой схемой (`contract-documents`): прежние версии новых полей `gates`, `verification`, `reference` не знают → откат через копию |
|
|
36
|
+
| alpha.17 с `interrupted`, `inputClasses`, `classified`, `neutralFailures`, `alreadySatisfied` в evidence ревью или классом отказа `unfinished`/`needs-lead` | не проверялось | не проверялось | не проверялось | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | **нет** (строгая схема) | да | да | — | попытка (`interrupted`, `inputClasses`, `classified`), поручение (`neutralFailures`), `alreadySatisfied` evidence ревью и классы отказа `unfinished`, `needs-lead` — новые значения строгих схем; прежние версии их отклоняют → откат через копию |
|
|
37
|
+
| неизвестная `stateVersion` | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет, отказ до записи | нет | `STATE_VERSION_UNSUPPORTED`, exit 4 |
|
|
38
|
+
|
|
39
|
+
Столбец alpha.2 относится и к alpha.3; alpha.4 и alpha.5 читают все строки, кроме неизвестной `stateVersion` и строк alpha.6 с новыми полями (standalone — отказ до записи) и строки alpha.7. alpha.8, alpha.9, alpha.10, alpha.11, alpha.12 и alpha.13 формат состояния не меняют и читают всё, что читает alpha.7; alpha.14 и alpha.15 (локальные, не опубликованы) и alpha.16 читают всё, что читает alpha.13, и добавляют необязательные поля договора проверки (строка alpha.14). alpha.17 читает всё, что читает alpha.16, и добавляет необязательные поля попытки, поручения и evidence ревью и классы отказа `unfinished` и `needs-lead` (строка alpha.17); alpha.18 формат состояния не меняет и читает всё, что читает alpha.17. Каждая следующая версия добавляет сюда свой столбец. Отказ неизвестного
|
|
38
40
|
формата до записи проверяют тесты совместимости пакета
|
|
39
41
|
<!-- repo-only -->(`tests/compatibility.test.ts`)<!-- /repo-only -->.
|
|
40
42
|
|
|
@@ -8,7 +8,7 @@ import { redactor } from "../environment/redaction.js";
|
|
|
8
8
|
import { inspectReview } from "./inspect.js";
|
|
9
9
|
import { probeCallMs, probeServer, probeTool } from "./review-probe.js";
|
|
10
10
|
import { claudeResult, runtimeEvents } from "./runtime-events.js";
|
|
11
|
-
import {
|
|
11
|
+
import { runtimeVersion, unknownUsage, usageStream } from "./usage.js";
|
|
12
12
|
/** Встроенные инструменты исполнителя claude, когда профиль их не называет; shell — в песочнице ОС. */
|
|
13
13
|
export const claudeWriterTools = ['Read', 'Glob', 'Grep', 'Edit', 'Write', 'Bash'];
|
|
14
14
|
const writerTools = (profile) => profile?.claudeTools ?? claudeWriterTools;
|
|
@@ -283,12 +283,17 @@ export function cliAdapter(runtime, options = {}) {
|
|
|
283
283
|
// короткий секрет портит `item.completed`), текст полей маскируется
|
|
284
284
|
// при разборе; сырой поток только в памяти и не сохраняется.
|
|
285
285
|
let raw = '';
|
|
286
|
+
// Телеметрия — по всему потоку, независимо от пределов журнала и
|
|
287
|
+
// хвоста stdout: итоговое событие долгого вызова лежит за ними.
|
|
288
|
+
const telemetry = usageStream(runtime);
|
|
286
289
|
try {
|
|
287
290
|
result = await command(argv, r.cwd, {
|
|
288
291
|
contain: { dirs: review ? [] : r.sandbox.writable },
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
+
onRawStdout: (text) => {
|
|
293
|
+
telemetry.push(text);
|
|
294
|
+
if (review)
|
|
295
|
+
raw = (raw + text).slice(-2_000_000);
|
|
296
|
+
},
|
|
292
297
|
onOutput: (stream, text) => {
|
|
293
298
|
if (logged >= 10_000_000)
|
|
294
299
|
return;
|
|
@@ -312,12 +317,11 @@ export function cliAdapter(runtime, options = {}) {
|
|
|
312
317
|
return unavailable(`${runtime}: runtime не запускается: ${String(error)}`);
|
|
313
318
|
throw error;
|
|
314
319
|
}
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const model = reportedModel(result.stdout);
|
|
320
|
+
const usage = telemetry.usage(result.code === 0 && !result.timedOut && !signal.aborted);
|
|
321
|
+
const model = telemetry.model();
|
|
322
|
+
// Сообщённые runtime счётчики и стоимость — и в диагностике вызова:
|
|
323
|
+
// runtime.log ограничен и итоговой строки может не содержать.
|
|
324
|
+
await writeFile(join(dir, 'runtime.json'), JSON.stringify({ ...result.diagnostics, usage }, null, 2));
|
|
321
325
|
const bookkeeping = ['system', 'result', 'error', 'session.created', 'thread.started'];
|
|
322
326
|
const started = result.timedOut ||
|
|
323
327
|
runtimeEvents(result.stdout).events.some((e) => !bookkeeping.includes(String(e.type)));
|
|
@@ -118,6 +118,15 @@ export type ProbeGateRun = {
|
|
|
118
118
|
/** Имена переменных, которые выставил controller (значения не пишутся). */
|
|
119
119
|
controllerEnv: string[];
|
|
120
120
|
report?: ProbeReport;
|
|
121
|
+
/**
|
|
122
|
+
* Копия отчёта свойств, если проверка записала его по пути
|
|
123
|
+
* `DEVCONTOUR_PROPERTY_REPORT` в scratch. Только evidence probe: движок
|
|
124
|
+
* этот отчёт не читает, и свойства по нему не засчитываются.
|
|
125
|
+
*/
|
|
126
|
+
propertyReport?: {
|
|
127
|
+
path: string;
|
|
128
|
+
scope: 'probe-only';
|
|
129
|
+
};
|
|
121
130
|
/** Каталог evidence запуска в каталоге ревью controller. */
|
|
122
131
|
artifacts?: string;
|
|
123
132
|
/** Временный каталог отчёта; убран после сохранения evidence. */
|
|
@@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
9
9
|
import { z } from 'zod';
|
|
10
10
|
import { idSchema, relativePathSchema, sha256, } from "../contracts/index.js";
|
|
11
11
|
import { redactor } from "../environment/redaction.js";
|
|
12
|
-
import { completedCheck, freshnessEnv, junitSummary, runCheck, sandboxBlockedHosts, } from "../verification/gates.js";
|
|
12
|
+
import { completedCheck, freshnessEnv, propertyReportEnv, junitSummary, runCheck, sandboxBlockedHosts, } from "../verification/gates.js";
|
|
13
13
|
/**
|
|
14
14
|
* Пробные проверки reviewer под пределами harness.
|
|
15
15
|
*
|
|
@@ -112,6 +112,21 @@ export function fixedReportArgument(argv, cwd, report) {
|
|
|
112
112
|
}
|
|
113
113
|
return undefined;
|
|
114
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Копия отчёта свойств из scratch в evidence probe. Как и JUnit: symlink,
|
|
117
|
+
* жёсткая ссылка, файл вне scratch и слишком большой файл не читаются.
|
|
118
|
+
*/
|
|
119
|
+
async function savePropertyReport(path, scratch, runDir, id, redact) {
|
|
120
|
+
const stat = await lstat(path).catch(() => undefined);
|
|
121
|
+
if (!stat?.isFile() || stat.nlink > 1 || stat.size > REPORT_LIMIT)
|
|
122
|
+
return undefined;
|
|
123
|
+
const real = await realpath(path);
|
|
124
|
+
if (!within(dirname(real), scratch))
|
|
125
|
+
return undefined;
|
|
126
|
+
const saved = join(runDir, `${id}.property.json`);
|
|
127
|
+
await writeFile(saved, redact(await readFile(real, 'utf8')), { flag: 'wx' });
|
|
128
|
+
return { path: saved, scope: 'probe-only' };
|
|
129
|
+
}
|
|
115
130
|
/**
|
|
116
131
|
* Отчёт запуска gate в scratch controller. Symlink, жёсткая ссылка и путь вне
|
|
117
132
|
* scratch не читаются: так отчёт подменялся бы чужим файлом — прежним
|
|
@@ -458,12 +473,18 @@ export class ReviewProbes {
|
|
|
458
473
|
}
|
|
459
474
|
meta.scratch = scratch;
|
|
460
475
|
const reportPath = join(scratch, `${gate.id}.xml`);
|
|
476
|
+
// Отчёт свойств — тоже в scratch, под тем же именем переменной, что и у
|
|
477
|
+
// gate движка (`propertyReportEnv`): проверка, пишущая отчёт свойств по
|
|
478
|
+
// прежнему пути в дереве, под probe получала бы EPERM. Seed, селектор и
|
|
479
|
+
// корпус probe не выставляет: генеративные gate он не исполняет.
|
|
480
|
+
const propertyPath = join(scratch, `${gate.id}.property.json`);
|
|
461
481
|
const controllerEnv = {
|
|
462
482
|
CI: '1',
|
|
463
483
|
...freshnessEnv(gate.kind, env),
|
|
464
484
|
...(gate.report
|
|
465
485
|
? { DEVCONTOUR_REPORT_PATH: reportPath, HARNESS_REPORT_PATH: reportPath }
|
|
466
486
|
: {}),
|
|
487
|
+
[propertyReportEnv]: propertyPath,
|
|
467
488
|
};
|
|
468
489
|
meta.controllerEnv = Object.keys(controllerEnv);
|
|
469
490
|
const started = Date.now();
|
|
@@ -493,6 +514,7 @@ export class ReviewProbes {
|
|
|
493
514
|
const read = gate.report
|
|
494
515
|
? await inspectReport(reportPath, scratch, started, redact)
|
|
495
516
|
: undefined;
|
|
517
|
+
meta.propertyReport = await savePropertyReport(propertyPath, scratch, runDir, gate.id, redact);
|
|
496
518
|
if (read) {
|
|
497
519
|
meta.report = read.report;
|
|
498
520
|
if (read.xml !== undefined) {
|
package/lib/agents/schemas.d.ts
CHANGED
|
@@ -164,6 +164,9 @@ export declare const reviewOutputSchema: {
|
|
|
164
164
|
input: {
|
|
165
165
|
type: string;
|
|
166
166
|
};
|
|
167
|
+
inputClass: {
|
|
168
|
+
type: string[];
|
|
169
|
+
};
|
|
167
170
|
expected: {
|
|
168
171
|
type: string[];
|
|
169
172
|
};
|
|
@@ -215,3 +218,206 @@ export declare const reviewOutputSchema: {
|
|
|
215
218
|
};
|
|
216
219
|
required: string[];
|
|
217
220
|
};
|
|
221
|
+
/**
|
|
222
|
+
* Ответ reviewer попытки без изменений: тот же протокол и обязательное
|
|
223
|
+
* `alreadySatisfied` (`null` — подтверждения нет). Обычное ревью этого поля
|
|
224
|
+
* не получает: его вид ответа не меняется.
|
|
225
|
+
*/
|
|
226
|
+
export declare const alreadySatisfiedReviewOutputSchema: {
|
|
227
|
+
properties: {
|
|
228
|
+
alreadySatisfied: {
|
|
229
|
+
anyOf: ({
|
|
230
|
+
type: string;
|
|
231
|
+
additionalProperties?: undefined;
|
|
232
|
+
properties?: undefined;
|
|
233
|
+
required?: undefined;
|
|
234
|
+
} | {
|
|
235
|
+
type: string;
|
|
236
|
+
additionalProperties: boolean;
|
|
237
|
+
properties: {
|
|
238
|
+
gates: {
|
|
239
|
+
type: string;
|
|
240
|
+
minItems: number;
|
|
241
|
+
maxItems: number;
|
|
242
|
+
items: {
|
|
243
|
+
type: string;
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
evidence: {
|
|
247
|
+
type: string;
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
required: string[];
|
|
251
|
+
})[];
|
|
252
|
+
};
|
|
253
|
+
execution: {
|
|
254
|
+
type: string;
|
|
255
|
+
additionalProperties: boolean;
|
|
256
|
+
properties: {
|
|
257
|
+
commands: {
|
|
258
|
+
type: string;
|
|
259
|
+
maxItems: number;
|
|
260
|
+
items: {
|
|
261
|
+
type: string;
|
|
262
|
+
additionalProperties: boolean;
|
|
263
|
+
properties: {
|
|
264
|
+
command: {
|
|
265
|
+
type: string;
|
|
266
|
+
};
|
|
267
|
+
exitCode: {
|
|
268
|
+
type: string;
|
|
269
|
+
};
|
|
270
|
+
summary: {
|
|
271
|
+
type: string;
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
required: string[];
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
noCommandsReason: {
|
|
278
|
+
type: string[];
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
required: string[];
|
|
282
|
+
};
|
|
283
|
+
approved: {
|
|
284
|
+
type: string;
|
|
285
|
+
};
|
|
286
|
+
summary: {
|
|
287
|
+
type: string;
|
|
288
|
+
};
|
|
289
|
+
discoveries: {
|
|
290
|
+
type: string;
|
|
291
|
+
maxItems: number;
|
|
292
|
+
items: {
|
|
293
|
+
type: string;
|
|
294
|
+
additionalProperties: boolean;
|
|
295
|
+
properties: {
|
|
296
|
+
kind: {
|
|
297
|
+
type: string;
|
|
298
|
+
enum: string[];
|
|
299
|
+
};
|
|
300
|
+
title: {
|
|
301
|
+
type: string;
|
|
302
|
+
};
|
|
303
|
+
path: {
|
|
304
|
+
type: string;
|
|
305
|
+
};
|
|
306
|
+
line: {
|
|
307
|
+
type: string;
|
|
308
|
+
minimum: number;
|
|
309
|
+
};
|
|
310
|
+
observation: {
|
|
311
|
+
type: string;
|
|
312
|
+
};
|
|
313
|
+
consequence: {
|
|
314
|
+
type: string;
|
|
315
|
+
};
|
|
316
|
+
reproduction: {
|
|
317
|
+
type: string;
|
|
318
|
+
};
|
|
319
|
+
};
|
|
320
|
+
required: string[];
|
|
321
|
+
};
|
|
322
|
+
};
|
|
323
|
+
findings: {
|
|
324
|
+
type: string;
|
|
325
|
+
items: {
|
|
326
|
+
type: string;
|
|
327
|
+
additionalProperties: boolean;
|
|
328
|
+
properties: {
|
|
329
|
+
severity: {
|
|
330
|
+
type: string;
|
|
331
|
+
enum: string[];
|
|
332
|
+
};
|
|
333
|
+
message: {
|
|
334
|
+
type: string;
|
|
335
|
+
};
|
|
336
|
+
path: {
|
|
337
|
+
type: string[];
|
|
338
|
+
};
|
|
339
|
+
line: {
|
|
340
|
+
type: string[];
|
|
341
|
+
minimum: number;
|
|
342
|
+
};
|
|
343
|
+
rule: {
|
|
344
|
+
type: string[];
|
|
345
|
+
};
|
|
346
|
+
consequence: {
|
|
347
|
+
type: string[];
|
|
348
|
+
};
|
|
349
|
+
evidence: {
|
|
350
|
+
type: string[];
|
|
351
|
+
};
|
|
352
|
+
reproduction: {
|
|
353
|
+
anyOf: ({
|
|
354
|
+
type: string;
|
|
355
|
+
additionalProperties?: undefined;
|
|
356
|
+
properties?: undefined;
|
|
357
|
+
required?: undefined;
|
|
358
|
+
} | {
|
|
359
|
+
type: string;
|
|
360
|
+
additionalProperties: boolean;
|
|
361
|
+
properties: {
|
|
362
|
+
property: {
|
|
363
|
+
type: string[];
|
|
364
|
+
};
|
|
365
|
+
input: {
|
|
366
|
+
type: string;
|
|
367
|
+
};
|
|
368
|
+
inputClass: {
|
|
369
|
+
type: string[];
|
|
370
|
+
};
|
|
371
|
+
expected: {
|
|
372
|
+
type: string[];
|
|
373
|
+
};
|
|
374
|
+
actual: {
|
|
375
|
+
type: string[];
|
|
376
|
+
};
|
|
377
|
+
command: {
|
|
378
|
+
type: string[];
|
|
379
|
+
items: {
|
|
380
|
+
type: string;
|
|
381
|
+
};
|
|
382
|
+
};
|
|
383
|
+
executed: {
|
|
384
|
+
type: string;
|
|
385
|
+
};
|
|
386
|
+
run: {
|
|
387
|
+
type: string[];
|
|
388
|
+
};
|
|
389
|
+
};
|
|
390
|
+
required: string[];
|
|
391
|
+
})[];
|
|
392
|
+
};
|
|
393
|
+
};
|
|
394
|
+
required: string[];
|
|
395
|
+
};
|
|
396
|
+
};
|
|
397
|
+
previous: {
|
|
398
|
+
type: string;
|
|
399
|
+
items: {
|
|
400
|
+
type: string;
|
|
401
|
+
additionalProperties: boolean;
|
|
402
|
+
properties: {
|
|
403
|
+
id: {
|
|
404
|
+
type: string;
|
|
405
|
+
pattern: string;
|
|
406
|
+
};
|
|
407
|
+
status: {
|
|
408
|
+
type: string;
|
|
409
|
+
enum: ("open" | "closed" | "withdrawn")[];
|
|
410
|
+
};
|
|
411
|
+
basis: {
|
|
412
|
+
type: string;
|
|
413
|
+
pattern: string;
|
|
414
|
+
};
|
|
415
|
+
};
|
|
416
|
+
required: string[];
|
|
417
|
+
};
|
|
418
|
+
};
|
|
419
|
+
};
|
|
420
|
+
required: string[];
|
|
421
|
+
type: string;
|
|
422
|
+
additionalProperties: boolean;
|
|
423
|
+
};
|
package/lib/agents/schemas.js
CHANGED
|
@@ -80,13 +80,23 @@ export const reviewOutputSchema = {
|
|
|
80
80
|
properties: {
|
|
81
81
|
property: { type: ['string', 'null'] },
|
|
82
82
|
input: { type: 'string' },
|
|
83
|
+
inputClass: { type: ['string', 'null'] },
|
|
83
84
|
expected: { type: ['string', 'null'] },
|
|
84
85
|
actual: { type: ['string', 'null'] },
|
|
85
86
|
command: { type: ['array', 'null'], items: { type: 'string' } },
|
|
86
87
|
executed: { type: 'boolean' },
|
|
87
88
|
run: { type: ['string', 'null'] },
|
|
88
89
|
},
|
|
89
|
-
required: [
|
|
90
|
+
required: [
|
|
91
|
+
'property',
|
|
92
|
+
'input',
|
|
93
|
+
'inputClass',
|
|
94
|
+
'expected',
|
|
95
|
+
'actual',
|
|
96
|
+
'command',
|
|
97
|
+
'executed',
|
|
98
|
+
'run',
|
|
99
|
+
],
|
|
90
100
|
},
|
|
91
101
|
],
|
|
92
102
|
},
|
|
@@ -122,3 +132,29 @@ export const reviewOutputSchema = {
|
|
|
122
132
|
},
|
|
123
133
|
required: ['approved', 'summary', 'findings', 'discoveries', 'execution', 'previous'],
|
|
124
134
|
};
|
|
135
|
+
/**
|
|
136
|
+
* Ответ reviewer попытки без изменений: тот же протокол и обязательное
|
|
137
|
+
* `alreadySatisfied` (`null` — подтверждения нет). Обычное ревью этого поля
|
|
138
|
+
* не получает: его вид ответа не меняется.
|
|
139
|
+
*/
|
|
140
|
+
export const alreadySatisfiedReviewOutputSchema = {
|
|
141
|
+
...reviewOutputSchema,
|
|
142
|
+
properties: {
|
|
143
|
+
...reviewOutputSchema.properties,
|
|
144
|
+
alreadySatisfied: {
|
|
145
|
+
anyOf: [
|
|
146
|
+
{ type: 'null' },
|
|
147
|
+
{
|
|
148
|
+
type: 'object',
|
|
149
|
+
additionalProperties: false,
|
|
150
|
+
properties: {
|
|
151
|
+
gates: { type: 'array', minItems: 1, maxItems: 20, items: { type: 'string' } },
|
|
152
|
+
evidence: { type: 'string' },
|
|
153
|
+
},
|
|
154
|
+
required: ['gates', 'evidence'],
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
required: [...reviewOutputSchema.required, 'alreadySatisfied'],
|
|
160
|
+
};
|
package/lib/agents/usage.d.ts
CHANGED
|
@@ -6,3 +6,25 @@ export declare function parseUsage(runtime: 'codex' | 'claude', stdout: string,
|
|
|
6
6
|
export declare function runtimeVersion(executable: string, env?: NodeJS.ProcessEnv): Promise<string | null>;
|
|
7
7
|
/** Модель, которую runtime выбрал на самом деле: событие system у claude, ключи modelUsage у codex. */
|
|
8
8
|
export declare function reportedModel(stdout: string): string | null;
|
|
9
|
+
/** Строка потока длиннее — не разбирается и делает телеметрию неполной. */
|
|
10
|
+
export declare const LINE_LIMIT = 8000000;
|
|
11
|
+
/**
|
|
12
|
+
* Телеметрия, собранная по ходу потока runtime, а не из хвоста вывода. Хвост
|
|
13
|
+
* stdout и журнал вызова ограничены, и у долгого вызова итоговое событие
|
|
14
|
+
* `result` (стоимость и счётчики claude) или ранние `turn.completed` codex
|
|
15
|
+
* оказывались за пределом: стоимость, сообщённая провайдером, терялась или
|
|
16
|
+
* учитывалась неполной. Здесь каждая строка разбирается сразу; хранятся
|
|
17
|
+
* только поля телеметрии — последнее событие `result`, события
|
|
18
|
+
* `turn.completed` и первая сообщённая модель, — а не текст вывода.
|
|
19
|
+
*/
|
|
20
|
+
export declare function usageStream(runtime: 'codex' | 'claude'): {
|
|
21
|
+
/**
|
|
22
|
+
* Очередной фрагмент stdout runtime (без маски: берутся только числа).
|
|
23
|
+
* Вызывается из обработчика вывода процесса и не бросает: сбой разбора —
|
|
24
|
+
* неполная телеметрия, а не падение controller.
|
|
25
|
+
*/
|
|
26
|
+
push(text: string): void;
|
|
27
|
+
/** Телеметрия всего потока; `completed` — вызов завершился штатно. */
|
|
28
|
+
usage(completed: boolean): Usage;
|
|
29
|
+
model: () => string | null;
|
|
30
|
+
};
|