devcontour-harness 0.1.0-alpha.5 → 0.1.0-alpha.6
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 +24 -2
- package/docs/compatibility-versions.md +56 -0
- package/docs/compatibility.md +2 -2
- package/docs/connectors.md +323 -0
- package/docs/contracts.md +33 -5
- package/docs/integrations/hindsight.md +148 -0
- package/docs/quickstart.md +1 -1
- package/docs/release-notes/0.1.0-alpha.6.md +238 -0
- package/docs/review-probes.md +120 -0
- package/docs/review-protocol.md +251 -0
- package/docs/toolchains.md +167 -0
- package/docs/turbo-starter.md +269 -0
- package/docs/upgrade.md +48 -12
- package/examples/README.md +1 -0
- package/examples/toolchains/README.md +32 -0
- package/examples/toolchains/go/bad/label/label.go +9 -0
- package/examples/toolchains/go/good/label/label.go +9 -0
- package/examples/toolchains/go/policy.json +79 -0
- package/examples/toolchains/go/repo/REQUIREMENTS.md +9 -0
- package/examples/toolchains/go/repo/_gitignore +1 -0
- package/examples/toolchains/go/repo/go.mod +5 -0
- package/examples/toolchains/go/repo/go.sum +2 -0
- package/examples/toolchains/go/repo/label/label.go +9 -0
- package/examples/toolchains/go/repo/label/label_test.go +27 -0
- package/examples/toolchains/go/repo/label/version.go +9 -0
- package/examples/toolchains/go/task.json +25 -0
- package/examples/toolchains/mixed-go/bad/backend/label/label.go +9 -0
- package/examples/toolchains/mixed-go/bad/frontend/src/label.js +4 -0
- package/examples/toolchains/mixed-go/good/backend/label/label.go +9 -0
- package/examples/toolchains/mixed-go/good/frontend/src/label.js +4 -0
- package/examples/toolchains/mixed-go/policy.json +126 -0
- package/examples/toolchains/mixed-go/repo/REQUIREMENTS.md +9 -0
- package/examples/toolchains/mixed-go/repo/_gitignore +6 -0
- package/examples/toolchains/mixed-go/repo/backend/go.mod +3 -0
- package/examples/toolchains/mixed-go/repo/backend/label/label.go +9 -0
- package/examples/toolchains/mixed-go/repo/backend/label/label_test.go +30 -0
- package/examples/toolchains/mixed-go/repo/contract/check.mjs +17 -0
- package/examples/toolchains/mixed-go/repo/contract/label.json +9 -0
- package/examples/toolchains/mixed-go/repo/frontend/package.json +15 -0
- package/examples/toolchains/mixed-go/repo/frontend/pnpm-lock.yaml +22 -0
- package/examples/toolchains/mixed-go/repo/frontend/src/label.js +4 -0
- package/examples/toolchains/mixed-go/repo/frontend/test/label.test.js +11 -0
- package/examples/toolchains/mixed-go/task.json +25 -0
- package/examples/toolchains/mixed-python/bad/backend/src/fx_backend/__init__.py +6 -0
- package/examples/toolchains/mixed-python/bad/frontend/src/label.js +4 -0
- package/examples/toolchains/mixed-python/good/backend/src/fx_backend/__init__.py +6 -0
- package/examples/toolchains/mixed-python/good/frontend/src/label.js +4 -0
- package/examples/toolchains/mixed-python/policy.json +121 -0
- package/examples/toolchains/mixed-python/repo/REQUIREMENTS.md +9 -0
- package/examples/toolchains/mixed-python/repo/_gitignore +6 -0
- package/examples/toolchains/mixed-python/repo/backend/.python-version +1 -0
- package/examples/toolchains/mixed-python/repo/backend/pyproject.toml +19 -0
- package/examples/toolchains/mixed-python/repo/backend/src/fx_backend/__init__.py +6 -0
- package/examples/toolchains/mixed-python/repo/backend/tests/test_label.py +11 -0
- package/examples/toolchains/mixed-python/repo/backend/uv.lock +108 -0
- package/examples/toolchains/mixed-python/repo/contract/check.mjs +17 -0
- package/examples/toolchains/mixed-python/repo/contract/label.json +9 -0
- package/examples/toolchains/mixed-python/repo/frontend/package.json +15 -0
- package/examples/toolchains/mixed-python/repo/frontend/pnpm-lock.yaml +22 -0
- package/examples/toolchains/mixed-python/repo/frontend/src/label.js +4 -0
- package/examples/toolchains/mixed-python/repo/frontend/test/label.test.js +11 -0
- package/examples/toolchains/mixed-python/task.json +25 -0
- package/examples/toolchains/npm/bad/src/label.js +4 -0
- package/examples/toolchains/npm/good/src/label.js +4 -0
- package/examples/toolchains/npm/policy.json +82 -0
- package/examples/toolchains/npm/repo/REQUIREMENTS.md +9 -0
- package/examples/toolchains/npm/repo/_gitignore +4 -0
- package/examples/toolchains/npm/repo/package-lock.json +22 -0
- package/examples/toolchains/npm/repo/package.json +13 -0
- package/examples/toolchains/npm/repo/src/label.js +4 -0
- package/examples/toolchains/npm/repo/test/label.test.js +13 -0
- package/examples/toolchains/npm/task.json +25 -0
- package/examples/toolchains/pnpm/bad/packages/label/src/label.js +4 -0
- package/examples/toolchains/pnpm/good/packages/label/src/label.js +4 -0
- package/examples/toolchains/pnpm/policy.json +85 -0
- package/examples/toolchains/pnpm/repo/REQUIREMENTS.md +9 -0
- package/examples/toolchains/pnpm/repo/_gitignore +4 -0
- package/examples/toolchains/pnpm/repo/package.json +10 -0
- package/examples/toolchains/pnpm/repo/packages/checker/check.mjs +5 -0
- package/examples/toolchains/pnpm/repo/packages/checker/package.json +9 -0
- package/examples/toolchains/pnpm/repo/packages/label/package.json +14 -0
- package/examples/toolchains/pnpm/repo/packages/label/src/label.js +4 -0
- package/examples/toolchains/pnpm/repo/packages/label/test/label.test.js +13 -0
- package/examples/toolchains/pnpm/repo/pnpm-lock.yaml +29 -0
- package/examples/toolchains/pnpm/repo/pnpm-workspace.yaml +2 -0
- package/examples/toolchains/pnpm/task.json +25 -0
- package/examples/toolchains/python/bad/src/fx_label/__init__.py +6 -0
- package/examples/toolchains/python/good/src/fx_label/__init__.py +6 -0
- package/examples/toolchains/python/policy.json +80 -0
- package/examples/toolchains/python/repo/.python-version +1 -0
- package/examples/toolchains/python/repo/REQUIREMENTS.md +9 -0
- package/examples/toolchains/python/repo/_gitignore +5 -0
- package/examples/toolchains/python/repo/pyproject.toml +19 -0
- package/examples/toolchains/python/repo/src/fx_label/__init__.py +6 -0
- package/examples/toolchains/python/repo/tests/test_label.py +13 -0
- package/examples/toolchains/python/repo/uv.lock +108 -0
- package/examples/toolchains/python/task.json +25 -0
- package/examples/toolchains/turbo/bad/packages/label/src/label.js +4 -0
- package/examples/toolchains/turbo/good/packages/label/src/label.js +4 -0
- package/examples/toolchains/turbo/policy.json +110 -0
- package/examples/toolchains/turbo/repo/REQUIREMENTS.md +9 -0
- package/examples/toolchains/turbo/repo/_gitignore +4 -0
- package/examples/toolchains/turbo/repo/package.json +13 -0
- package/examples/toolchains/turbo/repo/packages/checker/check.mjs +5 -0
- package/examples/toolchains/turbo/repo/packages/checker/package.json +9 -0
- package/examples/toolchains/turbo/repo/packages/label/package.json +14 -0
- package/examples/toolchains/turbo/repo/packages/label/src/label.js +4 -0
- package/examples/toolchains/turbo/repo/packages/label/test/label.test.js +13 -0
- package/examples/toolchains/turbo/repo/pnpm-lock.yaml +94 -0
- package/examples/toolchains/turbo/repo/pnpm-workspace.yaml +2 -0
- package/examples/toolchains/turbo/repo/turbo.json +7 -0
- package/examples/toolchains/turbo/task.json +25 -0
- package/examples/turbo-starter/README.md +16 -0
- package/examples/turbo-starter/changes/issued-at-consumer-only.patch +12 -0
- package/examples/turbo-starter/changes/issued-at.patch +130 -0
- package/examples/turbo-starter/cleanup.mjs +58 -0
- package/examples/turbo-starter/graph.json +32 -0
- package/examples/turbo-starter/harness/acceptance/db-isolation.test.mjs +97 -0
- package/examples/turbo-starter/harness/acceptance/env-probe.test.mjs +75 -0
- package/examples/turbo-starter/harness/acceptance/generation.test.mjs +54 -0
- package/examples/turbo-starter/harness/acceptance/issued-at.test.mjs +43 -0
- package/examples/turbo-starter/harness/acceptance/lifecycle-probe.test.mjs +47 -0
- package/examples/turbo-starter/harness/compose-bridge.mjs +593 -0
- package/examples/turbo-starter/harness/compose.acceptance.yml +23 -0
- package/examples/turbo-starter/harness/env/backend.env.template +7 -0
- package/examples/turbo-starter/harness/env/compose.env.template +6 -0
- package/examples/turbo-starter/policy.json +109 -0
- package/examples/turbo-starter/policy.lifecycle.json +114 -0
- package/examples/turbo-starter/setup.mjs +352 -0
- package/lib/agents/cli-adapter.js +2 -0
- package/lib/agents/review-probe.d.ts +179 -7
- package/lib/agents/review-probe.js +648 -55
- package/lib/agents/schemas.d.ts +3 -1
- package/lib/agents/schemas.js +7 -3
- package/lib/cli.js +167 -7
- package/lib/contracts/cli.d.ts +820 -11
- package/lib/contracts/cli.js +243 -4
- package/lib/contracts/errors.d.ts +3 -1
- package/lib/contracts/errors.js +2 -0
- package/lib/contracts/events.d.ts +37 -5
- package/lib/contracts/events.js +9 -0
- package/lib/contracts/execution.d.ts +176 -8
- package/lib/contracts/execution.js +9 -1
- package/lib/contracts/failure.js +5 -0
- package/lib/contracts/index.d.ts +1 -0
- package/lib/contracts/index.js +1 -0
- package/lib/contracts/policy.d.ts +15 -0
- package/lib/contracts/policy.js +10 -0
- package/lib/contracts/ports.d.ts +50 -0
- package/lib/contracts/profiles.d.ts +14 -0
- package/lib/contracts/profiles.js +4 -0
- package/lib/contracts/published.d.ts +230 -7
- package/lib/contracts/result.d.ts +171 -0
- package/lib/contracts/result.js +39 -1
- package/lib/contracts/review.d.ts +231 -0
- package/lib/contracts/review.js +326 -2
- package/lib/contracts/toolchain.d.ts +96 -0
- package/lib/contracts/toolchain.js +89 -0
- package/lib/control/doctor.d.ts +16 -1
- package/lib/control/doctor.js +45 -3
- package/lib/control/harness.d.ts +52 -6
- package/lib/control/harness.js +28 -1
- package/lib/control/recovery.d.ts +3 -1
- package/lib/control/review.js +14 -6
- package/lib/engine/classify.js +1 -0
- package/lib/engine/engine.d.ts +39 -15
- package/lib/engine/prompt.d.ts +29 -1
- package/lib/engine/prompt.js +57 -0
- package/lib/engine/property-recovery.js +2 -0
- package/lib/engine/result.js +52 -0
- package/lib/engine/reuse.js +6 -1
- package/lib/engine/runner.d.ts +25 -0
- package/lib/engine/runner.js +491 -122
- package/lib/environment/lifecycle.js +6 -0
- package/lib/environment/live-calls.js +3 -2
- package/lib/environment/os-tools.d.ts +16 -0
- package/lib/environment/os-tools.js +35 -0
- package/lib/environment/process.js +5 -4
- package/lib/integrations/connector/commands.d.ts +358 -0
- package/lib/integrations/connector/commands.js +428 -0
- package/lib/integrations/connector/config.d.ts +215 -0
- package/lib/integrations/connector/config.js +214 -0
- package/lib/integrations/connector/delivery.d.ts +107 -0
- package/lib/integrations/connector/delivery.js +591 -0
- package/lib/integrations/connector/fake.d.ts +291 -0
- package/lib/integrations/connector/fake.js +786 -0
- package/lib/integrations/connector/history.d.ts +124 -0
- package/lib/integrations/connector/history.js +497 -0
- package/lib/integrations/connector/index.d.ts +16 -0
- package/lib/integrations/connector/index.js +16 -0
- package/lib/integrations/connector/redact.d.ts +19 -0
- package/lib/integrations/connector/redact.js +91 -0
- package/lib/integrations/connector/registry.d.ts +15 -0
- package/lib/integrations/connector/registry.js +43 -0
- package/lib/integrations/connector/snapshot.d.ts +131 -0
- package/lib/integrations/connector/snapshot.js +422 -0
- package/lib/integrations/connector/source.d.ts +37 -0
- package/lib/integrations/connector/source.js +73 -0
- package/lib/integrations/connector/steps.d.ts +71 -0
- package/lib/integrations/connector/steps.js +188 -0
- package/lib/integrations/connector/store.d.ts +140 -0
- package/lib/integrations/connector/store.js +277 -0
- package/lib/integrations/connector/summary.d.ts +38 -0
- package/lib/integrations/connector/summary.js +59 -0
- package/lib/integrations/connector/testing-worker.d.ts +1 -0
- package/lib/integrations/connector/testing-worker.js +81 -0
- package/lib/integrations/connector/testing.d.ts +205 -0
- package/lib/integrations/connector/testing.js +1615 -0
- package/lib/integrations/connector/transport.d.ts +240 -0
- package/lib/integrations/connector/transport.js +28 -0
- package/lib/integrations/memory/context.d.ts +120 -0
- package/lib/integrations/memory/context.js +239 -0
- package/lib/integrations/memory/index.d.ts +8 -0
- package/lib/integrations/memory/index.js +8 -0
- package/lib/integrations/memory/provider.d.ts +79 -0
- package/lib/integrations/memory/provider.js +22 -0
- package/lib/integrations/memory/sink.d.ts +56 -0
- package/lib/integrations/memory/sink.js +116 -0
- package/lib/integrations/memory/testing.d.ts +44 -0
- package/lib/integrations/memory/testing.js +61 -0
- package/lib/integrations/relay-v1/index.d.ts +122 -0
- package/lib/integrations/relay-v1/index.js +860 -0
- package/lib/integrations/relay-v2/index.d.ts +145 -0
- package/lib/integrations/relay-v2/index.js +752 -0
- package/lib/integrations/relay-v2/process.d.ts +32 -0
- package/lib/integrations/relay-v2/process.js +112 -0
- package/lib/integrations/relay-v2/protocol.d.ts +172 -0
- package/lib/integrations/relay-v2/protocol.js +142 -0
- package/lib/profiles/resolve.d.ts +5 -1
- package/lib/profiles/resolve.js +31 -0
- package/lib/storage/document.d.ts +60 -12
- package/lib/toolchains/index.d.ts +9 -0
- package/lib/toolchains/index.js +9 -0
- package/lib/toolchains/inspect.d.ts +105 -0
- package/lib/toolchains/inspect.js +831 -0
- package/lib/toolchains/manifests.d.ts +67 -0
- package/lib/toolchains/manifests.js +238 -0
- package/lib/toolchains/probe.d.ts +28 -0
- package/lib/toolchains/probe.js +54 -0
- package/lib/toolchains/recipes.d.ts +33 -0
- package/lib/toolchains/recipes.js +51 -0
- package/lib/verification/acceptance.d.ts +16 -0
- package/lib/verification/acceptance.js +16 -0
- package/lib/verification/gates.d.ts +16 -0
- package/lib/verification/gates.js +44 -3
- package/package.json +22 -1
- package/profiles/go-gotestsum.json +21 -0
- package/profiles/npm-ci.json +22 -0
- package/profiles/pnpm-frozen.json +24 -0
- package/profiles/python-uv.json +26 -0
- package/schemas/execution-document.schema.json +155 -0
- package/schemas/execution-policy.schema.json +48 -0
- package/schemas/result-envelope.schema.json +213 -1
- package/schemas/run-event.schema.json +93 -0
- package/schemas/run-result.schema.json +207 -0
- package/schemas/stack-profile.schema.json +43 -0
- package/templates/controller-mode/AGENTS.controller.md +58 -0
- package/templates/controller-mode/README.md +44 -0
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.6` — предварительный выпуск (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.6 # точная версия
|
|
31
31
|
# или: npm install --save-exact devcontour-harness@alpha # текущая alpha
|
|
32
32
|
npx harness --version
|
|
33
33
|
```
|
|
@@ -117,6 +117,28 @@ PASS» нет. Адаптеры хоста реализуют порты `Execut
|
|
|
117
117
|
`devcontour-harness/schemas/<имя>.schema.json`. Декларации используют типы
|
|
118
118
|
Node.js: TypeScript-потребителю нужен `@types/node` (или `skipLibCheck`).
|
|
119
119
|
|
|
120
|
+
## Выпуск 0.1.0-alpha.6
|
|
121
|
+
|
|
122
|
+
Ядро работает как прежде; всё новое подключается явно. Подробно —
|
|
123
|
+
[заметки выпуска](docs/release-notes/0.1.0-alpha.6.md).
|
|
124
|
+
|
|
125
|
+
- Инструменты целевого проекта: npm, pnpm, Turborepo, Go/gotestsum,
|
|
126
|
+
Python/uv — явными шагами `prepare`, gates и `repositories[].toolchain`;
|
|
127
|
+
`doctor` и обязательный preflight `run` ([toolchains](docs/toolchains.md)).
|
|
128
|
+
- Рецепт Turbo Starter с lifecycle-мостом Docker
|
|
129
|
+
([turbo-starter](docs/turbo-starter.md)).
|
|
130
|
+
- Коннектор задач с транспортами Relay v1 и Relay-2: команды `source-*`,
|
|
131
|
+
`run --source`, доставка с намерением, read-back и явным разбором
|
|
132
|
+
неизвестного исхода ([connectors](docs/connectors.md)).
|
|
133
|
+
- Протокол ревью кода: ID и переходы находок, ограниченный повтор reviewer,
|
|
134
|
+
`REVIEW_PROTOCOL_INVALID` ([review-protocol](docs/review-protocol.md));
|
|
135
|
+
объявленные gates в проверках reviewer ([review-probes](docs/review-probes.md)).
|
|
136
|
+
- Точка подключения внешней памяти — договор без готового адаптера
|
|
137
|
+
([hindsight](docs/integrations/hindsight.md)).
|
|
138
|
+
|
|
139
|
+
Состояние alpha.5 читается без преобразования. Standalone-состояние с новыми записями
|
|
140
|
+
alpha.5 не читает; прежний DevContour его открывает без отказа — откат только через копию ([upgrade](docs/upgrade.md)).
|
|
141
|
+
|
|
120
142
|
## Выпуск 0.1.0-alpha.5
|
|
121
143
|
|
|
122
144
|
Первая публикация в npm. Движок, форматы состояния, политики и договоры — те
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Проверенные версии
|
|
2
|
+
|
|
3
|
+
Набор версий, на котором выпуск фактически проверен. Это не список
|
|
4
|
+
обязательных требований: другие версии могут работать, но не проверялись.
|
|
5
|
+
Строки с «TODO» заполняются по итогам приёмки выпуска.
|
|
6
|
+
|
|
7
|
+
## Пакет и потребители
|
|
8
|
+
|
|
9
|
+
| Что | Версия | Где проверено |
|
|
10
|
+
| ---------------------- | --------------------------------------------------- | -------------------------------------- |
|
|
11
|
+
| ОС / архитектура | macOS 15 (Darwin 24.6), arm64 | все проверки выпуска |
|
|
12
|
+
| Node.js | 24.3.0 (`engines: >=24.3.0`) | все проверки выпуска |
|
|
13
|
+
| npm | 11.4.2 | C01 (установка архива), A01, A02 |
|
|
14
|
+
| pnpm | 10.12.3 | C01 (`pnpm add <архив> --prod`) |
|
|
15
|
+
| TypeScript потребителя | 6.0.3 + `@types/node` 24.13.5 | A01, C01 (ставится отдельно от пакета) |
|
|
16
|
+
| Прежний потребитель | API 0.1.0-alpha.5 | A01 |
|
|
17
|
+
| DevContour | 0.4.0-alpha.7 (`e26f8f4`), vendored alpha.4 → архив | C02 |
|
|
18
|
+
| Git | 2.33.0 | все сценарии |
|
|
19
|
+
|
|
20
|
+
## Инструменты целевых проектов
|
|
21
|
+
|
|
22
|
+
| Что | Версия | Где проверено |
|
|
23
|
+
| -------------- | ------ | -------------- |
|
|
24
|
+
| Turbo | TODO | T01/turbo, S01 |
|
|
25
|
+
| Go / gotestsum | TODO | T01/go |
|
|
26
|
+
| Python / uv | TODO | T01/python |
|
|
27
|
+
| Docker | TODO | S01–S06 |
|
|
28
|
+
|
|
29
|
+
## Транспорты
|
|
30
|
+
|
|
31
|
+
| Что | Версия / commit | Где проверено |
|
|
32
|
+
| ------------------- | --------------- | ------------- |
|
|
33
|
+
| Relay v1 (server) | TODO | R01, W01 |
|
|
34
|
+
| Relay-2 (CLI) / Bun | TODO | R02, R03, W01 |
|
|
35
|
+
|
|
36
|
+
## Как повторить
|
|
37
|
+
|
|
38
|
+
<!-- repo-only -->
|
|
39
|
+
|
|
40
|
+
Проверки выпуска — инструменты разработки harness: они лежат в checkout
|
|
41
|
+
репозитория (`scripts/acceptance/`, `tests/fixtures/consumer-alpha5`) и в
|
|
42
|
+
npm-архив не входят.
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
node scripts/acceptance/package-pack.mjs --out <dir>
|
|
46
|
+
node scripts/acceptance/package-check.mjs <dir>/devcontour-harness-<ver>.tgz
|
|
47
|
+
node scripts/acceptance/consumer-check.mjs <dir>/devcontour-harness-<ver>.tgz
|
|
48
|
+
node scripts/acceptance/core-minimal-env.mjs <dir>/devcontour-harness-<ver>.tgz
|
|
49
|
+
node scripts/acceptance/devcontour-check.mjs <dir>/devcontour-harness-<ver>.tgz \
|
|
50
|
+
--devcontour <путь или URL DevContour> --baseline
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Отчёты скриптов (`report.json`) содержат фактические версии `node`, `npm`,
|
|
54
|
+
`pnpm` и компилятора, hash архива и argv каждой команды.
|
|
55
|
+
|
|
56
|
+
<!-- /repo-only -->
|
package/docs/compatibility.md
CHANGED
|
@@ -91,7 +91,7 @@ coordinator. `Store.change(type, fn)` открывает `BEGIN IMMEDIATE` (вл
|
|
|
91
91
|
| `WorkState` | `Task` (поля исполнения) | `status`, `attempt`, `activeRunId`, `resultSha`, `failure`, `failureKind`, `failureFingerprint`, `approvedAt`, `approvedDigest`, `approvedScope`, `approval`, `hold`, `budgetBlock`, `checkVersion`, `recovery`, `recoveryHistory` — те же имена и формы. `graphId` — доска, в активной ревизии которой задача |
|
|
92
92
|
| `WorkOrder` | `Task` (поля постановки) | `description` → `goal`; `writePaths` (или область роли) → `writeScope`; `contracts` + `contractDigests` → `contracts[{id, digest}]`; `contextPacks` → `context`; `source` = `{connector: 'devcontour', ref: <taskId>, revision: <approvedDigest>}`. Продуктовые поля (`preparation`, `featureId`, `assignee`, `supersedes`, `finding`, `sharedCompletion`, `scope`) в поручение не входят и остаются в `Task` |
|
|
93
93
|
| `AttemptState` | `Run` | Те же имена и формы, включая `context` (краткие pins), `consumers[].checked`, `partial`, `continuedFrom`, `dispatch`, `timings`; `taskId` ↔ `workId`; runtime `demo` ↔ `fixture` на границе (сохранённое значение не переписывается); `memory` остаётся полем `Run` хоста; `engineVersion`, `consumerVersion`, `contextSnapshot` — новые необязательные поля |
|
|
94
|
-
| `EvidenceRecord` | `Evidence` | Без
|
|
94
|
+
| `EvidenceRecord` | `Evidence` | Без изменений; аддитивные необязательные `reviewRound` и `findings[].id/status` ([review-protocol.md](review-protocol.md)) хранятся как есть, прежние записи читаются без них; строгие переходы находок — только для адаптера reviewer с необязательным `RuntimeCapabilities.reviewProtocol: 1` (`cliAdapter`), runtime-обёртки хоста без поля сохраняют приёмку alpha.5 |
|
|
95
95
|
| `ControlState` | `paused`, `pauseReason`, `pausedAt`, `pauseOperation`, `pauseFailures`, `waits`, `appliedConfig`, `reconfigure` | Те же формы; `appliedConfig` ↔ `appliedPolicy` |
|
|
96
96
|
| `ControllerLease` | `leader` | Без изменений |
|
|
97
97
|
| `JointVerificationState` | `Verification` | `manifest`, `manifestDigest`, `policyDigest`, `specDigest`, `impact`, `evidence`, `token`, `leaseUntil`, `status` — те же формы; `tasks` → `workIds` (снимок задач остаётся в `Verification`); `boards`, `productRelease` — поля хоста |
|
|
@@ -181,7 +181,7 @@ Gates, шаги подготовки и проверки потребителе
|
|
|
181
181
|
| Версия движка в основании reuse | Попытка записывает `engineVersion` (и `consumerVersion`). Кандидат попытки другой версии движка повторно не используется: новая попытка заново проходит gates и ревью. Прежние попытки сохраняют своё основание; отсутствующая версия не выдумывается |
|
|
182
182
|
| Reviewer задаётся правилом | `different-vendor` по умолчанию; `same-vendor-allowed` включается явно |
|
|
183
183
|
| Токены вне журнала | Исправление утечки: прежде `run.claimed` и `run.recovered` записывали в журнал попытку целиком, с fencing-токеном. Новые события пишутся без токенов; при выдаче старых событий наружу (CLI, HTTP, RunEvent) токены удаляются. Историю базы физически не переписываем |
|
|
184
|
-
| История находок ревью | Reviewer называет состояние прежних находок; прежние попытки читаются без
|
|
184
|
+
| История находок ревью | Reviewer называет состояние прежних находок; прежние попытки читаются без статусов; ревью кода ведёт историю находок поручения с ID controller, находки записей alpha.5 получают детерминированный ID (review-protocol.md) |
|
|
185
185
|
|
|
186
186
|
## Состояние standalone
|
|
187
187
|
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# Коннектор задач: Relay v1 и Relay-2
|
|
2
|
+
|
|
3
|
+
Коннектор подключает к harness внешнее хранилище задач: читает задачу,
|
|
4
|
+
закрепляет её постановку, исполняет её обычным путём (ревью плана →
|
|
5
|
+
согласование → изолированная попытка → gates → независимое ревью → приёмка в
|
|
6
|
+
Git) и доставляет подтверждённый результат обратно в задачу. Это opt-in
|
|
7
|
+
модуль `devcontour-harness/integrations/connector`: корень пакета и
|
|
8
|
+
`./contracts` его не импортируют, адаптер backend загружается только для
|
|
9
|
+
явно выбранного provider.
|
|
10
|
+
|
|
11
|
+
Поддерживаются два независимых транспорта:
|
|
12
|
+
|
|
13
|
+
| provider | Backend | Транспорт |
|
|
14
|
+
| --------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
15
|
+
| `relay-v1-http` | Relay v1 (`/api/v1`, project-scoped routes) | HTTP, `src/integrations/relay-v1` |
|
|
16
|
+
| `relay-v2-cli` | Relay-2 | subprocess CLI (`--format json`, явные `--config`/`--project`/`--actor`), `src/integrations/relay-v2` |
|
|
17
|
+
|
|
18
|
+
Provider выбирается **только явно** в конфигурации — никогда по имени
|
|
19
|
+
бинарника `relay`. Базы v1 и v2 не взаимозаменяемы, миграции истории нет.
|
|
20
|
+
|
|
21
|
+
## Пользовательский путь
|
|
22
|
+
|
|
23
|
+
Все шаги — команды CLI; TypeScript писать не нужно.
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
# 1. Настроить: connector.json (см. «Конфигурация») и policy.json harness.
|
|
27
|
+
|
|
28
|
+
# 2. Проверить подключение, проект, capabilities и mapping — только чтение:
|
|
29
|
+
# ни мутаций, ни записи истории, ни создания состояния.
|
|
30
|
+
npx harness source-check --source connector.json --policy policy.json --state ../state
|
|
31
|
+
|
|
32
|
+
# 3. Прочитать и закрепить снимок задач: graph.json, context.json, manifest.json.
|
|
33
|
+
npx harness source-snapshot --source connector.json --policy policy.json --state ../state --out ../snapshot
|
|
34
|
+
|
|
35
|
+
# 4. Обычное согласование (approvalMode: operator) — по файлам снимка.
|
|
36
|
+
npx harness review-plan --state ../state --policy policy.json --source connector.json \
|
|
37
|
+
--graph ../snapshot/graph.json --context ../snapshot/context.json --author external
|
|
38
|
+
npx harness approve --state ../state --subject <graphId> --digest <graphDigest>
|
|
39
|
+
# С --source внешние предпосылки (зависимости, выполненные через этот
|
|
40
|
+
# коннектор) допускаются по решению источника (trusts) и доступности SHA в
|
|
41
|
+
# target ref — те же правила, что у run; без --source доверенных receipt нет.
|
|
42
|
+
# В approvalMode: agent ревью плана выполняется в шаге 5 автоматически.
|
|
43
|
+
|
|
44
|
+
# 5. Запуск: задачи перечитываются, semantic digest сверяется с закреплённым
|
|
45
|
+
# снимком, eligibility проверяется — всё до любого вызова runtime.
|
|
46
|
+
# Принятый результат доставляется в исходную задачу.
|
|
47
|
+
npx harness run --source connector.json --policy policy.json --state ../state
|
|
48
|
+
|
|
49
|
+
# 6. Локальный и внешний статус: принято / доставлено / конфликт / неизвестный
|
|
50
|
+
# исход и независимое чтение получателя.
|
|
51
|
+
npx harness source-status --source connector.json --state ../state
|
|
52
|
+
|
|
53
|
+
# 7. Повтор или продолжение доставки — с тем же ключом операции; writer,
|
|
54
|
+
# reviewer, gates и Git не вызываются.
|
|
55
|
+
npx harness source-deliver --source connector.json --state ../state [--work <workId>]
|
|
56
|
+
|
|
57
|
+
# 8. Разбор неизвестного исхода или конфликта (см. «Восстановление»).
|
|
58
|
+
npx harness source-reconcile --source connector.json --state ../state \
|
|
59
|
+
--operation <key> [--decision resend|adopt:<id>|recheck]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`<graphId>`, `<graphDigest>`, ключи операций и ID поручений выводят
|
|
63
|
+
`source-snapshot` и `source-status` (JSON в stdout). Exit codes как у всего
|
|
64
|
+
CLI: 0 — успех, 2 — неверный вход, 3 — отказ/блокировка (в том числе
|
|
65
|
+
`uncertain`/`conflict` доставки и непройденная проверка), 4 — инфраструктура
|
|
66
|
+
(backend недоступен).
|
|
67
|
+
|
|
68
|
+
## Конфигурация
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"version": 1,
|
|
73
|
+
"provider": "relay-v1-http",
|
|
74
|
+
"relay": { "endpoint": "http://127.0.0.1:4700" },
|
|
75
|
+
"projectId": "AbCd1234",
|
|
76
|
+
"actor": "harness-controller",
|
|
77
|
+
"repository": { "id": "app" },
|
|
78
|
+
"tasks": [
|
|
79
|
+
{
|
|
80
|
+
"ref": "PRODUCT-3",
|
|
81
|
+
"role": "developer",
|
|
82
|
+
"writeScope": ["apps/api/src", "packages/sdk/src"],
|
|
83
|
+
"gates": ["unit"],
|
|
84
|
+
"criteria": [
|
|
85
|
+
{ "title": "API returns displayName", "gate": "unit", "testId": "api.user.displayName" },
|
|
86
|
+
{ "id": "Ab3dE6gH", "gate": "typecheck", "evidence": "gate" }
|
|
87
|
+
],
|
|
88
|
+
"requiredDocuments": ["Spec"]
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"completion": { "mode": "complete", "historicalComment": false },
|
|
92
|
+
"eligibility": { "columns": ["ready", "in-progress"] },
|
|
93
|
+
"limits": {
|
|
94
|
+
"documents": 20,
|
|
95
|
+
"documentBytes": 262144,
|
|
96
|
+
"totalBytes": 4194304,
|
|
97
|
+
"taskBytes": 1048576,
|
|
98
|
+
"rereads": 3,
|
|
99
|
+
"leaseMs": 120000
|
|
100
|
+
},
|
|
101
|
+
"history": { "enabled": true, "client": "devcontour-harness" }
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
| Поле | Смысл |
|
|
106
|
+
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
107
|
+
| `provider` | `relay-v1-http` или `relay-v2-cli`; только явно |
|
|
108
|
+
| `relay` | Настройки адаптера. v1: `endpoint` (+ `timeoutMs`, `maxResponseBytes`). v2: `binary`, `config` (относительно файла конфигурации), `project?` (workspace), `env?` (например `RELAY_HOME`, на macOS `DYLD_LIBRARY_PATH`), `timeoutMs`, `maxOutputBytes`, `build?`. `projectId`/`actor` берутся из верхнего уровня |
|
|
109
|
+
| `projectId` | Ожидаемая идентичность проекта backend; несовпадение блокирует чтение снимка и любые мутации |
|
|
110
|
+
| `actor` | Автор всех записей коннектора |
|
|
111
|
+
| `stateDir` | Каталог состояния коннектора (относительно файла); без него — `--state` |
|
|
112
|
+
| `repository` | ID репозитория политики (и путь для сверки) |
|
|
113
|
+
| `tasks[]` | Задачи: `ref` (постоянный ID или ключ), роль, `writeScope`, `gates`, сопоставление критериев, обязательные документы |
|
|
114
|
+
| `tasks[].criteria[]` | Критерий (`id` или точный `title`) → `gate` и `testId` JUnit; `evidence: "gate"` — достаточно прошедшего gate (явный выбор) |
|
|
115
|
+
| `completion` | `complete` — закрыть по правилам backend (по умолчанию в `done`); `review-only` — перевести в `review`/`column` и оставить человеку; `historicalComment` — при конфликте постановки записать явно исторический комментарий |
|
|
116
|
+
| `eligibility.columns` | Колонки, из которых задача допускается к запуску (`done`/`cancelled` — никогда) |
|
|
117
|
+
| `limits` | Пределы документов и постановки, число повторных чтений, срок владения доставкой |
|
|
118
|
+
| `history` | Запись истории работы (корневая и дочерние сессии) |
|
|
119
|
+
|
|
120
|
+
### Идентичность и снимок
|
|
121
|
+
|
|
122
|
+
- Идентичность задачи — `<provider>:<projectId>:<постоянный ID>`; ID поручения
|
|
123
|
+
и графа — хэш от неё. Одинаковые номера задач разных проектов/backend не
|
|
124
|
+
совпадают; смена cwd на worktree идентичность не меняет.
|
|
125
|
+
- `SourceRef.revision` — **semantic digest** постановки: текст, определения
|
|
126
|
+
критериев (без отметок выполнения), зависимости, подзадачи, значимые
|
|
127
|
+
документы и digest mapping. Колонка, свой in-progress, комментарии, история
|
|
128
|
+
и отметки критериев в него не входят. CAS-ревизии backend, токены
|
|
129
|
+
согласованности чтения и идентичность сборки хранятся только в manifest
|
|
130
|
+
снимка (никогда в поле Git SHA).
|
|
131
|
+
- Чтение — раундами по всем задачам; снимок принимается, когда два раунда
|
|
132
|
+
подряд совпали токенами и содержимым. Изменения — не больше `rereads`
|
|
133
|
+
повторов, затем явный отказ `NOT_READY`; ошибка сети/CLI — отказ, а не
|
|
134
|
+
пустая доска.
|
|
135
|
+
- Обязательное содержимое (текст постановки, критерии, `requiredDocuments`)
|
|
136
|
+
не усекается: превышение предела блокирует запуск с причиной и пределом.
|
|
137
|
+
Дополнительные документы усекаются с явной отметкой в начале файла и в
|
|
138
|
+
manifest (`truncated`) либо опускаются с записью в `missing` снимка.
|
|
139
|
+
- Eligibility проверяется отдельно от digest: `done`/`cancelled`, колонка вне
|
|
140
|
+
`eligibility.columns`, незавершённая зависимость, зависимость в `done` без
|
|
141
|
+
receipt этого коннектора. Колонка, в которую задачу перевела наша
|
|
142
|
+
подтверждённая доставка той же постановки, повтор не блокирует.
|
|
143
|
+
- Статус `done` зависимости — не доказательство: предпосылка зависимой
|
|
144
|
+
задачи появляется только из receipt доставки этого коннектора (издатель —
|
|
145
|
+
ID коннектора, digest сверяется с его состоянием), и движок дополнительно
|
|
146
|
+
проверяет доступность result SHA в target ref.
|
|
147
|
+
|
|
148
|
+
## Доставка: протокол и гарантии
|
|
149
|
+
|
|
150
|
+
Ключ операции — `sha256(provider, projectId, workId, runId, resultDigest)`.
|
|
151
|
+
|
|
152
|
+
1. **Intent до вызова.** Операция записывается в состояние коннектора до
|
|
153
|
+
первого внешнего вызова. Не удалось записать — мутация не отправляется.
|
|
154
|
+
2. **Сверка перед мутацией.** Задача перечитывается: изменился semantic
|
|
155
|
+
digest или задача отменена/закрыта другим — `conflict`; результат остаётся
|
|
156
|
+
привязан к своему снимку и SHA, текущая задача не закрывается (по
|
|
157
|
+
`historicalComment` — один явно исторический комментарий).
|
|
158
|
+
3. **Шаги**, каждый записан до и после вызова: комментарий с маркером
|
|
159
|
+
`<!-- devcontour-harness:op=<key>:step=<n> -->`; отметки сопоставленных
|
|
160
|
+
критериев с CAS; перемещение с CAS; закрытие истории. Критерий отмечается
|
|
161
|
+
только по mapping на прошедший в integration gate/testcase принятого
|
|
162
|
+
результата; ручные критерии, непрошедший testcase, незавершённые
|
|
163
|
+
подзадачи и зависимости оставляют задачу незавершённой.
|
|
164
|
+
Перед **каждым** неподтверждённым шагом (в том числе при продолжении
|
|
165
|
+
после обрыва или перезапуска) задача перечитывается: постановка обязана
|
|
166
|
+
совпасть со снимком результата, задача — не быть отменённой или закрытой
|
|
167
|
+
другим, а для нового CAS-шага текущая ревизия — равняться ревизии,
|
|
168
|
+
записанной после **нашего** предыдущего шага. Иначе — `conflict`, и
|
|
169
|
+
изменённая задача старым результатом не закрывается.
|
|
170
|
+
4. **Неизвестный исход** (таймаут, обрыв ответа, падение процесса между
|
|
171
|
+
вызовом и записью итога) разбирается фактами получателя: комментарий — по
|
|
172
|
+
маркеру (ровно один — подтверждено); CAS-шаг — по состоянию и ревизии
|
|
173
|
+
(цель достигнута, ревизия ровно на 1 больше нашей и постановка та же —
|
|
174
|
+
подтверждено; цель достигнута, но ревизия или постановка ушли дальше —
|
|
175
|
+
`conflict`; ревизия прежняя — не применено; ревизия
|
|
176
|
+
сменилась без нашей записи — `conflict`). Ответ `conflict` получателя
|
|
177
|
+
никогда не лечится повтором старой команды по новой ревизии.
|
|
178
|
+
5. **Подтверждённый отказ ≠ неизвестный исход.** Структурный отказ
|
|
179
|
+
получателя (`refused`; `conflict` для записи без CAS — комментария;
|
|
180
|
+
`unavailable` до отправки) означает, что мутации не было: шаг остаётся
|
|
181
|
+
`planned`, доставка — `failed` с причиной «подтверждённый отказ
|
|
182
|
+
получателя», повтор `source-deliver` безопасен (тот же маркер). Класс
|
|
183
|
+
ответа задаёт адаптер: 5xx/ненулевой exit без доказательства отката для
|
|
184
|
+
мутации адаптер сообщает как `uncertain`, и тогда действует п. 6.
|
|
185
|
+
6. **`uncertain`.** Если исход доказать нельзя (0 маркеров после возможной
|
|
186
|
+
отправки, больше одного, read-back недоступен), операция получает
|
|
187
|
+
`uncertain` (событие `delivery.uncertain` с ключом операции), повторная
|
|
188
|
+
доставка ничего не отправляет до `source-reconcile`.
|
|
189
|
+
7. **Receipt.** После подтверждения всех шагов сохраняется receipt (ID
|
|
190
|
+
комментария, критерии, колонка, ревизия, сессии истории); для принятого
|
|
191
|
+
результата — доверенный receipt для зависимых задач.
|
|
192
|
+
|
|
193
|
+
Повторная доставка принятого результата не вызывает writer/reviewer, не
|
|
194
|
+
запускает gates и не меняет Git. Частично выполненная доставка продолжается
|
|
195
|
+
с первого неподтверждённого шага без повтора append-only записей.
|
|
196
|
+
|
|
197
|
+
### Один владелец доставки
|
|
198
|
+
|
|
199
|
+
Владение операцией — lease с токеном, сроком и fencing в SQLite состояния
|
|
200
|
+
коннектора (`BEGIN IMMEDIATE`). Живой владелец продлевает lease и во время
|
|
201
|
+
долгого вызова; второй процесс над тем же каталогом получает
|
|
202
|
+
`CONTROLLER_BUSY` и ничего не отправляет. Упавшего владельца можно
|
|
203
|
+
перехватить только после истечения срока, intent при этом не теряется;
|
|
204
|
+
каждая запись проверяет lease в той же транзакции, поэтому процесс,
|
|
205
|
+
потерявший владение, больше ничего не записывает. Срок `limits.leaseMs`
|
|
206
|
+
должен превышать таймаут одного вызова транспорта.
|
|
207
|
+
|
|
208
|
+
**Граница гарантии:** она действует только для процессов, разделяющих один
|
|
209
|
+
каталог состояния коннектора. Независимые установки с разными каталогами
|
|
210
|
+
состояния вне гарантии и могут доставить одну операцию дважды —
|
|
211
|
+
`source-check` и `source-status` показывают это в `ownership`. Distributed
|
|
212
|
+
lock в этой версии не реализован.
|
|
213
|
+
|
|
214
|
+
### Что гарантируется, а что нет
|
|
215
|
+
|
|
216
|
+
Доказывается тестами (`tests/connector-*.test.ts`, общий набор
|
|
217
|
+
`connectorSuite`):
|
|
218
|
+
|
|
219
|
+
- одна подтверждённая доставка — один комментарий с маркером, без повторных
|
|
220
|
+
эффектов критериев и истории, в том числе после перезапуска процесса;
|
|
221
|
+
- обрыв до отправки — безопасный повтор; запись получателем без ответа —
|
|
222
|
+
read-back без дубля; ответ без сохранённого receipt — без новых мутаций;
|
|
223
|
+
отказ записи intent — без мутации;
|
|
224
|
+
- неизвестный исход не объявляется успехом и не повторяется автоматически;
|
|
225
|
+
- старая постановка не закрывает новую; чужое изменение между сверкой и CAS —
|
|
226
|
+
конфликт без повтора;
|
|
227
|
+
- два процесса не отправляют одну операцию одновременно.
|
|
228
|
+
|
|
229
|
+
**Не гарантируется:** distributed exactly-once — у получателя нет
|
|
230
|
+
идемпотентности по `requestId` (Relay v1 явно её не обещает, у Relay-2 её
|
|
231
|
+
нет), а Git и Relay не образуют общей транзакции. Неоднозначные случаи
|
|
232
|
+
решает оператор.
|
|
233
|
+
|
|
234
|
+
### Восстановление (`source-reconcile`)
|
|
235
|
+
|
|
236
|
+
Сначала проверяются факты получателя; решение оператора нужно только там,
|
|
237
|
+
где факты неоднозначны.
|
|
238
|
+
|
|
239
|
+
| Ситуация | Что видно | Действие |
|
|
240
|
+
| ----------------------------------------------------------------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
241
|
+
| Запись прошла, ответ потерян | маркер найден ровно один | `source-reconcile --operation <key>` — подтверждение по факту, доставка продолжается |
|
|
242
|
+
| Read-back был недоступен | `uncertain`, причина «read-back недоступен» | повторить `source-reconcile` после восстановления доступа |
|
|
243
|
+
| Таймаут, маркера нет | 0 маркеров | проверить получателя; если записи нет — `--decision resend` (тот же маркер) |
|
|
244
|
+
| Несколько записей с маркером | N > 1 | выбрать одну: `--decision adopt:<commentId>`; первая найденная не выбирается автоматически |
|
|
245
|
+
| CAS-конфликт без изменения постановки (например, сдвиг ранга соседней задачей в v1) | `conflict` | `--decision recheck`: постановка перечитывается, при совпадении digest шаг продолжается от новой ревизии |
|
|
246
|
+
| Постановка изменилась | `conflict`, `matchesSnapshot: false` | результат остаётся историческим; новый `source-snapshot` → согласование → `run --source` |
|
|
247
|
+
|
|
248
|
+
## История работы
|
|
249
|
+
|
|
250
|
+
При включённой истории (`history.enabled`):
|
|
251
|
+
|
|
252
|
+
- до исполнения попытки (до вызова writer) — корневая сессия поручения с
|
|
253
|
+
intent, затем fork дочерней сессии попытки, attach и её intent. Ошибка
|
|
254
|
+
записи intent — отказ окружения: попытка не начинается;
|
|
255
|
+
- отказ попытки — отмена дочерней сессии; доставка результата — checkpoint с
|
|
256
|
+
SHA и сводкой gates, завершение и приём дочерней, завершение корня (или
|
|
257
|
+
отмена при непринятом результате);
|
|
258
|
+
- каждая запись несёт маркер; после перезапуска controller шаги разбираются
|
|
259
|
+
read-back (`findSessions`, `checkpoints`, ревизия сессии) — без дублей;
|
|
260
|
+
записи прерванной попытки только подтверждаются фактами и отменяются;
|
|
261
|
+
- ревизия сессии и run backend — fencing: если сессию перехватил другой
|
|
262
|
+
владелец, устаревший run её не завершает (`conflict`);
|
|
263
|
+
- ID сессии/run backend, sessionId runtime и lease token попытки — разные
|
|
264
|
+
значения; lease token и полный runtime log в историю не пишутся.
|
|
265
|
+
|
|
266
|
+
## В Relay уходит
|
|
267
|
+
|
|
268
|
+
Краткий итог: исход, проверяемые SHA (candidate, integration/result), target
|
|
269
|
+
ref, сводка gates (без журналов), таблица критериев → gate/testcase →
|
|
270
|
+
результат, semantic digest и CAS-ревизия снимка. Локальные пути заменяются
|
|
271
|
+
пометкой (они не ссылки для другого компьютера), значения секретов политики
|
|
272
|
+
маскируются, полный runtime log и вызовы инструментов не копируются.
|
|
273
|
+
|
|
274
|
+
## Маскирование секретов
|
|
275
|
+
|
|
276
|
+
Ошибки транспорта (тело ответа HTTP, stderr CLI) маскируются до того, как
|
|
277
|
+
попадут в отчёт `source-check`, `source-status`, ошибки снимка, причины
|
|
278
|
+
шагов и операций в состоянии коннектора, `lastError` доставки, отказ записи
|
|
279
|
+
истории и вывод CLI. Маскируются значения секретов политики на любом уровне
|
|
280
|
+
(`environment.secrets` политики, репозиториев и tool profiles — по
|
|
281
|
+
окружению controller; для `source-snapshot` укажите `--policy`, иначе
|
|
282
|
+
используется политика каталога состояния) и значения настроек provider с
|
|
283
|
+
именем вида `*TOKEN*`, `*SECRET*`, `*PASSWORD*`, `*KEY*`.
|
|
284
|
+
|
|
285
|
+
## Состояние коннектора
|
|
286
|
+
|
|
287
|
+
`<stateDir>/connectors/<provider>-<hash(projectId)>.sqlite` — отдельная от
|
|
288
|
+
`state.sqlite` база: снимки (manifest и digest), операции доставки (intent,
|
|
289
|
+
шаги, receipt), lease, связи с историей. Это не состояние исполнения: оно
|
|
290
|
+
остаётся единственным — в `state.sqlite` harness.
|
|
291
|
+
|
|
292
|
+
## Библиотека и договор адаптера
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
import { openConnector } from 'devcontour-harness/integrations/connector';
|
|
296
|
+
|
|
297
|
+
const connector = await openConnector('connector.json', { stateDir: '../state' });
|
|
298
|
+
const h = Harness.open({ stateDir: '../state', policy, baseDir, hooks: connector.hooks() });
|
|
299
|
+
await connector.snapshot('../snapshot');
|
|
300
|
+
await connector.run(h, { author: 'external' });
|
|
301
|
+
await connector.status(h);
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Модуль адаптера (`src/integrations/<adapter>/index.ts`) экспортирует
|
|
305
|
+
`createTransport(settings, options?)` и возвращает `RelayTransport`
|
|
306
|
+
(`src/integrations/connector/transport.ts`). `settings` — объект `relay`
|
|
307
|
+
конфигурации, дополненный `projectId` и `actor` верхнего уровня; для
|
|
308
|
+
`relay-v2-cli` пути `binary` и `config` уже абсолютные (разрешены от каталога
|
|
309
|
+
файла конфигурации). Неверные настройки — `HarnessError('INVALID_INPUT')`.
|
|
310
|
+
|
|
311
|
+
### Общий набор проверки адаптера
|
|
312
|
+
|
|
313
|
+
`src/integrations/connector/testing.ts` содержит подделку backend
|
|
314
|
+
(`FakeRelayTransport`, fixture), обёртку точек отказа `faultyTransport` для
|
|
315
|
+
любого транспорта, барьеры (`LocalBarrier`, `FileBarrier`) и общий набор
|
|
316
|
+
`connectorSuite(backend)` — W02–W05, D01–D06, R04. Backend набора
|
|
317
|
+
(`SuiteBackend`) создаёт изолированный проект (`project()`), даёт транспорт,
|
|
318
|
+
действия «другого участника» (`admin`) и способ воссоздать транспорт в новом
|
|
319
|
+
процессе (`worker: { kind: 'config' }` — через `createTransportFor`).
|
|
320
|
+
Crash/restart и гонки выполняются в отдельных процессах
|
|
321
|
+
(`testing-worker.ts`) над тем же каталогом состояния. <!-- repo-only -->Набор на подделке —
|
|
322
|
+
`tests/connector-suite.test.ts`; на настоящих Relay v1/Relay-2 —
|
|
323
|
+
`tests/integration/*.test.ts` (репозиторий harness).<!-- /repo-only -->
|
package/docs/contracts.md
CHANGED
|
@@ -103,6 +103,7 @@ result SHA доступен в target ref.
|
|
|
103
103
|
| `toolProfiles{}`, `environment`, `lifecycle`, `resources[]` | Инструменты (у профиля — встроенные инструменты claude, shell и сеть codex, MCP-серверы `mcp{}`: stdio-команда или http-адрес, только перечисленные `tools`, учётные данные — именами переменных `env`/`bearerTokenEnv`, передаются CLI по имени), среда, ресурсы (порты 1024–65535) |
|
|
104
104
|
| `concurrency`, `leaseMs`, `runTimeoutMs`, `reviewProbes` | Пределы исполнения |
|
|
105
105
|
| `maxAttempts`, `repairBudget`, `reuseImplementation` | Повторы и повторное использование кандидата |
|
|
106
|
+
| `reviewProtocolRetries` | Необязательное: дополнительные вызовы reviewer кода при ошибке протокола ответа (0–2; нет поля — 1, умолчание не подставляется и digest политики не меняет), [review-protocol.md](review-protocol.md) |
|
|
106
107
|
| `budgets{work, group, total, onUnknown}`, `prices[]` | Пределы USD и/или времени; тарифы |
|
|
107
108
|
|
|
108
109
|
Переменные `HARNESS_*` и `DEVCONTOUR_*` политика задать не может.
|
|
@@ -211,7 +212,17 @@ Runtime возвращает сырой ответ; движок разбира
|
|
|
211
212
|
а не самооценка writer. Reviewer называет состояние каждой прежней открытой
|
|
212
213
|
находки (`previous[]`); `reviewIssues` отклоняет `approved` при блокирующей
|
|
213
214
|
находке, в том числе прежней открытой, неназванную прежнюю находку и ссылку на
|
|
214
|
-
неизвестную. Идентичность находки — `findingId(subject, {rule, message})
|
|
215
|
+
неизвестную. Идентичность находки плана/контракта — `findingId(subject, {rule, message})`;
|
|
216
|
+
невалидный ответ раунд не применяет (переходы и новые находки не записываются).
|
|
217
|
+
|
|
218
|
+
Ревью кода ведёт историю находок поручения с ID, выданными controller
|
|
219
|
+
(`codeReviewHistory`, `checkCodeReview`): reviewer называет ровно один переход
|
|
220
|
+
каждой открытой находки, ошибка протокола (`REVIEW_PROTOCOL_INVALID`,
|
|
221
|
+
причина и путь поля, например `previous[0].id`) отделена от содержательного
|
|
222
|
+
отказа (`REVIEW_REJECTED`) и даёт ограниченный повтор только reviewer
|
|
223
|
+
(`reviewProtocolRetries`, 0–2, по умолчанию 1). Evidence ревью несёт
|
|
224
|
+
аддитивное поле `reviewRound`, находки — `id`/`status`, ссылки результата —
|
|
225
|
+
`review`. Правила — [docs/review-protocol.md](review-protocol.md).
|
|
215
226
|
|
|
216
227
|
## Выходы
|
|
217
228
|
|
|
@@ -282,7 +293,7 @@ Runtime возвращает сырой ответ; движок разбира
|
|
|
282
293
|
|
|
283
294
|
Подлинность SHA, деревьев, artifacts и записей (их наличие в Git и в
|
|
284
295
|
хранилище исполнителя) получатель не удостоверяет — это транспорт хоста.
|
|
285
|
-
Таблица — проверяемое утверждение:
|
|
296
|
+
Таблица — проверяемое утверждение: <!-- repo-only -->`tests/receipt-trust.test.ts`<!-- /repo-only --> по JSON
|
|
286
297
|
Schema строит подделку каждого поля (другое значение, удаление
|
|
287
298
|
необязательного поля, пустой массив, повтор и удаление элемента) на двух
|
|
288
299
|
фикстурах и требует отказа для первых двух категорий и того же вердикта для
|
|
@@ -386,6 +397,20 @@ Schema строит подделку каждого поля (другое зн
|
|
|
386
397
|
| `evidence[].reviewer.runtime` | ожидание получателя | reviewer роли в политике получателя |
|
|
387
398
|
| `evidence[].reviewer.model` | сведение | модель reviewer |
|
|
388
399
|
| `evidence[].reviewer.sameVendor` | согласованность | вендоры writer и reviewer |
|
|
400
|
+
| `evidence[].review` | сведение | раунд протокола ревью кода |
|
|
401
|
+
| `evidence[].review.round` | сведение | раунд протокола ревью кода |
|
|
402
|
+
| `evidence[].review.call` | сведение | раунд протокола ревью кода |
|
|
403
|
+
| `evidence[].review.protocol` | сведение | раунд протокола ревью кода |
|
|
404
|
+
| `evidence[].review.issues` | сведение | раунд протокола ревью кода |
|
|
405
|
+
| `evidence[].review.issues[]` | сведение | раунд протокола ревью кода |
|
|
406
|
+
| `evidence[].review.issues[].path` | сведение | раунд протокола ревью кода |
|
|
407
|
+
| `evidence[].review.issues[].reason` | сведение | раунд протокола ревью кода |
|
|
408
|
+
| `evidence[].review.issues[].message` | сведение | раунд протокола ревью кода |
|
|
409
|
+
| `evidence[].review.transitions` | сведение | раунд протокола ревью кода |
|
|
410
|
+
| `evidence[].review.transitions[]` | сведение | раунд протокола ревью кода |
|
|
411
|
+
| `evidence[].review.transitions[].id` | сведение | раунд протокола ревью кода |
|
|
412
|
+
| `evidence[].review.transitions[].from` | сведение | раунд протокола ревью кода |
|
|
413
|
+
| `evidence[].review.transitions[].to` | сведение | раунд протокола ревью кода |
|
|
389
414
|
| `findings` | сведение | сводка находок может относиться к отклонённым раундам |
|
|
390
415
|
| `findings[]` | сведение | сводка находок |
|
|
391
416
|
| `findings[].severity` | сведение | сводка находок |
|
|
@@ -393,6 +418,8 @@ Schema строит подделку каждого поля (другое зн
|
|
|
393
418
|
| `findings[].path` | сведение | сводка находок |
|
|
394
419
|
| `findings[].line` | сведение | сводка находок |
|
|
395
420
|
| `findings[].rule` | сведение | сводка находок |
|
|
421
|
+
| `findings[].id` | сведение | сводка находок |
|
|
422
|
+
| `findings[].status` | сведение | сводка находок |
|
|
396
423
|
| `limitations` | сведение | чего результат не доказывает |
|
|
397
424
|
| `limitations[]` | сведение | чего результат не доказывает |
|
|
398
425
|
| `finishedAt` | сведение | время окончания |
|
|
@@ -479,8 +506,9 @@ manifestDigest, impact?, evidence[], error?}`. Смена любого SHA де
|
|
|
479
506
|
(`implementation`, `<фаза>-test:<gate>`, `<фаза>-consumer:<репозиторий>:<gate>`,
|
|
480
507
|
`<фаза>-review`, `<фаза>-environment:<шаг>`, `integration-wait`) и сохраняет
|
|
481
508
|
снимок контекста артефактом `implementation/context.json`. Отказ приёмки с
|
|
482
|
-
кодом `GATE_FAILED`, `REVIEW_REJECTED`, `
|
|
483
|
-
`BUDGET_EXHAUSTED` записывается классом отказа этого
|
|
509
|
+
кодом `GATE_FAILED`, `REVIEW_REJECTED`, `REVIEW_PROTOCOL_INVALID`,
|
|
510
|
+
`SCOPE_VIOLATION` или `BUDGET_EXHAUSTED` записывается классом отказа этого
|
|
511
|
+
правила.
|
|
484
512
|
|
|
485
513
|
Хост, ведущий движок поверх своего хранилища, собирает исполнение из
|
|
486
514
|
экспортов корня пакета: `Engine`, `Runner`, `WorkflowQueue`, `JointRunner`,
|
|
@@ -514,7 +542,7 @@ exit code CLI.
|
|
|
514
542
|
| 0 | успех | — |
|
|
515
543
|
| 2 | `input` | `INVALID_INPUT`, `UNSUPPORTED_COMMAND`, `UNSUPPORTED_VERSION`, `GRAPH_*`, `GATE_*`, `REVIEWER_*` |
|
|
516
544
|
| 3 | `refused` | `APPROVAL_STALE`, `APPROVAL_REQUIRED`, `LEASE_STALE`, `CONTROLLER_BUSY`, `PAUSED`, `NOT_READY`, `SCOPE_VIOLATION`, `GATE_FAILED`, `REVIEW_REJECTED`, `BUDGET_EXHAUSTED`, `BUDGET_UNKNOWN`, `ATTEMPTS_EXHAUSTED`, `REVISION_CONFLICT`, `CANCELLED`, `NOT_FOUND` |
|
|
517
|
-
| 4 | `infrastructure` | `STATE_VERSION_UNSUPPORTED`, `RUNTIME_UNAVAILABLE`, `SANDBOX_UNAVAILABLE`, `GIT_FAILED`, `STORAGE_FAILED`, `DELIVERY_FAILED`, `INTERNAL`
|
|
545
|
+
| 4 | `infrastructure` | `STATE_VERSION_UNSUPPORTED`, `RUNTIME_UNAVAILABLE`, `REVIEW_PROTOCOL_INVALID`, `SANDBOX_UNAVAILABLE`, `GIT_FAILED`, `STORAGE_FAILED`, `DELIVERY_FAILED`, `INTERNAL` |
|
|
518
546
|
|
|
519
547
|
Exit 1 не используется: им Node завершает процесс при необработанном
|
|
520
548
|
исключении.
|