devcontour-harness 0.0.0-stage → 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.
Files changed (390) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +183 -2
  3. package/docs/architecture.md +473 -0
  4. package/docs/compatibility-versions.md +56 -0
  5. package/docs/compatibility.md +192 -0
  6. package/docs/connectors.md +323 -0
  7. package/docs/contracts.md +603 -0
  8. package/docs/integrations/hindsight.md +148 -0
  9. package/docs/quickstart.md +182 -0
  10. package/docs/release-notes/0.1.0-alpha.6.md +238 -0
  11. package/docs/review-probes.md +120 -0
  12. package/docs/review-protocol.md +251 -0
  13. package/docs/toolchains.md +167 -0
  14. package/docs/turbo-starter.md +269 -0
  15. package/docs/upgrade.md +202 -0
  16. package/examples/README.md +27 -0
  17. package/examples/external-connector/README.md +19 -0
  18. package/examples/external-connector/connector.mjs +55 -0
  19. package/examples/files-only/README.md +28 -0
  20. package/examples/files-only/context/norms/rules.md +4 -0
  21. package/examples/files-only/graph.json +23 -0
  22. package/examples/files-only/policy.json +30 -0
  23. package/examples/one-vendor/README.md +19 -0
  24. package/examples/one-vendor/policy.json +27 -0
  25. package/examples/single-task/README.md +18 -0
  26. package/examples/single-task/graph.json +27 -0
  27. package/examples/single-task/policy-same-vendor.json +55 -0
  28. package/examples/single-task/policy.json +52 -0
  29. package/examples/single-task/src/.gitkeep +0 -0
  30. package/examples/single-task/test/run.js +19 -0
  31. package/examples/toolchains/README.md +32 -0
  32. package/examples/toolchains/go/bad/label/label.go +9 -0
  33. package/examples/toolchains/go/good/label/label.go +9 -0
  34. package/examples/toolchains/go/policy.json +79 -0
  35. package/examples/toolchains/go/repo/REQUIREMENTS.md +9 -0
  36. package/examples/toolchains/go/repo/_gitignore +1 -0
  37. package/examples/toolchains/go/repo/go.mod +5 -0
  38. package/examples/toolchains/go/repo/go.sum +2 -0
  39. package/examples/toolchains/go/repo/label/label.go +9 -0
  40. package/examples/toolchains/go/repo/label/label_test.go +27 -0
  41. package/examples/toolchains/go/repo/label/version.go +9 -0
  42. package/examples/toolchains/go/task.json +25 -0
  43. package/examples/toolchains/mixed-go/bad/backend/label/label.go +9 -0
  44. package/examples/toolchains/mixed-go/bad/frontend/src/label.js +4 -0
  45. package/examples/toolchains/mixed-go/good/backend/label/label.go +9 -0
  46. package/examples/toolchains/mixed-go/good/frontend/src/label.js +4 -0
  47. package/examples/toolchains/mixed-go/policy.json +126 -0
  48. package/examples/toolchains/mixed-go/repo/REQUIREMENTS.md +9 -0
  49. package/examples/toolchains/mixed-go/repo/_gitignore +6 -0
  50. package/examples/toolchains/mixed-go/repo/backend/go.mod +3 -0
  51. package/examples/toolchains/mixed-go/repo/backend/label/label.go +9 -0
  52. package/examples/toolchains/mixed-go/repo/backend/label/label_test.go +30 -0
  53. package/examples/toolchains/mixed-go/repo/contract/check.mjs +17 -0
  54. package/examples/toolchains/mixed-go/repo/contract/label.json +9 -0
  55. package/examples/toolchains/mixed-go/repo/frontend/package.json +15 -0
  56. package/examples/toolchains/mixed-go/repo/frontend/pnpm-lock.yaml +22 -0
  57. package/examples/toolchains/mixed-go/repo/frontend/src/label.js +4 -0
  58. package/examples/toolchains/mixed-go/repo/frontend/test/label.test.js +11 -0
  59. package/examples/toolchains/mixed-go/task.json +25 -0
  60. package/examples/toolchains/mixed-python/bad/backend/src/fx_backend/__init__.py +6 -0
  61. package/examples/toolchains/mixed-python/bad/frontend/src/label.js +4 -0
  62. package/examples/toolchains/mixed-python/good/backend/src/fx_backend/__init__.py +6 -0
  63. package/examples/toolchains/mixed-python/good/frontend/src/label.js +4 -0
  64. package/examples/toolchains/mixed-python/policy.json +121 -0
  65. package/examples/toolchains/mixed-python/repo/REQUIREMENTS.md +9 -0
  66. package/examples/toolchains/mixed-python/repo/_gitignore +6 -0
  67. package/examples/toolchains/mixed-python/repo/backend/.python-version +1 -0
  68. package/examples/toolchains/mixed-python/repo/backend/pyproject.toml +19 -0
  69. package/examples/toolchains/mixed-python/repo/backend/src/fx_backend/__init__.py +6 -0
  70. package/examples/toolchains/mixed-python/repo/backend/tests/test_label.py +11 -0
  71. package/examples/toolchains/mixed-python/repo/backend/uv.lock +108 -0
  72. package/examples/toolchains/mixed-python/repo/contract/check.mjs +17 -0
  73. package/examples/toolchains/mixed-python/repo/contract/label.json +9 -0
  74. package/examples/toolchains/mixed-python/repo/frontend/package.json +15 -0
  75. package/examples/toolchains/mixed-python/repo/frontend/pnpm-lock.yaml +22 -0
  76. package/examples/toolchains/mixed-python/repo/frontend/src/label.js +4 -0
  77. package/examples/toolchains/mixed-python/repo/frontend/test/label.test.js +11 -0
  78. package/examples/toolchains/mixed-python/task.json +25 -0
  79. package/examples/toolchains/npm/bad/src/label.js +4 -0
  80. package/examples/toolchains/npm/good/src/label.js +4 -0
  81. package/examples/toolchains/npm/policy.json +82 -0
  82. package/examples/toolchains/npm/repo/REQUIREMENTS.md +9 -0
  83. package/examples/toolchains/npm/repo/_gitignore +4 -0
  84. package/examples/toolchains/npm/repo/package-lock.json +22 -0
  85. package/examples/toolchains/npm/repo/package.json +13 -0
  86. package/examples/toolchains/npm/repo/src/label.js +4 -0
  87. package/examples/toolchains/npm/repo/test/label.test.js +13 -0
  88. package/examples/toolchains/npm/task.json +25 -0
  89. package/examples/toolchains/pnpm/bad/packages/label/src/label.js +4 -0
  90. package/examples/toolchains/pnpm/good/packages/label/src/label.js +4 -0
  91. package/examples/toolchains/pnpm/policy.json +85 -0
  92. package/examples/toolchains/pnpm/repo/REQUIREMENTS.md +9 -0
  93. package/examples/toolchains/pnpm/repo/_gitignore +4 -0
  94. package/examples/toolchains/pnpm/repo/package.json +10 -0
  95. package/examples/toolchains/pnpm/repo/packages/checker/check.mjs +5 -0
  96. package/examples/toolchains/pnpm/repo/packages/checker/package.json +9 -0
  97. package/examples/toolchains/pnpm/repo/packages/label/package.json +14 -0
  98. package/examples/toolchains/pnpm/repo/packages/label/src/label.js +4 -0
  99. package/examples/toolchains/pnpm/repo/packages/label/test/label.test.js +13 -0
  100. package/examples/toolchains/pnpm/repo/pnpm-lock.yaml +29 -0
  101. package/examples/toolchains/pnpm/repo/pnpm-workspace.yaml +2 -0
  102. package/examples/toolchains/pnpm/task.json +25 -0
  103. package/examples/toolchains/python/bad/src/fx_label/__init__.py +6 -0
  104. package/examples/toolchains/python/good/src/fx_label/__init__.py +6 -0
  105. package/examples/toolchains/python/policy.json +80 -0
  106. package/examples/toolchains/python/repo/.python-version +1 -0
  107. package/examples/toolchains/python/repo/REQUIREMENTS.md +9 -0
  108. package/examples/toolchains/python/repo/_gitignore +5 -0
  109. package/examples/toolchains/python/repo/pyproject.toml +19 -0
  110. package/examples/toolchains/python/repo/src/fx_label/__init__.py +6 -0
  111. package/examples/toolchains/python/repo/tests/test_label.py +13 -0
  112. package/examples/toolchains/python/repo/uv.lock +108 -0
  113. package/examples/toolchains/python/task.json +25 -0
  114. package/examples/toolchains/turbo/bad/packages/label/src/label.js +4 -0
  115. package/examples/toolchains/turbo/good/packages/label/src/label.js +4 -0
  116. package/examples/toolchains/turbo/policy.json +110 -0
  117. package/examples/toolchains/turbo/repo/REQUIREMENTS.md +9 -0
  118. package/examples/toolchains/turbo/repo/_gitignore +4 -0
  119. package/examples/toolchains/turbo/repo/package.json +13 -0
  120. package/examples/toolchains/turbo/repo/packages/checker/check.mjs +5 -0
  121. package/examples/toolchains/turbo/repo/packages/checker/package.json +9 -0
  122. package/examples/toolchains/turbo/repo/packages/label/package.json +14 -0
  123. package/examples/toolchains/turbo/repo/packages/label/src/label.js +4 -0
  124. package/examples/toolchains/turbo/repo/packages/label/test/label.test.js +13 -0
  125. package/examples/toolchains/turbo/repo/pnpm-lock.yaml +94 -0
  126. package/examples/toolchains/turbo/repo/pnpm-workspace.yaml +2 -0
  127. package/examples/toolchains/turbo/repo/turbo.json +7 -0
  128. package/examples/toolchains/turbo/task.json +25 -0
  129. package/examples/turbo-starter/README.md +16 -0
  130. package/examples/turbo-starter/changes/issued-at-consumer-only.patch +12 -0
  131. package/examples/turbo-starter/changes/issued-at.patch +130 -0
  132. package/examples/turbo-starter/cleanup.mjs +58 -0
  133. package/examples/turbo-starter/graph.json +32 -0
  134. package/examples/turbo-starter/harness/acceptance/db-isolation.test.mjs +97 -0
  135. package/examples/turbo-starter/harness/acceptance/env-probe.test.mjs +75 -0
  136. package/examples/turbo-starter/harness/acceptance/generation.test.mjs +54 -0
  137. package/examples/turbo-starter/harness/acceptance/issued-at.test.mjs +43 -0
  138. package/examples/turbo-starter/harness/acceptance/lifecycle-probe.test.mjs +47 -0
  139. package/examples/turbo-starter/harness/compose-bridge.mjs +593 -0
  140. package/examples/turbo-starter/harness/compose.acceptance.yml +23 -0
  141. package/examples/turbo-starter/harness/env/backend.env.template +7 -0
  142. package/examples/turbo-starter/harness/env/compose.env.template +6 -0
  143. package/examples/turbo-starter/policy.json +109 -0
  144. package/examples/turbo-starter/policy.lifecycle.json +114 -0
  145. package/examples/turbo-starter/setup.mjs +352 -0
  146. package/examples/two-vendors/policy.json +30 -0
  147. package/lib/agents/cli-adapter.d.ts +48 -0
  148. package/lib/agents/cli-adapter.js +386 -0
  149. package/lib/agents/inspect.d.ts +6 -0
  150. package/lib/agents/inspect.js +46 -0
  151. package/lib/agents/probe-server.d.ts +2 -0
  152. package/lib/agents/probe-server.js +13 -0
  153. package/lib/agents/review-probe.d.ts +295 -0
  154. package/lib/agents/review-probe.js +872 -0
  155. package/lib/agents/runtime-events.d.ts +11 -0
  156. package/lib/agents/runtime-events.js +21 -0
  157. package/lib/agents/schemas.d.ts +217 -0
  158. package/lib/agents/schemas.js +124 -0
  159. package/lib/agents/usage.d.ts +8 -0
  160. package/lib/agents/usage.js +83 -0
  161. package/lib/cli.d.ts +2 -0
  162. package/lib/cli.js +491 -0
  163. package/lib/connectors/files.d.ts +108 -0
  164. package/lib/connectors/files.js +133 -0
  165. package/lib/contracts/checks.d.ts +307 -0
  166. package/lib/contracts/checks.js +181 -0
  167. package/lib/contracts/cli.d.ts +3895 -0
  168. package/lib/contracts/cli.js +664 -0
  169. package/lib/contracts/context.d.ts +135 -0
  170. package/lib/contracts/context.js +129 -0
  171. package/lib/contracts/digest.d.ts +9 -0
  172. package/lib/contracts/digest.js +22 -0
  173. package/lib/contracts/errors.d.ts +81 -0
  174. package/lib/contracts/errors.js +70 -0
  175. package/lib/contracts/events.d.ts +827 -0
  176. package/lib/contracts/events.js +258 -0
  177. package/lib/contracts/execution.d.ts +3216 -0
  178. package/lib/contracts/execution.js +872 -0
  179. package/lib/contracts/failure.d.ts +67 -0
  180. package/lib/contracts/failure.js +127 -0
  181. package/lib/contracts/index.d.ts +18 -0
  182. package/lib/contracts/index.js +18 -0
  183. package/lib/contracts/policy.d.ts +1080 -0
  184. package/lib/contracts/policy.js +544 -0
  185. package/lib/contracts/ports.d.ts +417 -0
  186. package/lib/contracts/ports.js +1 -0
  187. package/lib/contracts/primitives.d.ts +63 -0
  188. package/lib/contracts/primitives.js +73 -0
  189. package/lib/contracts/profiles.d.ts +336 -0
  190. package/lib/contracts/profiles.js +109 -0
  191. package/lib/contracts/published.d.ts +3237 -0
  192. package/lib/contracts/published.js +34 -0
  193. package/lib/contracts/result.d.ts +1280 -0
  194. package/lib/contracts/result.js +311 -0
  195. package/lib/contracts/review.d.ts +441 -0
  196. package/lib/contracts/review.js +477 -0
  197. package/lib/contracts/toolchain.d.ts +96 -0
  198. package/lib/contracts/toolchain.js +89 -0
  199. package/lib/contracts/version.d.ts +17 -0
  200. package/lib/contracts/version.js +17 -0
  201. package/lib/contracts/work.d.ts +173 -0
  202. package/lib/contracts/work.js +178 -0
  203. package/lib/control/base-move.d.ts +44 -0
  204. package/lib/control/base-move.js +90 -0
  205. package/lib/control/doctor.d.ts +50 -0
  206. package/lib/control/doctor.js +113 -0
  207. package/lib/control/harness.d.ts +1125 -0
  208. package/lib/control/harness.js +741 -0
  209. package/lib/control/provenance.d.ts +17 -0
  210. package/lib/control/provenance.js +25 -0
  211. package/lib/control/recovery.d.ts +237 -0
  212. package/lib/control/recovery.js +236 -0
  213. package/lib/control/review.d.ts +62 -0
  214. package/lib/control/review.js +178 -0
  215. package/lib/control/workflow.d.ts +247 -0
  216. package/lib/control/workflow.js +259 -0
  217. package/lib/engine/budget.d.ts +345 -0
  218. package/lib/engine/budget.js +278 -0
  219. package/lib/engine/classify.d.ts +8 -0
  220. package/lib/engine/classify.js +32 -0
  221. package/lib/engine/engine.d.ts +1527 -0
  222. package/lib/engine/engine.js +2259 -0
  223. package/lib/engine/failure.d.ts +1 -0
  224. package/lib/engine/failure.js +3 -0
  225. package/lib/engine/joint-runner.d.ts +257 -0
  226. package/lib/engine/joint-runner.js +254 -0
  227. package/lib/engine/measured.d.ts +15 -0
  228. package/lib/engine/measured.js +82 -0
  229. package/lib/engine/prompt.d.ts +66 -0
  230. package/lib/engine/prompt.js +131 -0
  231. package/lib/engine/property-recovery.d.ts +50 -0
  232. package/lib/engine/property-recovery.js +171 -0
  233. package/lib/engine/repair.d.ts +33 -0
  234. package/lib/engine/repair.js +82 -0
  235. package/lib/engine/result.d.ts +9 -0
  236. package/lib/engine/result.js +218 -0
  237. package/lib/engine/reuse.d.ts +80 -0
  238. package/lib/engine/reuse.js +102 -0
  239. package/lib/engine/runner.d.ts +360 -0
  240. package/lib/engine/runner.js +1836 -0
  241. package/lib/engine/standalone.d.ts +6 -0
  242. package/lib/engine/standalone.js +48 -0
  243. package/lib/engine/usage.d.ts +87 -0
  244. package/lib/engine/usage.js +165 -0
  245. package/lib/environment/isolation.d.ts +110 -0
  246. package/lib/environment/isolation.js +238 -0
  247. package/lib/environment/lifecycle.d.ts +40 -0
  248. package/lib/environment/lifecycle.js +197 -0
  249. package/lib/environment/live-calls.d.ts +14 -0
  250. package/lib/environment/live-calls.js +73 -0
  251. package/lib/environment/os-tools.d.ts +16 -0
  252. package/lib/environment/os-tools.js +35 -0
  253. package/lib/environment/process.d.ts +32 -0
  254. package/lib/environment/process.js +369 -0
  255. package/lib/environment/redaction.d.ts +22 -0
  256. package/lib/environment/redaction.js +102 -0
  257. package/lib/environment/resources.d.ts +31 -0
  258. package/lib/environment/resources.js +120 -0
  259. package/lib/index.d.ts +65 -0
  260. package/lib/index.js +67 -0
  261. package/lib/integrations/connector/commands.d.ts +358 -0
  262. package/lib/integrations/connector/commands.js +428 -0
  263. package/lib/integrations/connector/config.d.ts +215 -0
  264. package/lib/integrations/connector/config.js +214 -0
  265. package/lib/integrations/connector/delivery.d.ts +107 -0
  266. package/lib/integrations/connector/delivery.js +591 -0
  267. package/lib/integrations/connector/fake.d.ts +291 -0
  268. package/lib/integrations/connector/fake.js +786 -0
  269. package/lib/integrations/connector/history.d.ts +124 -0
  270. package/lib/integrations/connector/history.js +497 -0
  271. package/lib/integrations/connector/index.d.ts +16 -0
  272. package/lib/integrations/connector/index.js +16 -0
  273. package/lib/integrations/connector/redact.d.ts +19 -0
  274. package/lib/integrations/connector/redact.js +91 -0
  275. package/lib/integrations/connector/registry.d.ts +15 -0
  276. package/lib/integrations/connector/registry.js +43 -0
  277. package/lib/integrations/connector/snapshot.d.ts +131 -0
  278. package/lib/integrations/connector/snapshot.js +422 -0
  279. package/lib/integrations/connector/source.d.ts +37 -0
  280. package/lib/integrations/connector/source.js +73 -0
  281. package/lib/integrations/connector/steps.d.ts +71 -0
  282. package/lib/integrations/connector/steps.js +188 -0
  283. package/lib/integrations/connector/store.d.ts +140 -0
  284. package/lib/integrations/connector/store.js +277 -0
  285. package/lib/integrations/connector/summary.d.ts +38 -0
  286. package/lib/integrations/connector/summary.js +59 -0
  287. package/lib/integrations/connector/testing-worker.d.ts +1 -0
  288. package/lib/integrations/connector/testing-worker.js +81 -0
  289. package/lib/integrations/connector/testing.d.ts +205 -0
  290. package/lib/integrations/connector/testing.js +1615 -0
  291. package/lib/integrations/connector/transport.d.ts +240 -0
  292. package/lib/integrations/connector/transport.js +28 -0
  293. package/lib/integrations/memory/context.d.ts +120 -0
  294. package/lib/integrations/memory/context.js +239 -0
  295. package/lib/integrations/memory/index.d.ts +8 -0
  296. package/lib/integrations/memory/index.js +8 -0
  297. package/lib/integrations/memory/provider.d.ts +79 -0
  298. package/lib/integrations/memory/provider.js +22 -0
  299. package/lib/integrations/memory/sink.d.ts +56 -0
  300. package/lib/integrations/memory/sink.js +116 -0
  301. package/lib/integrations/memory/testing.d.ts +44 -0
  302. package/lib/integrations/memory/testing.js +61 -0
  303. package/lib/integrations/relay-v1/index.d.ts +122 -0
  304. package/lib/integrations/relay-v1/index.js +860 -0
  305. package/lib/integrations/relay-v2/index.d.ts +145 -0
  306. package/lib/integrations/relay-v2/index.js +752 -0
  307. package/lib/integrations/relay-v2/process.d.ts +32 -0
  308. package/lib/integrations/relay-v2/process.js +112 -0
  309. package/lib/integrations/relay-v2/protocol.d.ts +172 -0
  310. package/lib/integrations/relay-v2/protocol.js +142 -0
  311. package/lib/package.d.ts +2 -0
  312. package/lib/package.js +3 -0
  313. package/lib/profiles/resolve.d.ts +190 -0
  314. package/lib/profiles/resolve.js +273 -0
  315. package/lib/storage/document.d.ts +1234 -0
  316. package/lib/storage/document.js +80 -0
  317. package/lib/storage/sqlite.d.ts +35 -0
  318. package/lib/storage/sqlite.js +260 -0
  319. package/lib/testing/index.d.ts +5 -0
  320. package/lib/testing/index.js +5 -0
  321. package/lib/testing/store-contract.d.ts +8 -0
  322. package/lib/testing/store-contract.js +167 -0
  323. package/lib/toolchains/index.d.ts +9 -0
  324. package/lib/toolchains/index.js +9 -0
  325. package/lib/toolchains/inspect.d.ts +105 -0
  326. package/lib/toolchains/inspect.js +831 -0
  327. package/lib/toolchains/manifests.d.ts +67 -0
  328. package/lib/toolchains/manifests.js +238 -0
  329. package/lib/toolchains/probe.d.ts +28 -0
  330. package/lib/toolchains/probe.js +54 -0
  331. package/lib/toolchains/recipes.d.ts +33 -0
  332. package/lib/toolchains/recipes.js +51 -0
  333. package/lib/validate.d.ts +36 -0
  334. package/lib/validate.js +175 -0
  335. package/lib/verification/acceptance.d.ts +284 -0
  336. package/lib/verification/acceptance.js +670 -0
  337. package/lib/verification/checks.d.ts +72 -0
  338. package/lib/verification/checks.js +190 -0
  339. package/lib/verification/confirm.d.ts +125 -0
  340. package/lib/verification/confirm.js +411 -0
  341. package/lib/verification/corpus.d.ts +1303 -0
  342. package/lib/verification/corpus.js +744 -0
  343. package/lib/verification/dependencies.d.ts +66 -0
  344. package/lib/verification/dependencies.js +144 -0
  345. package/lib/verification/gates.d.ts +160 -0
  346. package/lib/verification/gates.js +600 -0
  347. package/lib/verification/joint.d.ts +63 -0
  348. package/lib/verification/joint.js +121 -0
  349. package/lib/verification/proof.d.ts +54 -0
  350. package/lib/verification/proof.js +96 -0
  351. package/lib/verification/property.d.ts +86 -0
  352. package/lib/verification/property.js +214 -0
  353. package/lib/verification/requirements.d.ts +25 -0
  354. package/lib/verification/requirements.js +69 -0
  355. package/lib/verification/self-check.d.ts +29 -0
  356. package/lib/verification/self-check.js +99 -0
  357. package/lib/verification/spike.d.ts +79 -0
  358. package/lib/verification/spike.js +124 -0
  359. package/package.json +100 -4
  360. package/profiles/expo-mobile.json +15 -0
  361. package/profiles/go-api.json +15 -0
  362. package/profiles/go-gotestsum.json +21 -0
  363. package/profiles/mobile-maestro.json +29 -0
  364. package/profiles/nest-api.json +26 -0
  365. package/profiles/next-product.json +72 -0
  366. package/profiles/node-checks.json +77 -0
  367. package/profiles/npm-ci.json +22 -0
  368. package/profiles/pnpm-frozen.json +24 -0
  369. package/profiles/python-api.json +32 -0
  370. package/profiles/python-uv.json +26 -0
  371. package/profiles/react-native.json +50 -0
  372. package/profiles/react-vite-admin.json +71 -0
  373. package/schemas/context-snapshot.schema.json +231 -0
  374. package/schemas/contract-document.schema.json +385 -0
  375. package/schemas/execution-document.schema.json +3695 -0
  376. package/schemas/execution-policy.schema.json +2196 -0
  377. package/schemas/joint-verification.schema.json +617 -0
  378. package/schemas/result-envelope.schema.json +1652 -0
  379. package/schemas/review-record.schema.json +177 -0
  380. package/schemas/run-event.schema.json +2458 -0
  381. package/schemas/run-result.schema.json +1570 -0
  382. package/schemas/stack-profile.schema.json +535 -0
  383. package/schemas/work-graph.schema.json +381 -0
  384. package/schemas/work-order.schema.json +256 -0
  385. package/skills/harness/SKILL.md +64 -0
  386. package/templates/AGENTS.md +13 -0
  387. package/templates/controller-mode/AGENTS.controller.md +58 -0
  388. package/templates/controller-mode/README.md +44 -0
  389. package/templates/graph.json +22 -0
  390. package/templates/policy.json +28 -0
@@ -0,0 +1,1125 @@
1
+ import { type Author, type ContextSnapshot, type ContractDocument, type PropertyRecovery, type ExecutionPolicy, type ResultEnvelope, type ResultSink, type WorkSource, type RuntimeAdapter, type RuntimeName, type WorkGraph } from '../contracts/index.ts';
2
+ import { Engine } from '../engine/engine.ts';
3
+ import { Runner, type RunnerHooks } from '../engine/runner.ts';
4
+ import { SqliteExecutionStore } from '../storage/sqlite.ts';
5
+ import { WorkflowQueue } from './workflow.ts';
6
+ import { type PolicySource } from './provenance.ts';
7
+ import { JointRunner } from '../engine/joint-runner.ts';
8
+ export interface HarnessOptions {
9
+ /** Каталог состояния исполнения: база, worktrees, артефакты. */
10
+ stateDir: string;
11
+ policy: ExecutionPolicy;
12
+ /** Каталог, от которого разрешаются относительные пути репозиториев политики. */
13
+ baseDir: string;
14
+ /** Подключённые runtime; по умолчанию — CLI codex и claude из PATH. */
15
+ adapters?: Partial<Record<RuntimeName, RuntimeAdapter>>;
16
+ /** Читающие операции не создают каталог состояния. */
17
+ readOnly?: boolean;
18
+ /**
19
+ * Открыть базу состояния только для чтения (status, events, result): процесс
20
+ * не записывает даже метку писателя. Любая запись — отказ.
21
+ */
22
+ readOnlyState?: boolean;
23
+ environment?: NodeJS.ProcessEnv;
24
+ /**
25
+ * Файл, из которого загружена политика. С ним процесс может записать свою
26
+ * политику применённой, только пока файл не менялся; без него политика —
27
+ * объект вызывающего, и право ограничено остальными условиями.
28
+ */
29
+ policySource?: PolicySource;
30
+ /** База блокировок ресурсов; по умолчанию — общая для машины. */
31
+ resourceDatabase?: string;
32
+ /**
33
+ * Дополнения хоста к попыткам (например, история работы внешнего
34
+ * хранилища задач до исполнения). Приёмку не решают: отказ хука — отказ
35
+ * попытки.
36
+ */
37
+ hooks?: RunnerHooks;
38
+ }
39
+ /**
40
+ * Доменные операции harness — общие для библиотеки и CLI. Здесь нет
41
+ * операции «передать PASS» или «принять без проверок»: приёмка возможна
42
+ * только через движок после evidence обеих фаз.
43
+ */
44
+ export declare class Harness {
45
+ readonly options: HarnessOptions;
46
+ readonly engine: Engine;
47
+ readonly runner: Runner;
48
+ readonly store: SqliteExecutionStore;
49
+ readonly policy: ExecutionPolicy;
50
+ /** Техническая очередь: сохранённые стадии и ограниченное восстановление графа. */
51
+ readonly workflows: WorkflowQueue;
52
+ /** Совместная проверка комбинации репозиториев. */
53
+ readonly joint: JointRunner;
54
+ private readonly adapters;
55
+ static open(options: HarnessOptions): Harness;
56
+ private constructor();
57
+ close(): void;
58
+ /**
59
+ * Совместная проверка набора принятых поручений на текущих target ref.
60
+ * Возвращает итог (`passed` или `failed` с причиной); продуктовое принятие
61
+ * комбинации решает хост.
62
+ */
63
+ verifyJoint(workIds: string[], options?: {
64
+ baseline?: string;
65
+ }): Promise<{
66
+ status: "active";
67
+ apiVersion: "devcontour-harness/v1alpha1";
68
+ id: string;
69
+ startedAt: string;
70
+ policyDigest: string;
71
+ specDigest: string;
72
+ workIds: string[];
73
+ evidence: {
74
+ gate: string;
75
+ passed: boolean;
76
+ command: string[];
77
+ exitCode: number;
78
+ log: string;
79
+ digest: string;
80
+ summary: string;
81
+ artifacts: {
82
+ path: string;
83
+ digest: string;
84
+ }[];
85
+ durationMs?: number | undefined;
86
+ }[];
87
+ manifest?: Record<string, {
88
+ sha: string;
89
+ tree: string;
90
+ }> | undefined;
91
+ manifestDigest?: string | undefined;
92
+ impact?: {
93
+ changed: string[];
94
+ affected: string[];
95
+ gateIds: string[];
96
+ mode: "all" | "affected";
97
+ reason: string;
98
+ baseline?: string | undefined;
99
+ } | undefined;
100
+ } | {
101
+ status: "failed";
102
+ finishedAt: string;
103
+ error: string;
104
+ apiVersion: "devcontour-harness/v1alpha1";
105
+ id: string;
106
+ startedAt: string;
107
+ policyDigest: string;
108
+ specDigest: string;
109
+ workIds: string[];
110
+ evidence: {
111
+ gate: string;
112
+ passed: boolean;
113
+ command: string[];
114
+ exitCode: number;
115
+ log: string;
116
+ digest: string;
117
+ summary: string;
118
+ artifacts: {
119
+ path: string;
120
+ digest: string;
121
+ }[];
122
+ durationMs?: number | undefined;
123
+ }[];
124
+ manifest?: Record<string, {
125
+ sha: string;
126
+ tree: string;
127
+ }> | undefined;
128
+ manifestDigest?: string | undefined;
129
+ impact?: {
130
+ changed: string[];
131
+ affected: string[];
132
+ gateIds: string[];
133
+ mode: "all" | "affected";
134
+ reason: string;
135
+ baseline?: string | undefined;
136
+ } | undefined;
137
+ } | {
138
+ status: "passed";
139
+ finishedAt: string;
140
+ manifest: Record<string, {
141
+ sha: string;
142
+ tree: string;
143
+ }>;
144
+ manifestDigest: string;
145
+ apiVersion: "devcontour-harness/v1alpha1";
146
+ id: string;
147
+ startedAt: string;
148
+ policyDigest: string;
149
+ specDigest: string;
150
+ workIds: string[];
151
+ evidence: {
152
+ gate: string;
153
+ passed: boolean;
154
+ command: string[];
155
+ exitCode: number;
156
+ log: string;
157
+ digest: string;
158
+ summary: string;
159
+ artifacts: {
160
+ path: string;
161
+ digest: string;
162
+ }[];
163
+ durationMs?: number | undefined;
164
+ }[];
165
+ impact?: {
166
+ changed: string[];
167
+ affected: string[];
168
+ gateIds: string[];
169
+ mode: "all" | "affected";
170
+ reason: string;
171
+ baseline?: string | undefined;
172
+ } | undefined;
173
+ }>;
174
+ /**
175
+ * Актуальность результата совместной проверки набора и свежесть его
176
+ * manifest: SHA каждого репозитория сравнивается с текущим target ref.
177
+ * Свежесть — наблюдение, а не запрет: решение о принятии — за хостом.
178
+ */
179
+ jointResult(workIds: string[]): Promise<{
180
+ verification?: import("../contracts/result.ts").JointVerification;
181
+ current: boolean;
182
+ reason?: string;
183
+ } | {
184
+ freshness: {
185
+ fresh: boolean;
186
+ head?: string | undefined;
187
+ repositoryId: string;
188
+ sha: string;
189
+ }[];
190
+ verification?: import("../contracts/result.ts").JointVerification;
191
+ current: boolean;
192
+ reason?: string;
193
+ }>;
194
+ /** Запросить применение политики с digest `policyDigest(next)`; держит новые выдачи. */
195
+ requestReconfigure(operation: string, digest: string): {
196
+ operation: string;
197
+ digest: string;
198
+ changed: boolean;
199
+ retried?: undefined;
200
+ } | {
201
+ operation: string;
202
+ digest: string;
203
+ changed: boolean;
204
+ retried: boolean;
205
+ };
206
+ /** Применить запрос политикой этого процесса (после drain), см. `Engine.applyReconfigure`. */
207
+ applyReconfigure(by?: string): {
208
+ status: "none";
209
+ } | {
210
+ status: "busy";
211
+ busy: string[];
212
+ } | {
213
+ status: "waiting";
214
+ expected: string;
215
+ } | {
216
+ status: "failed";
217
+ error: string;
218
+ } | {
219
+ status: "applied";
220
+ generation: number;
221
+ };
222
+ policyState(): {
223
+ stale?: string | undefined;
224
+ reconfigure?: {
225
+ operation: string;
226
+ digest: string;
227
+ requestedAt: string;
228
+ appliedAt?: string | undefined;
229
+ appliedBy?: string | undefined;
230
+ error?: string | undefined;
231
+ } | undefined;
232
+ applied?: {
233
+ digest: string;
234
+ at: string;
235
+ by: string;
236
+ generation?: number | undefined;
237
+ } | undefined;
238
+ loaded: string;
239
+ };
240
+ /**
241
+ * Довести незавершённую очистку закончившейся попытки: повторить teardown по
242
+ * сохранённым receipt окружений и убрать её рабочие деревья и снимки.
243
+ */
244
+ cleanup(runId: string): Promise<{
245
+ status: "nothing-pending";
246
+ receipts?: undefined;
247
+ } | {
248
+ status: "cleaned";
249
+ receipts: string[];
250
+ }>;
251
+ private repoPath;
252
+ /**
253
+ * Снимок контекста для ревью плана: без нужного графу источника — отказ
254
+ * `NOT_READY`, нарушения снимка (digest, размер) — `INVALID_INPUT`.
255
+ * Поручения без контекста — снимок не нужен.
256
+ */
257
+ private planContext;
258
+ /**
259
+ * Раунд технического ревью предмета (граф или контракт) с конкретным
260
+ * digest. Тот же digest и автор, уже согласованные последним раундом, —
261
+ * тот же раунд без вызова модели. Reviewer — по правилу вендора политики;
262
+ * недопустимый автор — `REVIEWER_SAME_VENDOR` до вызова. Reviewer называет
263
+ * состояние каждой прежней открытой находки; история не переписывается.
264
+ */
265
+ review(input: {
266
+ kind: 'plan';
267
+ graph: WorkGraph;
268
+ context?: ContextSnapshot;
269
+ author: Author;
270
+ } | {
271
+ kind: 'contract';
272
+ contract: ContractDocument;
273
+ author: Author;
274
+ }): Promise<{
275
+ id: string;
276
+ kind: "plan" | "contract";
277
+ subject: string;
278
+ digest: string;
279
+ round: number;
280
+ at: string;
281
+ approved: boolean;
282
+ summary: string;
283
+ authorRuntime: "codex" | "claude" | "fixture" | "external";
284
+ reviewerRuntime: "codex" | "claude" | "fixture";
285
+ sameVendor: boolean;
286
+ findings: {
287
+ id: string;
288
+ severity: "blocking" | "note";
289
+ message: string;
290
+ status: "open" | "closed" | "withdrawn";
291
+ openedIn: number;
292
+ changedIn: number;
293
+ rule?: string | undefined;
294
+ path?: string | null | undefined;
295
+ line?: number | null | undefined;
296
+ basis?: string | undefined;
297
+ }[];
298
+ artifact: string;
299
+ reviewerModel?: string | undefined;
300
+ reviewerBinding?: string | undefined;
301
+ contextDigest?: string | undefined;
302
+ }>;
303
+ /**
304
+ * Эксперименты, на которые ссылаются тяжёлые обязательства: reviewer читает
305
+ * фактический результат, а не пересказ автора.
306
+ */
307
+ private spikeNote;
308
+ private assertContract;
309
+ /** Корпус: принятые версии, решения, отложенные принятия. */
310
+ get corpus(): import("../index.ts").CorpusStore;
311
+ /**
312
+ * Ограниченный эксперимент выполнимости до реализации тяжёлого обязательства.
313
+ * Таймаут — `inconclusive`: не доказательство невыполнимости и не основание
314
+ * ослаблять обязательство.
315
+ */
316
+ spike(input: unknown): Promise<{
317
+ id: string;
318
+ repositoryId: string;
319
+ sha: string;
320
+ command: string[];
321
+ seed: number;
322
+ sizes: number[];
323
+ timeoutMs: number;
324
+ question: string;
325
+ results: {
326
+ size: number;
327
+ ms: number;
328
+ outcome: "error" | "ok" | "timeout";
329
+ exitCode: number;
330
+ }[];
331
+ outcome: "failed" | "feasible" | "inconclusive";
332
+ limits: string;
333
+ environment: {
334
+ platform: string;
335
+ arch: string;
336
+ node: string;
337
+ cpus: number;
338
+ isolation: string;
339
+ };
340
+ at: string;
341
+ digest: string;
342
+ }>;
343
+ /** Эксперименты выполнимости репозитория (по умолчанию — всех). */
344
+ spikes(repositoryId?: string): {
345
+ id: string;
346
+ repositoryId: string;
347
+ sha: string;
348
+ command: string[];
349
+ seed: number;
350
+ sizes: number[];
351
+ timeoutMs: number;
352
+ question: string;
353
+ results: {
354
+ size: number;
355
+ ms: number;
356
+ outcome: "error" | "ok" | "timeout";
357
+ exitCode: number;
358
+ }[];
359
+ outcome: "failed" | "feasible" | "inconclusive";
360
+ limits: string;
361
+ environment: {
362
+ platform: string;
363
+ arch: string;
364
+ node: string;
365
+ cpus: number;
366
+ isolation: string;
367
+ };
368
+ at: string;
369
+ digest: string;
370
+ }[];
371
+ /** Подтвердить пример закреплённым эталоном; подтверждённый — новая версия корпуса. */
372
+ submitCase(input: unknown): Promise<{
373
+ suite: string;
374
+ repeated: boolean;
375
+ decision: {
376
+ id: string;
377
+ property: string;
378
+ input: string;
379
+ inputHash: string;
380
+ outcome: "rejected" | "inconclusive" | "confirmed" | "refuted";
381
+ reason: string;
382
+ source: {
383
+ sha: string;
384
+ runId?: string | undefined;
385
+ taskId?: string | undefined;
386
+ };
387
+ origin: {
388
+ kind: "review" | "agent" | "operator" | "lead";
389
+ runtime?: string | undefined;
390
+ };
391
+ at: string;
392
+ key?: string | undefined;
393
+ claimed?: {
394
+ expected: string | null;
395
+ actual: string | null;
396
+ reproduction?: string | undefined;
397
+ } | undefined;
398
+ observed?: {
399
+ repeats: number;
400
+ durationsMs: number[];
401
+ expected?: string | undefined;
402
+ actual?: string | undefined;
403
+ equal?: boolean | undefined;
404
+ } | undefined;
405
+ method?: {
406
+ gate: string;
407
+ artifacts: {
408
+ path: string;
409
+ blob: string;
410
+ }[];
411
+ contract: string;
412
+ basis: string;
413
+ command?: string[] | undefined;
414
+ } | undefined;
415
+ caseId?: string | undefined;
416
+ version?: number | undefined;
417
+ };
418
+ version: {
419
+ number: number;
420
+ digest: string;
421
+ cases: number;
422
+ } | null;
423
+ adoption: {
424
+ awaitingOperator?: true | undefined;
425
+ id: string;
426
+ status: "completed" | "waiting";
427
+ results: Record<string, string>;
428
+ }[];
429
+ }>;
430
+ /** Ручное техническое подтверждение принятия версии корпуса (operator mode). */
431
+ approveAdoption(suiteId: string, pendingId: string): {
432
+ pending: {
433
+ id: string;
434
+ version: number;
435
+ tasks: string[];
436
+ status: "completed" | "waiting";
437
+ results: Record<string, string>;
438
+ actor: string;
439
+ reason: string;
440
+ requestedAt: string;
441
+ digest?: string | undefined;
442
+ awaitingOperator?: boolean | undefined;
443
+ completedAt?: string | undefined;
444
+ };
445
+ suite: {
446
+ id: string;
447
+ repositoryId: string;
448
+ contractId: string;
449
+ contractDigest: string;
450
+ gate: string;
451
+ basis: string;
452
+ cases: Record<string, {
453
+ id: string;
454
+ property: string;
455
+ input: string;
456
+ expected: string;
457
+ source: {
458
+ kind: "oracle";
459
+ decision: string;
460
+ sha: string;
461
+ runId?: string | undefined;
462
+ taskId?: string | undefined;
463
+ reproduction?: string | undefined;
464
+ };
465
+ addedAt: string;
466
+ }>;
467
+ versions: {
468
+ number: number;
469
+ digest: string;
470
+ previous: string | null;
471
+ cases: string[];
472
+ blob: string;
473
+ createdAt: string;
474
+ reason: string;
475
+ decisions: string[];
476
+ }[];
477
+ decisions: {
478
+ id: string;
479
+ property: string;
480
+ input: string;
481
+ inputHash: string;
482
+ outcome: "rejected" | "inconclusive" | "confirmed" | "refuted";
483
+ reason: string;
484
+ source: {
485
+ sha: string;
486
+ runId?: string | undefined;
487
+ taskId?: string | undefined;
488
+ };
489
+ origin: {
490
+ kind: "review" | "agent" | "operator" | "lead";
491
+ runtime?: string | undefined;
492
+ };
493
+ at: string;
494
+ key?: string | undefined;
495
+ claimed?: {
496
+ expected: string | null;
497
+ actual: string | null;
498
+ reproduction?: string | undefined;
499
+ } | undefined;
500
+ observed?: {
501
+ repeats: number;
502
+ durationsMs: number[];
503
+ expected?: string | undefined;
504
+ actual?: string | undefined;
505
+ equal?: boolean | undefined;
506
+ } | undefined;
507
+ method?: {
508
+ gate: string;
509
+ artifacts: {
510
+ path: string;
511
+ blob: string;
512
+ }[];
513
+ contract: string;
514
+ basis: string;
515
+ command?: string[] | undefined;
516
+ } | undefined;
517
+ caseId?: string | undefined;
518
+ version?: number | undefined;
519
+ }[];
520
+ adoptions: {
521
+ id: string;
522
+ taskId: string;
523
+ from: {
524
+ number: number;
525
+ digest: string;
526
+ } | null;
527
+ to: {
528
+ number: number;
529
+ digest: string;
530
+ };
531
+ actor: string;
532
+ reason: string;
533
+ operation: string;
534
+ at: string;
535
+ }[];
536
+ pending: {
537
+ id: string;
538
+ version: number;
539
+ tasks: string[];
540
+ status: "completed" | "waiting";
541
+ results: Record<string, string>;
542
+ actor: string;
543
+ reason: string;
544
+ requestedAt: string;
545
+ digest?: string | undefined;
546
+ awaitingOperator?: boolean | undefined;
547
+ completedAt?: string | undefined;
548
+ }[];
549
+ operations: Record<string, {
550
+ key: string;
551
+ status: "completed" | "running";
552
+ startedAt: string;
553
+ token?: string | undefined;
554
+ leaseUntil?: number | undefined;
555
+ decision?: string | undefined;
556
+ }>;
557
+ revision: number;
558
+ };
559
+ };
560
+ /** Решение эпизода по свойству человеком: CAS по версии записи. */
561
+ decideRecovery(workId: string, recoveryId: string, decision: Omit<NonNullable<PropertyRecovery['decision']>, 'source' | 'decidedAt'>, version: number): {
562
+ id: string;
563
+ property: string;
564
+ basis: string;
565
+ runs: string[];
566
+ openedAt: string;
567
+ status: "closed" | "stopped" | "awaiting-lead" | "analyzing" | "applying" | "retry" | "retrying" | "awaiting-user";
568
+ calls: number;
569
+ history: {
570
+ at: string;
571
+ event: string;
572
+ detail?: string | undefined;
573
+ }[];
574
+ version: number;
575
+ decision?: {
576
+ action: "environment" | "add-cases" | "new-approach" | "strengthen-checker" | "split-task" | "clarify-obligation";
577
+ reason: string;
578
+ evidence: string[];
579
+ source: {
580
+ kind: "operator" | "lead";
581
+ runtime?: string | undefined;
582
+ model?: string | undefined;
583
+ };
584
+ decidedAt: string;
585
+ hypothesis?: string | undefined;
586
+ plan?: string | undefined;
587
+ cases?: {
588
+ input: string;
589
+ expected?: string | null | undefined;
590
+ }[] | undefined;
591
+ proposal?: string | undefined;
592
+ conflict?: string | undefined;
593
+ } | undefined;
594
+ retryRun?: string | undefined;
595
+ reason?: string | undefined;
596
+ };
597
+ /** Согласование оператором (approvalMode: operator) графа, digest которого прошёл ревью. */
598
+ approve(subject: string, digest: string): {
599
+ subject: string;
600
+ digest: string;
601
+ at: string;
602
+ changed: boolean;
603
+ };
604
+ /**
605
+ * Действующий контекст графа — снимок, связанный с его согласованием, а не
606
+ * последний переданный: отклонённый или ещё не согласованный снимок не
607
+ * исполняется.
608
+ */
609
+ private contextOf;
610
+ /**
611
+ * Зарегистрировать граф (идемпотентно по редакции), в режиме `agent`
612
+ * провести ревью плана, если его нет, согласовать и вести очередь до
613
+ * простоя. Результаты доставляются получателю с идемпотентным ключом.
614
+ */
615
+ run(input: {
616
+ graph: WorkGraph;
617
+ context?: ContextSnapshot;
618
+ author: Author;
619
+ sink?: ResultSink;
620
+ once?: boolean;
621
+ /**
622
+ * Источник, из которого прочитан граф. Его решение `trusts` — единственное
623
+ * основание принять внешнюю предпосылку с receipt `trusted`; доступность
624
+ * result SHA в target ref проверяется в любом случае. Без источника
625
+ * доверенных receipt нет.
626
+ */
627
+ source?: WorkSource;
628
+ }): Promise<{
629
+ works: {
630
+ blockers: {
631
+ code: "NOT_READY" | "PAUSED" | "ATTEMPTS_EXHAUSTED" | "APPROVAL_STALE" | "APPROVAL_REQUIRED" | "BUDGET_EXHAUSTED" | "REVIEWER_SAME_VENDOR" | "REVIEWER_MISSING" | "INVALID_INPUT";
632
+ message: string;
633
+ }[];
634
+ resultSha?: string | undefined;
635
+ runId?: string | undefined;
636
+ id: string;
637
+ status: "ready" | "failed" | "cancelled" | "draft" | "running" | "verifying" | "reviewing" | "integrating" | "done";
638
+ }[];
639
+ workflow?: {
640
+ history: {
641
+ at: string;
642
+ stage: number;
643
+ event: string;
644
+ }[];
645
+ error?: string | undefined;
646
+ key: string;
647
+ kind: string;
648
+ id: string;
649
+ stage: number;
650
+ status: "failed" | "completed" | "running" | "queued" | "stale";
651
+ attempts: number;
652
+ repairs: number;
653
+ repairBudget: number;
654
+ } | undefined;
655
+ graphId: string;
656
+ digest: string;
657
+ resumed: boolean;
658
+ }>;
659
+ /**
660
+ * Вести задание графа: стадия согласования уже пройдена синхронно; стадия
661
+ * исполнения — очередь до простоя, затем решение о восстановлении по
662
+ * записанному состоянию. Повтор назначается и списывается одной
663
+ * транзакцией; остановка записывает причину в задание.
664
+ */
665
+ private advance;
666
+ /**
667
+ * Эпизоды повторяющихся отказов по свойству. Возвращает true, когда
668
+ * разрешённое действие назначено и его результата нужно дождаться;
669
+ * останавливается с причиной там, где автоматического действия нет.
670
+ * Бюджет восстановлений и разбор эпизода учитываются одной транзакцией до
671
+ * вызова модели: рестарт и повтор бесплатного вызова не получают.
672
+ */
673
+ private recoverProperties;
674
+ private applyRecovery;
675
+ private afterDecision;
676
+ /**
677
+ * Восстановление упавшего поручения группы. Решение и его исполнение — одна
678
+ * транзакция: между чтением и записью никто не успеет отменить поручение.
679
+ * Возвращает true, когда повтор назначен; остановка — исключение с причиной.
680
+ */
681
+ private repair;
682
+ status(graphId?: string): {
683
+ budgets: {
684
+ onUnknown: "stop" | "continue";
685
+ budgets: {
686
+ reason?: string | undefined;
687
+ scope: import("../engine/budget.ts").BudgetScope;
688
+ state: "exceeded" | "undetermined" | "within";
689
+ limit: {
690
+ usd?: number;
691
+ timeMs?: number;
692
+ };
693
+ reportedUsd: number;
694
+ estimatedUsd: number;
695
+ unknownCalls: number;
696
+ unfinishedCalls: number;
697
+ abandonedCalls: number;
698
+ errorCalls: number;
699
+ uncoveredRuns: number;
700
+ durationMs: number;
701
+ remainingUsd: number | null;
702
+ remainingMs: number | null;
703
+ }[];
704
+ };
705
+ graphs: {
706
+ id: string;
707
+ digest: string;
708
+ source: {
709
+ connector: string;
710
+ ref: string;
711
+ revision: string;
712
+ };
713
+ approved: boolean;
714
+ }[];
715
+ works: {
716
+ blockers: {
717
+ code: "NOT_READY" | "PAUSED" | "ATTEMPTS_EXHAUSTED" | "APPROVAL_STALE" | "APPROVAL_REQUIRED" | "BUDGET_EXHAUSTED" | "REVIEWER_SAME_VENDOR" | "REVIEWER_MISSING" | "INVALID_INPUT";
718
+ message: string;
719
+ }[];
720
+ resultSha?: string | undefined;
721
+ activeRunId?: string | undefined;
722
+ id: string;
723
+ graphId: string;
724
+ status: "ready" | "failed" | "cancelled" | "draft" | "running" | "verifying" | "reviewing" | "integrating" | "done";
725
+ attempt: number;
726
+ }[];
727
+ controller?: {
728
+ owner: string;
729
+ leaseUntil: number;
730
+ engineVersion?: string | undefined;
731
+ } | undefined;
732
+ stateVersion: 1;
733
+ control: {
734
+ paused: boolean;
735
+ pauseReason?: "runtime" | "operator" | "shutdown" | "base-check" | "reconfigure" | undefined;
736
+ pausedAt?: string | undefined;
737
+ pauseOperation?: string | undefined;
738
+ pauseFailures?: ("gate" | "unknown" | "review" | "environment" | "cancelled" | "timeout" | "provider-auth" | "stale-base" | "empty-result" | "scope-violation" | "review-protocol" | "merge" | "budget")[] | undefined;
739
+ waits?: {
740
+ kind: "base-check" | "context-lock";
741
+ detail: string;
742
+ at: string;
743
+ operation?: string | undefined;
744
+ }[] | undefined;
745
+ appliedPolicy?: {
746
+ digest: string;
747
+ at: string;
748
+ by: string;
749
+ generation?: number | undefined;
750
+ } | undefined;
751
+ reconfigure?: {
752
+ operation: string;
753
+ digest: string;
754
+ requestedAt: string;
755
+ appliedAt?: string | undefined;
756
+ appliedBy?: string | undefined;
757
+ error?: string | undefined;
758
+ } | undefined;
759
+ };
760
+ } | {
761
+ budgets?: undefined;
762
+ graphs: {
763
+ id: string;
764
+ digest: string;
765
+ source: {
766
+ connector: string;
767
+ ref: string;
768
+ revision: string;
769
+ };
770
+ approved: boolean;
771
+ }[];
772
+ works: {
773
+ blockers: {
774
+ code: "NOT_READY" | "PAUSED" | "ATTEMPTS_EXHAUSTED" | "APPROVAL_STALE" | "APPROVAL_REQUIRED" | "BUDGET_EXHAUSTED" | "REVIEWER_SAME_VENDOR" | "REVIEWER_MISSING" | "INVALID_INPUT";
775
+ message: string;
776
+ }[];
777
+ resultSha?: string | undefined;
778
+ activeRunId?: string | undefined;
779
+ id: string;
780
+ graphId: string;
781
+ status: "ready" | "failed" | "cancelled" | "draft" | "running" | "verifying" | "reviewing" | "integrating" | "done";
782
+ attempt: number;
783
+ }[];
784
+ controller?: {
785
+ owner: string;
786
+ leaseUntil: number;
787
+ engineVersion?: string | undefined;
788
+ } | undefined;
789
+ stateVersion: 1;
790
+ control: {
791
+ paused: boolean;
792
+ pauseReason?: "runtime" | "operator" | "shutdown" | "base-check" | "reconfigure" | undefined;
793
+ pausedAt?: string | undefined;
794
+ pauseOperation?: string | undefined;
795
+ pauseFailures?: ("gate" | "unknown" | "review" | "environment" | "cancelled" | "timeout" | "provider-auth" | "stale-base" | "empty-result" | "scope-violation" | "review-protocol" | "merge" | "budget")[] | undefined;
796
+ waits?: {
797
+ kind: "base-check" | "context-lock";
798
+ detail: string;
799
+ at: string;
800
+ operation?: string | undefined;
801
+ }[] | undefined;
802
+ appliedPolicy?: {
803
+ digest: string;
804
+ at: string;
805
+ by: string;
806
+ generation?: number | undefined;
807
+ } | undefined;
808
+ reconfigure?: {
809
+ operation: string;
810
+ digest: string;
811
+ requestedAt: string;
812
+ appliedAt?: string | undefined;
813
+ appliedBy?: string | undefined;
814
+ error?: string | undefined;
815
+ } | undefined;
816
+ };
817
+ };
818
+ events(after?: number, limit?: number): {
819
+ events: import("../contracts/events.ts").RunEvent[];
820
+ next: number;
821
+ };
822
+ /** Результат завершённой попытки поручения (последней или `runId`) и состояние его доставки. */
823
+ result(workId: string, runId?: string): ResultEnvelope;
824
+ /**
825
+ * Доставка результата поручения получателю. Ключ — получатель, поручение и
826
+ * попытка: повтор не создаёт второй записи и не вызывает моделей или
827
+ * интеграции. Конфликт редакции записывается, результат её не закрывает.
828
+ */
829
+ deliver(workId: string, sink: ResultSink): Promise<{
830
+ apiVersion: "devcontour-harness/v1alpha1";
831
+ result: {
832
+ outcome: "accepted";
833
+ shas: {
834
+ base: string;
835
+ candidate: string;
836
+ integration: string;
837
+ result: string;
838
+ };
839
+ apiVersion: "devcontour-harness/v1alpha1";
840
+ workOrderId: string;
841
+ graphId: string;
842
+ source: {
843
+ connector: string;
844
+ ref: string;
845
+ revision: string;
846
+ };
847
+ runId: string;
848
+ attempt: number;
849
+ repositoryId: string;
850
+ targetRef: string;
851
+ inputs: {
852
+ harnessVersion: string;
853
+ stateVersion: 1;
854
+ workOrderDigest: string;
855
+ graphDigest: string;
856
+ policyDigest: string;
857
+ consumerVersion?: string | undefined;
858
+ contextDigest?: string | undefined;
859
+ checks?: string | undefined;
860
+ corpus?: {
861
+ suite: string;
862
+ number: number;
863
+ digest: string;
864
+ } | undefined;
865
+ requiredGates?: string[] | undefined;
866
+ writer?: {
867
+ runtime: "codex" | "claude" | "fixture";
868
+ model?: string | undefined;
869
+ } | undefined;
870
+ };
871
+ checked: {
872
+ dependencies: {
873
+ repositoryId: string;
874
+ sha: string;
875
+ tree: string;
876
+ artifacts: {
877
+ path: string;
878
+ digest: string;
879
+ }[];
880
+ }[];
881
+ freshness: {
882
+ repositoryId: string;
883
+ snapshot: string;
884
+ head: string;
885
+ fresh: boolean;
886
+ }[];
887
+ consumers: {
888
+ repositoryId: string;
889
+ gates: string[];
890
+ sha: string;
891
+ tree: string;
892
+ dependencies: {
893
+ repositoryId: string;
894
+ sha: string;
895
+ tree: string;
896
+ artifacts: {
897
+ path: string;
898
+ digest: string;
899
+ }[];
900
+ }[];
901
+ freshness: {
902
+ repositoryId: string;
903
+ snapshot: string;
904
+ head: string;
905
+ fresh: boolean;
906
+ }[];
907
+ }[];
908
+ };
909
+ evidence: {
910
+ id: string;
911
+ kind: "check" | "test" | "property" | "review" | "consumer";
912
+ phase: "candidate" | "integration";
913
+ gate: string;
914
+ sha: string;
915
+ passed: boolean;
916
+ digest: string;
917
+ summary: string;
918
+ consumer?: string | undefined;
919
+ checks?: string | undefined;
920
+ tests?: {
921
+ id: string;
922
+ status: "passed" | "failed" | "skipped";
923
+ opaque?: true | undefined;
924
+ }[] | undefined;
925
+ testsTruncated?: boolean | undefined;
926
+ property?: {
927
+ level?: "manifest" | "legacy" | undefined;
928
+ manifest?: {
929
+ digest: string;
930
+ properties: string[];
931
+ corpus?: {
932
+ digest: string;
933
+ cases: number;
934
+ } | undefined;
935
+ } | undefined;
936
+ } | undefined;
937
+ reviewer?: {
938
+ runtime: "codex" | "claude" | "fixture";
939
+ sameVendor: boolean;
940
+ model?: string | undefined;
941
+ } | undefined;
942
+ review?: {
943
+ round: number;
944
+ call: number;
945
+ protocol: "valid" | "invalid" | "unsafe";
946
+ issues?: {
947
+ path: string;
948
+ reason: string;
949
+ message: string;
950
+ }[] | undefined;
951
+ transitions?: {
952
+ id: string;
953
+ from: "open" | "closed" | "withdrawn";
954
+ to: "open" | "closed" | "withdrawn";
955
+ }[] | undefined;
956
+ } | undefined;
957
+ }[];
958
+ findings: {
959
+ severity: string;
960
+ message: string;
961
+ path?: string | null | undefined;
962
+ line?: number | null | undefined;
963
+ rule?: string | undefined;
964
+ id?: string | undefined;
965
+ status?: "open" | "closed" | "withdrawn" | undefined;
966
+ }[];
967
+ limitations: string[];
968
+ finishedAt: string;
969
+ } | {
970
+ outcome: "rejected" | "blocked" | "cancelled" | "stopped";
971
+ shas: {
972
+ base?: string | undefined;
973
+ candidate?: string | undefined;
974
+ integration?: string | undefined;
975
+ };
976
+ stopReason: {
977
+ code: "INVALID_INPUT" | "UNSUPPORTED_COMMAND" | "UNSUPPORTED_VERSION" | "GRAPH_CYCLE" | "GRAPH_UNKNOWN_DEPENDENCY" | "GRAPH_DUPLICATE_ID" | "GATE_UNKNOWN" | "GATE_GROUP_CYCLE" | "REVIEWER_SAME_VENDOR" | "REVIEWER_MISSING" | "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" | "STATE_VERSION_UNSUPPORTED" | "RUNTIME_UNAVAILABLE" | "REVIEW_PROTOCOL_INVALID" | "SANDBOX_UNAVAILABLE" | "GIT_FAILED" | "STORAGE_FAILED" | "DELIVERY_FAILED" | "INTERNAL";
978
+ message: string;
979
+ };
980
+ apiVersion: "devcontour-harness/v1alpha1";
981
+ workOrderId: string;
982
+ graphId: string;
983
+ source: {
984
+ connector: string;
985
+ ref: string;
986
+ revision: string;
987
+ };
988
+ runId: string;
989
+ attempt: number;
990
+ repositoryId: string;
991
+ targetRef: string;
992
+ inputs: {
993
+ harnessVersion: string;
994
+ stateVersion: 1;
995
+ workOrderDigest: string;
996
+ graphDigest: string;
997
+ policyDigest: string;
998
+ consumerVersion?: string | undefined;
999
+ contextDigest?: string | undefined;
1000
+ checks?: string | undefined;
1001
+ corpus?: {
1002
+ suite: string;
1003
+ number: number;
1004
+ digest: string;
1005
+ } | undefined;
1006
+ requiredGates?: string[] | undefined;
1007
+ writer?: {
1008
+ runtime: "codex" | "claude" | "fixture";
1009
+ model?: string | undefined;
1010
+ } | undefined;
1011
+ };
1012
+ checked: {
1013
+ dependencies: {
1014
+ repositoryId: string;
1015
+ sha: string;
1016
+ tree: string;
1017
+ artifacts: {
1018
+ path: string;
1019
+ digest: string;
1020
+ }[];
1021
+ }[];
1022
+ freshness: {
1023
+ repositoryId: string;
1024
+ snapshot: string;
1025
+ head: string;
1026
+ fresh: boolean;
1027
+ }[];
1028
+ consumers: {
1029
+ repositoryId: string;
1030
+ gates: string[];
1031
+ sha: string;
1032
+ tree: string;
1033
+ dependencies: {
1034
+ repositoryId: string;
1035
+ sha: string;
1036
+ tree: string;
1037
+ artifacts: {
1038
+ path: string;
1039
+ digest: string;
1040
+ }[];
1041
+ }[];
1042
+ freshness: {
1043
+ repositoryId: string;
1044
+ snapshot: string;
1045
+ head: string;
1046
+ fresh: boolean;
1047
+ }[];
1048
+ }[];
1049
+ };
1050
+ evidence: {
1051
+ id: string;
1052
+ kind: "check" | "test" | "property" | "review" | "consumer";
1053
+ phase: "candidate" | "integration";
1054
+ gate: string;
1055
+ sha: string;
1056
+ passed: boolean;
1057
+ digest: string;
1058
+ summary: string;
1059
+ consumer?: string | undefined;
1060
+ checks?: string | undefined;
1061
+ tests?: {
1062
+ id: string;
1063
+ status: "passed" | "failed" | "skipped";
1064
+ opaque?: true | undefined;
1065
+ }[] | undefined;
1066
+ testsTruncated?: boolean | undefined;
1067
+ property?: {
1068
+ level?: "manifest" | "legacy" | undefined;
1069
+ manifest?: {
1070
+ digest: string;
1071
+ properties: string[];
1072
+ corpus?: {
1073
+ digest: string;
1074
+ cases: number;
1075
+ } | undefined;
1076
+ } | undefined;
1077
+ } | undefined;
1078
+ reviewer?: {
1079
+ runtime: "codex" | "claude" | "fixture";
1080
+ sameVendor: boolean;
1081
+ model?: string | undefined;
1082
+ } | undefined;
1083
+ review?: {
1084
+ round: number;
1085
+ call: number;
1086
+ protocol: "valid" | "invalid" | "unsafe";
1087
+ issues?: {
1088
+ path: string;
1089
+ reason: string;
1090
+ message: string;
1091
+ }[] | undefined;
1092
+ transitions?: {
1093
+ id: string;
1094
+ from: "open" | "closed" | "withdrawn";
1095
+ to: "open" | "closed" | "withdrawn";
1096
+ }[] | undefined;
1097
+ } | undefined;
1098
+ }[];
1099
+ findings: {
1100
+ severity: string;
1101
+ message: string;
1102
+ path?: string | null | undefined;
1103
+ line?: number | null | undefined;
1104
+ rule?: string | undefined;
1105
+ id?: string | undefined;
1106
+ status?: "open" | "closed" | "withdrawn" | undefined;
1107
+ }[];
1108
+ limitations: string[];
1109
+ finishedAt: string;
1110
+ };
1111
+ delivery: {
1112
+ sink: string;
1113
+ key: string;
1114
+ revision: string;
1115
+ status: "failed" | "pending" | "delivered" | "conflict" | "uncertain";
1116
+ attempts: number;
1117
+ updatedAt: string;
1118
+ lastError?: string | undefined;
1119
+ operation?: string | undefined;
1120
+ currentRevision?: string | undefined;
1121
+ receipt?: string | undefined;
1122
+ }[];
1123
+ }>;
1124
+ private deliverAll;
1125
+ }