devcontour-harness 0.0.0-stage → 0.1.0-alpha.5

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.
Files changed (197) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -2
  3. package/docs/architecture.md +473 -0
  4. package/docs/compatibility.md +192 -0
  5. package/docs/contracts.md +575 -0
  6. package/docs/quickstart.md +182 -0
  7. package/docs/upgrade.md +166 -0
  8. package/examples/README.md +26 -0
  9. package/examples/external-connector/README.md +19 -0
  10. package/examples/external-connector/connector.mjs +55 -0
  11. package/examples/files-only/README.md +28 -0
  12. package/examples/files-only/context/norms/rules.md +4 -0
  13. package/examples/files-only/graph.json +23 -0
  14. package/examples/files-only/policy.json +30 -0
  15. package/examples/one-vendor/README.md +19 -0
  16. package/examples/one-vendor/policy.json +27 -0
  17. package/examples/single-task/README.md +18 -0
  18. package/examples/single-task/graph.json +27 -0
  19. package/examples/single-task/policy-same-vendor.json +55 -0
  20. package/examples/single-task/policy.json +52 -0
  21. package/examples/single-task/src/.gitkeep +0 -0
  22. package/examples/single-task/test/run.js +19 -0
  23. package/examples/two-vendors/policy.json +30 -0
  24. package/lib/agents/cli-adapter.d.ts +48 -0
  25. package/lib/agents/cli-adapter.js +384 -0
  26. package/lib/agents/inspect.d.ts +6 -0
  27. package/lib/agents/inspect.js +46 -0
  28. package/lib/agents/probe-server.d.ts +2 -0
  29. package/lib/agents/probe-server.js +13 -0
  30. package/lib/agents/review-probe.d.ts +123 -0
  31. package/lib/agents/review-probe.js +279 -0
  32. package/lib/agents/runtime-events.d.ts +11 -0
  33. package/lib/agents/runtime-events.js +21 -0
  34. package/lib/agents/schemas.d.ts +215 -0
  35. package/lib/agents/schemas.js +120 -0
  36. package/lib/agents/usage.d.ts +8 -0
  37. package/lib/agents/usage.js +83 -0
  38. package/lib/cli.d.ts +2 -0
  39. package/lib/cli.js +331 -0
  40. package/lib/connectors/files.d.ts +108 -0
  41. package/lib/connectors/files.js +133 -0
  42. package/lib/contracts/checks.d.ts +307 -0
  43. package/lib/contracts/checks.js +181 -0
  44. package/lib/contracts/cli.d.ts +3086 -0
  45. package/lib/contracts/cli.js +425 -0
  46. package/lib/contracts/context.d.ts +135 -0
  47. package/lib/contracts/context.js +129 -0
  48. package/lib/contracts/digest.d.ts +9 -0
  49. package/lib/contracts/digest.js +22 -0
  50. package/lib/contracts/errors.d.ts +79 -0
  51. package/lib/contracts/errors.js +68 -0
  52. package/lib/contracts/events.d.ts +795 -0
  53. package/lib/contracts/events.js +249 -0
  54. package/lib/contracts/execution.d.ts +3048 -0
  55. package/lib/contracts/execution.js +864 -0
  56. package/lib/contracts/failure.d.ts +67 -0
  57. package/lib/contracts/failure.js +122 -0
  58. package/lib/contracts/index.d.ts +17 -0
  59. package/lib/contracts/index.js +17 -0
  60. package/lib/contracts/policy.d.ts +1065 -0
  61. package/lib/contracts/policy.js +534 -0
  62. package/lib/contracts/ports.d.ts +367 -0
  63. package/lib/contracts/ports.js +1 -0
  64. package/lib/contracts/primitives.d.ts +63 -0
  65. package/lib/contracts/primitives.js +73 -0
  66. package/lib/contracts/profiles.d.ts +322 -0
  67. package/lib/contracts/profiles.js +105 -0
  68. package/lib/contracts/published.d.ts +3014 -0
  69. package/lib/contracts/published.js +34 -0
  70. package/lib/contracts/result.d.ts +1109 -0
  71. package/lib/contracts/result.js +273 -0
  72. package/lib/contracts/review.d.ts +210 -0
  73. package/lib/contracts/review.js +153 -0
  74. package/lib/contracts/version.d.ts +17 -0
  75. package/lib/contracts/version.js +17 -0
  76. package/lib/contracts/work.d.ts +173 -0
  77. package/lib/contracts/work.js +178 -0
  78. package/lib/control/base-move.d.ts +44 -0
  79. package/lib/control/base-move.js +90 -0
  80. package/lib/control/doctor.d.ts +35 -0
  81. package/lib/control/doctor.js +71 -0
  82. package/lib/control/harness.d.ts +1079 -0
  83. package/lib/control/harness.js +714 -0
  84. package/lib/control/provenance.d.ts +17 -0
  85. package/lib/control/provenance.js +25 -0
  86. package/lib/control/recovery.d.ts +235 -0
  87. package/lib/control/recovery.js +236 -0
  88. package/lib/control/review.d.ts +62 -0
  89. package/lib/control/review.js +170 -0
  90. package/lib/control/workflow.d.ts +247 -0
  91. package/lib/control/workflow.js +259 -0
  92. package/lib/engine/budget.d.ts +345 -0
  93. package/lib/engine/budget.js +278 -0
  94. package/lib/engine/classify.d.ts +8 -0
  95. package/lib/engine/classify.js +31 -0
  96. package/lib/engine/engine.d.ts +1503 -0
  97. package/lib/engine/engine.js +2259 -0
  98. package/lib/engine/failure.d.ts +1 -0
  99. package/lib/engine/failure.js +3 -0
  100. package/lib/engine/joint-runner.d.ts +257 -0
  101. package/lib/engine/joint-runner.js +254 -0
  102. package/lib/engine/measured.d.ts +15 -0
  103. package/lib/engine/measured.js +82 -0
  104. package/lib/engine/prompt.d.ts +38 -0
  105. package/lib/engine/prompt.js +74 -0
  106. package/lib/engine/property-recovery.d.ts +50 -0
  107. package/lib/engine/property-recovery.js +169 -0
  108. package/lib/engine/repair.d.ts +33 -0
  109. package/lib/engine/repair.js +82 -0
  110. package/lib/engine/result.d.ts +9 -0
  111. package/lib/engine/result.js +166 -0
  112. package/lib/engine/reuse.d.ts +80 -0
  113. package/lib/engine/reuse.js +97 -0
  114. package/lib/engine/runner.d.ts +335 -0
  115. package/lib/engine/runner.js +1467 -0
  116. package/lib/engine/standalone.d.ts +6 -0
  117. package/lib/engine/standalone.js +48 -0
  118. package/lib/engine/usage.d.ts +87 -0
  119. package/lib/engine/usage.js +165 -0
  120. package/lib/environment/isolation.d.ts +110 -0
  121. package/lib/environment/isolation.js +238 -0
  122. package/lib/environment/lifecycle.d.ts +40 -0
  123. package/lib/environment/lifecycle.js +191 -0
  124. package/lib/environment/live-calls.d.ts +14 -0
  125. package/lib/environment/live-calls.js +72 -0
  126. package/lib/environment/process.d.ts +32 -0
  127. package/lib/environment/process.js +368 -0
  128. package/lib/environment/redaction.d.ts +22 -0
  129. package/lib/environment/redaction.js +102 -0
  130. package/lib/environment/resources.d.ts +31 -0
  131. package/lib/environment/resources.js +120 -0
  132. package/lib/index.d.ts +65 -0
  133. package/lib/index.js +67 -0
  134. package/lib/package.d.ts +2 -0
  135. package/lib/package.js +3 -0
  136. package/lib/profiles/resolve.d.ts +186 -0
  137. package/lib/profiles/resolve.js +242 -0
  138. package/lib/storage/document.d.ts +1186 -0
  139. package/lib/storage/document.js +80 -0
  140. package/lib/storage/sqlite.d.ts +35 -0
  141. package/lib/storage/sqlite.js +260 -0
  142. package/lib/testing/index.d.ts +5 -0
  143. package/lib/testing/index.js +5 -0
  144. package/lib/testing/store-contract.d.ts +8 -0
  145. package/lib/testing/store-contract.js +167 -0
  146. package/lib/validate.d.ts +36 -0
  147. package/lib/validate.js +175 -0
  148. package/lib/verification/acceptance.d.ts +268 -0
  149. package/lib/verification/acceptance.js +654 -0
  150. package/lib/verification/checks.d.ts +72 -0
  151. package/lib/verification/checks.js +190 -0
  152. package/lib/verification/confirm.d.ts +125 -0
  153. package/lib/verification/confirm.js +411 -0
  154. package/lib/verification/corpus.d.ts +1303 -0
  155. package/lib/verification/corpus.js +744 -0
  156. package/lib/verification/dependencies.d.ts +66 -0
  157. package/lib/verification/dependencies.js +144 -0
  158. package/lib/verification/gates.d.ts +144 -0
  159. package/lib/verification/gates.js +559 -0
  160. package/lib/verification/joint.d.ts +63 -0
  161. package/lib/verification/joint.js +121 -0
  162. package/lib/verification/proof.d.ts +54 -0
  163. package/lib/verification/proof.js +96 -0
  164. package/lib/verification/property.d.ts +86 -0
  165. package/lib/verification/property.js +214 -0
  166. package/lib/verification/requirements.d.ts +25 -0
  167. package/lib/verification/requirements.js +69 -0
  168. package/lib/verification/self-check.d.ts +29 -0
  169. package/lib/verification/self-check.js +99 -0
  170. package/lib/verification/spike.d.ts +79 -0
  171. package/lib/verification/spike.js +124 -0
  172. package/package.json +79 -4
  173. package/profiles/expo-mobile.json +15 -0
  174. package/profiles/go-api.json +15 -0
  175. package/profiles/mobile-maestro.json +29 -0
  176. package/profiles/nest-api.json +26 -0
  177. package/profiles/next-product.json +72 -0
  178. package/profiles/node-checks.json +77 -0
  179. package/profiles/python-api.json +32 -0
  180. package/profiles/react-native.json +50 -0
  181. package/profiles/react-vite-admin.json +71 -0
  182. package/schemas/context-snapshot.schema.json +231 -0
  183. package/schemas/contract-document.schema.json +385 -0
  184. package/schemas/execution-document.schema.json +3540 -0
  185. package/schemas/execution-policy.schema.json +2148 -0
  186. package/schemas/joint-verification.schema.json +617 -0
  187. package/schemas/result-envelope.schema.json +1440 -0
  188. package/schemas/review-record.schema.json +177 -0
  189. package/schemas/run-event.schema.json +2365 -0
  190. package/schemas/run-result.schema.json +1363 -0
  191. package/schemas/stack-profile.schema.json +492 -0
  192. package/schemas/work-graph.schema.json +381 -0
  193. package/schemas/work-order.schema.json +256 -0
  194. package/skills/harness/SKILL.md +64 -0
  195. package/templates/AGENTS.md +13 -0
  196. package/templates/graph.json +22 -0
  197. package/templates/policy.json +28 -0
@@ -0,0 +1,192 @@
1
+ # Совместимость форматов
2
+
3
+ Harness выделен из DevContour. Первая миграция DevContour на пакет **не
4
+ переносит данные**: состояние остаётся в прежнем хранилище, а адаптер
5
+ отображает существующие записи в нейтральные структуры в той же транзакции.
6
+ Ниже — как устроен адаптер, что сохраняется байт-в-байт и что меняется
7
+ намеренно.
8
+
9
+ ## Транзакции адаптера DevContour
10
+
11
+ DevContour хранит состояние одним JSON-документом в SQLite (`node:sqlite`) —
12
+ в центральной базе или распределённо по базам компонентов, присоединённым к
13
+ coordinator. `Store.change(type, fn)` открывает `BEGIN IMMEDIATE` (вложенный
14
+ `Store.atomic` — SAVEPOINT), читает документ, вызывает `fn`, записывает
15
+ документ целиком и вставляет событие журнала с `data` = возвращённым `fn`
16
+ значением (кроме `heartbeat`).
17
+
18
+ Адаптер `ExecutionStore`:
19
+
20
+ 1. **Внешняя транзакция** — `Store.atomic` с ровно одной `Store.change(kind, …)`
21
+ внутри. Документ, прочитанный ею, — текущий документ транзакции;
22
+ `ExecutionView` и `put*` читают и пишут его объекты (`Task`, `Run`, поля
23
+ управления), `putLocal` — `Store.saveLocal` той же транзакции.
24
+ 2. **Вложенная транзакция** не вызывает второй `Store.change`: она работает с
25
+ тем же документом внутри `Store.atomic` (SAVEPOINT для локальных записей).
26
+ Перед ней адаптер снимает копию документа и **всего журнального буфера**
27
+ (нейтральные события и legacy-данные); при исключении восстанавливает их на
28
+ месте. Изменения вложенной и внешней сохраняются обе — прямой вложенный
29
+ `Store.change` этого не обеспечивает: внешний снимок перезаписал бы
30
+ внутреннее изменение.
31
+ 3. **Журнал.** Возвращённое движком значение в журнал не идёт. Адаптер
32
+ записывает в `data` события прежнюю форму данных этого типа (для типов,
33
+ чьи данные читают хост и его экраны: `scheduler.error` → `{error}` и т. д.)
34
+ **без полей `token` на любой глубине** и добавляет ключ `harnessEvents` —
35
+ нейтральные события транзакции по порядку.
36
+ 4. **Событие без изменения документа.** `Store.change` не пишет событие, если
37
+ документ не изменился (транзакция только с `emit` или только с локальной
38
+ записью и `emit`). Для этого DevContour получает аддитивный метод
39
+ `Store.appendEvent(type, data)` — вставка события в открытой транзакции тем
40
+ же путём, что у `Store.change` (central: `main.events`; component:
41
+ `components.event`), с ростом ревизии данных. Адаптер вызывает его, когда
42
+ `Store.change` события не записал, а у транзакции есть нейтральные
43
+ события. Изменения остальных методов `Store` не требуется.
44
+ Транзакции только локальных записей (`workflow.updated`, `usage.recorded`,
45
+ `checks.recorded`) и `base.moved` (проверка владения и сдвиг ref)
46
+ событий не создают: адаптер выполняет их как `Store.atomic` без
47
+ `Store.change`, как DevContour сейчас пишет учёт вызовов и очередь ведущего.
48
+ 5. **Курсор.** `seq` нейтрального события = `id события журнала × 1024 + индекс` (не больше 1024 событий на транзакцию — с запасом для графа из 500 поручений; больше — отказ транзакции).
49
+ `ExecutionStore.events(after)` строит `RunEvent` из `harnessEvents` строго
50
+ по возрастанию `seq`; события прежних версий без `harnessEvents` в
51
+ нейтральный поток не попадают и читаются хостом как раньше.
52
+ 6. Возврат Promise из `fn` отклоняется до записи.
53
+ 7. `heartbeat` — `Store.change('heartbeat', …)`: растёт только счётчик сроков,
54
+ события нет.
55
+ 8. Приёмка: CAS `git update-ref <target> <integration> <base>` выполняется
56
+ внутри внешней транзакции до фиксации (как сейчас `finish(…, publish)`).
57
+
58
+ Свойства подтверждены пробой поверх baseline `Store` (с эмуляцией
59
+ `appendEvent`): вложенное и внешнее изменения сохраняются; исключение
60
+ вложенной откатывает её документ, события и legacy-данные; исключение
61
+ внешней не оставляет ни изменений, ни события; транзакция только с событием
62
+ и транзакция «локальная запись + событие» фиксируются и откатываются целиком;
63
+ токенов в журнале нет; курсор отдаёт события по возрастанию и каждое проходит
64
+ схему `RunEvent`; Promise отклоняется; `putLocal` различает владельцев.
65
+
66
+ ### Локальные записи
67
+
68
+ `local_workflow(namespace, owner, key, data)` — та же таблица. `owner` —
69
+ репозиторий-компонент или `@workspace`. У хранения по компонентам запись
70
+ владельца-компонента живёт в базе компонента (`componentN.local_workflow`),
71
+ `@workspace` — в coordinator. Адаптер не меняет правило размещения и
72
+ проверяет запись схемой пространства при чтении и записи.
73
+
74
+ | Пространство harness | `namespace` DevContour | Запись |
75
+ | ------------------------------------------------------ | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
76
+ | `usage` | `usage` | `CallRecord` ↔ `UsageRecord` |
77
+ | `check-suites` | `check-suites` | `CheckSuite` (корпус: случаи, версии, решения, принятия, отложенные принятия, операции подтверждения под владением, CAS `revision`) |
78
+ | `workflow-jobs` | `lead` | `WorkflowJob` (техническая очередь ведущего: предмет, автор, digest входа, этап, попытки, ремонты, владение, история) |
79
+ | `context-snapshots`, `run-keys`, `delivery`, `reviews` | новые | Новые записи; прежних данных нет |
80
+ | `contract-documents` | — (`contracts` состояния) | Документ контракта по digest; адаптер отдаёт его из контрактов DevContour (`checks`, `artifacts`) и не пишет отдельно |
81
+ | `spikes` | `spikes` | `Spike` (эксперимент выполнимости: SHA, команда, seed, размеры, предел, исходы, пределы вывода, среда, digest) |
82
+ | `reproductions` | — (`reproductions` состояния) | `ReproductionRegistry` поручения ↔ `Reproduction[]` с `taskId`; адаптер группирует по задаче и сохраняет ограничение 500 |
83
+
84
+ Прочие пространства DevContour (`contract-change`, `signals`,
85
+ `projection`) — продуктовые; движок их не читает и не пишет.
86
+
87
+ ## Отображение записей
88
+
89
+ | Нейтральная запись | Запись DevContour | Правило |
90
+ | ------------------------ | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
91
+ | `WorkState` | `Task` (поля исполнения) | `status`, `attempt`, `activeRunId`, `resultSha`, `failure`, `failureKind`, `failureFingerprint`, `approvedAt`, `approvedDigest`, `approvedScope`, `approval`, `hold`, `budgetBlock`, `checkVersion`, `recovery`, `recoveryHistory` — те же имена и формы. `graphId` — доска, в активной ревизии которой задача |
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
+ | `AttemptState` | `Run` | Те же имена и формы, включая `context` (краткие pins), `consumers[].checked`, `partial`, `continuedFrom`, `dispatch`, `timings`; `taskId` ↔ `workId`; runtime `demo` ↔ `fixture` на границе (сохранённое значение не переписывается); `memory` остаётся полем `Run` хоста; `engineVersion`, `consumerVersion`, `contextSnapshot` — новые необязательные поля |
94
+ | `EvidenceRecord` | `Evidence` | Без изменений |
95
+ | `ControlState` | `paused`, `pauseReason`, `pausedAt`, `pauseOperation`, `pauseFailures`, `waits`, `appliedConfig`, `reconfigure` | Те же формы; `appliedConfig` ↔ `appliedPolicy` |
96
+ | `ControllerLease` | `leader` | Без изменений |
97
+ | `JointVerificationState` | `Verification` | `manifest`, `manifestDigest`, `policyDigest`, `specDigest`, `impact`, `evidence`, `token`, `leaseUntil`, `status` — те же формы; `tasks` → `workIds` (снимок задач остаётся в `Verification`); `boards`, `productRelease` — поля хоста |
98
+ | `CallRecord` | `UsageRecord` (`local_workflow` `usage`) | Те же поля; `taskId` ↔ `workId`, `boardId` ↔ `groupId`, `taskIds` ↔ `workIds` |
99
+ | `ReviewRecord` | — (у DevContour раундов в форме `ReviewRecord` нет) | Прежние `contractAttempts` в раунды **не** превращаются: в них нет digest предмета и признака того же вендора, а выдумывать их нельзя. Согласование контракта DevContour — утверждённая редакция контракта (`contracts[]` с её `digest` и `approvedAt`); движок получает его через порт `ExecutionHost.contracts` (`approved({id, digest})`), а не по раундам `reviews`. История `contractAttempts` остаётся продуктовой записью и читается DevContour как прежде |
100
+
101
+ Адаптер записывает только поля нейтральной модели и сохраняет остальные поля
102
+ записи хоста как есть; неизвестные поля не удаляются.
103
+
104
+ ## Основания, которые не пересчитываются
105
+
106
+ Формулы digest записаны в принятой истории и receipts. Движок их не вычисляет —
107
+ их даёт хост через `BasisProvider`:
108
+
109
+ - digest постановки задачи (включает продуктовые поля), digest области
110
+ проверок, digest контракта по своей формуле закрепления;
111
+ - digest политики задачи, включая прежний вариант для старых receipts.
112
+
113
+ Формулы действующей версии проверок, основания реализации, seed свойства,
114
+ digest манифеста свойств и ключа ресурса переносятся в пакет без изменения.
115
+ Pins контекста DevContour сохраняют свой digest (`hostDigest` → `ContextPin.digest`);
116
+ `sourceDigest` снимка считается harness отдельно.
117
+
118
+ Standalone-хост использует `digestOf` (SHA-256 канонического JSON) от
119
+ нейтральных структур; эти digests с digests DevContour не сравниваются.
120
+
121
+ ## Бюджеты
122
+
123
+ | Область harness | DevContour |
124
+ | --------------- | --------------------------- |
125
+ | `work` | задача |
126
+ | `group` | доска со всеми её ревизиями |
127
+ | `total` | workspace |
128
+
129
+ `BudgetScopes` DevContour: `groupOf` — доска задачи в текущем графе,
130
+ `members` — задачи всех ревизий доски, `legacy` — прежнее правило атрибуции
131
+ (задача по попытке или предмету вызова, доска по текущему графу) для записей
132
+ без закреплённых `taskId`/`boardId`/`taskIds`; результат закрепляется один
133
+ раз. Расход остаётся за доской, на которой он сделан, при переносе задачи.
134
+ Тариф выбирается по модели, о которой сообщил runtime (`RuntimeResponse.model`
135
+ → `CallRecord.model`), а не по модели из политики.
136
+
137
+ ## Reviewer
138
+
139
+ Автор плана и контракта задаётся вызовом ревью (`--author`; у DevContour —
140
+ `authorRuntime` задания ведущего, закреплённый за входом: повтор с другим
141
+ автором отклоняется). Автор вне harness — `external`; его вендор не совпадает
142
+ ни с одним runtime.
143
+
144
+ Правило ревью кода роли собирается адаптером по прежней цепочке
145
+ `role.reviewer` компонента → `repository.reviewer` → `config.reviewer`;
146
+ одноимённые роли разных компонентов не схлопываются (политика строится на
147
+ компонент). Прежнее требование «writer ≠ reviewer» — `different-vendor`.
148
+
149
+ ## Сохраняемые форматы
150
+
151
+ | Что | Правило |
152
+ | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
153
+ | Состояние `version: 1` | Читается как есть; иная версия отклоняется до записи |
154
+ | Типы событий журнала | Прежние строки, см. `transactionKinds` |
155
+ | Ветки | Целевая `devcontour/accepted` (в политике `refs/heads/devcontour/accepted`), ветки попыток `devcontour/run-<runId>` |
156
+ | Каталоги попыток | `worktrees/<runId>`, `worktrees/<runId>-integration`, `artifacts/<runId>/…`, `dependencies/<runId>/manifest.json` |
157
+ | Receipt среды | `environment.json` `version: 1` |
158
+ | Отчёт свойств, договор проверки, корпус | `version: 1` |
159
+ | Владение репозиторием | `<git-common-dir>/devcontour-owner.json` |
160
+ | Ресурсы | Отдельная база блокировок ресурсов `resources.sqlite`: блокировки устройств и портов, а не состояние исполнения |
161
+ | Probe ревьюера | MCP-сервер `devcontour_probe`, инструмент `run_check`; протокол — построчный JSON-RPC (stdio), журнал `probes.jsonl` |
162
+
163
+ ## Переменные окружения gates
164
+
165
+ Gates, шаги подготовки и проверки потребителей получают переменные с
166
+ историческим префиксом `DEVCONTOUR_`: `DEVCONTOUR_REPOSITORY_ID`,
167
+ `DEVCONTOUR_RUN_ID`, `DEVCONTOUR_TASK_ID`, `DEVCONTOUR_PHASE`,
168
+ `DEVCONTOUR_RESOURCES_JSON`, `DEVCONTOUR_DEPENDENCIES_JSON`,
169
+ `DEVCONTOUR_COMPONENTS_JSON`, `DEVCONTOUR_REPORT_PATH`, `DEVCONTOUR_SEED`,
170
+ `DEVCONTOUR_PROPERTY_REPORT`, `DEVCONTOUR_PROPERTIES`, `DEVCONTOUR_CORPUS`,
171
+ `DEVCONTOUR_CASE`, `DEVCONTOUR_CASE_RESULT`, `DEVCONTOUR_MANIFEST_PATH`,
172
+ `DEVCONTOUR_CHANGESET_ID`, `DEVCONTOUR_PROCESS_MARK`. Имена — часть договора
173
+ проверок пользователей, а не связь с хостом; harness сохраняет их и задаёт
174
+ `HARNESS_*` с теми же значениями. Оба пространства резервирует controller:
175
+ политика не может задать переменные с этими префиксами.
176
+
177
+ ## Что меняется намеренно
178
+
179
+ | Изменение | Следствие |
180
+ | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
181
+ | Версия движка в основании reuse | Попытка записывает `engineVersion` (и `consumerVersion`). Кандидат попытки другой версии движка повторно не используется: новая попытка заново проходит gates и ревью. Прежние попытки сохраняют своё основание; отсутствующая версия не выдумывается |
182
+ | Reviewer задаётся правилом | `different-vendor` по умолчанию; `same-vendor-allowed` включается явно |
183
+ | Токены вне журнала | Исправление утечки: прежде `run.claimed` и `run.recovered` записывали в журнал попытку целиком, с fencing-токеном. Новые события пишутся без токенов; при выдаче старых событий наружу (CLI, HTTP, RunEvent) токены удаляются. Историю базы физически не переписываем |
184
+ | История находок ревью | Reviewer называет состояние прежних находок; прежние попытки читаются без статусов |
185
+
186
+ ## Состояние standalone
187
+
188
+ Standalone SQLite хранит документ `execution-document` (`stateVersion: 1`),
189
+ события и локальные записи в одной базе и запись о версии писателя. Процесс
190
+ другой версии с несовместимым форматом не открывает базу на запись. Матрица
191
+ поддерживаемых переходов и порядок upgrade/rollback — в
192
+ [docs/upgrade.md](upgrade.md).