@b00dea/cockpit 0.0.0-stage → 0.1.1

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 (426) hide show
  1. package/CHANGELOG.md +474 -0
  2. package/LICENSE +21 -0
  3. package/README.md +25 -2
  4. package/bin/cockpit.mjs +33 -0
  5. package/cockpit.schema.json +2644 -0
  6. package/dist/autonomy.d.ts +45 -0
  7. package/dist/autonomy.js +173 -0
  8. package/dist/bounded-read.d.ts +14 -0
  9. package/dist/bounded-read.js +42 -0
  10. package/dist/browser/commands.d.ts +117 -0
  11. package/dist/browser/commands.js +453 -0
  12. package/dist/browser/package-paths.d.ts +1 -0
  13. package/dist/browser/package-paths.js +6 -0
  14. package/dist/browser/proxy.d.ts +22 -0
  15. package/dist/browser/proxy.js +37 -0
  16. package/dist/browser/runtime.d.ts +118 -0
  17. package/dist/browser/runtime.js +186 -0
  18. package/dist/browser/surfaces.d.ts +141 -0
  19. package/dist/browser/surfaces.js +561 -0
  20. package/dist/browser/ui-gate.d.ts +15 -0
  21. package/dist/browser/ui-gate.js +18 -0
  22. package/dist/canonical-json.d.ts +2 -0
  23. package/dist/canonical-json.js +5 -0
  24. package/dist/cli-guard.d.ts +5 -0
  25. package/dist/cli-guard.js +71 -0
  26. package/dist/cli-main.d.ts +176 -0
  27. package/dist/cli-main.js +1584 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.js +16 -0
  30. package/dist/command-table.d.ts +121 -0
  31. package/dist/command-table.js +664 -0
  32. package/dist/config/load.d.ts +183 -0
  33. package/dist/config/load.js +367 -0
  34. package/dist/config/sibling-toml.d.ts +48 -0
  35. package/dist/config/sibling-toml.js +160 -0
  36. package/dist/config/surface-tools-toml.d.ts +9 -0
  37. package/dist/config/surface-tools-toml.js +37 -0
  38. package/dist/config/unconfirmed-toml.d.ts +9 -0
  39. package/dist/config/unconfirmed-toml.js +29 -0
  40. package/dist/config/verified-write.d.ts +43 -0
  41. package/dist/config/verified-write.js +89 -0
  42. package/dist/diagnostics.d.ts +26 -0
  43. package/dist/diagnostics.js +344 -0
  44. package/dist/docs/check.d.ts +16 -0
  45. package/dist/docs/check.js +197 -0
  46. package/dist/docs/decision-record.d.ts +34 -0
  47. package/dist/docs/decision-record.js +135 -0
  48. package/dist/docs/decisions.d.ts +16 -0
  49. package/dist/docs/decisions.js +103 -0
  50. package/dist/docs/markdown.d.ts +36 -0
  51. package/dist/docs/markdown.js +88 -0
  52. package/dist/docs/references.d.ts +32 -0
  53. package/dist/docs/references.js +148 -0
  54. package/dist/emit.d.ts +22 -0
  55. package/dist/emit.js +43 -0
  56. package/dist/entrypoint-kinds.d.ts +3 -0
  57. package/dist/entrypoint-kinds.js +11 -0
  58. package/dist/environment/application/confirm.d.ts +35 -0
  59. package/dist/environment/application/confirm.js +122 -0
  60. package/dist/environment/application/destructive.d.ts +6 -0
  61. package/dist/environment/application/destructive.js +429 -0
  62. package/dist/environment/application/doctor.d.ts +94 -0
  63. package/dist/environment/application/doctor.js +247 -0
  64. package/dist/environment/application/guard.d.ts +49 -0
  65. package/dist/environment/application/guard.js +677 -0
  66. package/dist/environment/application/health.d.ts +143 -0
  67. package/dist/environment/application/health.js +385 -0
  68. package/dist/environment/application/lifecycle-context.d.ts +235 -0
  69. package/dist/environment/application/lifecycle-context.js +154 -0
  70. package/dist/environment/application/lifecycle-state.d.ts +25 -0
  71. package/dist/environment/application/lifecycle-state.js +202 -0
  72. package/dist/environment/application/lifecycle.d.ts +18 -0
  73. package/dist/environment/application/lifecycle.js +737 -0
  74. package/dist/environment/application/logs.d.ts +45 -0
  75. package/dist/environment/application/logs.js +127 -0
  76. package/dist/environment/application/services.d.ts +60 -0
  77. package/dist/environment/application/services.js +89 -0
  78. package/dist/environment/application/setup.d.ts +129 -0
  79. package/dist/environment/application/setup.js +741 -0
  80. package/dist/environment/application/shared.d.ts +11 -0
  81. package/dist/environment/application/shared.js +61 -0
  82. package/dist/environment/application/siblings.d.ts +43 -0
  83. package/dist/environment/application/siblings.js +269 -0
  84. package/dist/environment/claims.d.ts +389 -0
  85. package/dist/environment/claims.js +1701 -0
  86. package/dist/environment/codex-hook-trust.d.ts +11 -0
  87. package/dist/environment/codex-hook-trust.js +185 -0
  88. package/dist/environment/compose-environment.d.ts +1 -0
  89. package/dist/environment/compose-environment.js +6 -0
  90. package/dist/environment/compose-ownership.d.ts +21 -0
  91. package/dist/environment/compose-ownership.js +117 -0
  92. package/dist/environment/compose-topology.d.ts +125 -0
  93. package/dist/environment/compose-topology.js +490 -0
  94. package/dist/environment/contract.d.ts +522 -0
  95. package/dist/environment/contract.js +794 -0
  96. package/dist/environment/declaration.d.ts +14 -0
  97. package/dist/environment/declaration.js +39 -0
  98. package/dist/environment/destructive-composition.d.ts +29 -0
  99. package/dist/environment/destructive-composition.js +333 -0
  100. package/dist/environment/docker-daemon.d.ts +30 -0
  101. package/dist/environment/docker-daemon.js +78 -0
  102. package/dist/environment/docker-endpoint.d.ts +10 -0
  103. package/dist/environment/docker-endpoint.js +19 -0
  104. package/dist/environment/env-schema-observation.d.ts +46 -0
  105. package/dist/environment/env-schema-observation.js +241 -0
  106. package/dist/environment/evidence.d.ts +136 -0
  107. package/dist/environment/evidence.js +437 -0
  108. package/dist/environment/executable.d.ts +38 -0
  109. package/dist/environment/executable.js +190 -0
  110. package/dist/environment/generated-application/authorities.d.ts +5 -0
  111. package/dist/environment/generated-application/authorities.js +61 -0
  112. package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
  113. package/dist/environment/generated-application/bootstrap-skill.js +328 -0
  114. package/dist/environment/generated-application/check.d.ts +13 -0
  115. package/dist/environment/generated-application/check.js +191 -0
  116. package/dist/environment/generated-application/custom-surface.d.ts +26 -0
  117. package/dist/environment/generated-application/custom-surface.js +289 -0
  118. package/dist/environment/generated-application/prepare.d.ts +29 -0
  119. package/dist/environment/generated-application/prepare.js +278 -0
  120. package/dist/environment/generated-application/publication.d.ts +33 -0
  121. package/dist/environment/generated-application/publication.js +547 -0
  122. package/dist/environment/generated-application/shared.d.ts +492 -0
  123. package/dist/environment/generated-application/shared.js +354 -0
  124. package/dist/environment/generated-application/surface-observation.d.ts +4 -0
  125. package/dist/environment/generated-application/surface-observation.js +69 -0
  126. package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
  127. package/dist/environment/generated-application/surface-outputs.js +400 -0
  128. package/dist/environment/generated-application/surfaces.d.ts +3 -0
  129. package/dist/environment/generated-application/surfaces.js +704 -0
  130. package/dist/environment/generated-application/sync.d.ts +6 -0
  131. package/dist/environment/generated-application/sync.js +124 -0
  132. package/dist/environment/git-observation.d.ts +202 -0
  133. package/dist/environment/git-observation.js +553 -0
  134. package/dist/environment/health-composition.d.ts +12 -0
  135. package/dist/environment/health-composition.js +645 -0
  136. package/dist/environment/host-observation.d.ts +56 -0
  137. package/dist/environment/host-observation.js +52 -0
  138. package/dist/environment/identity.d.ts +48 -0
  139. package/dist/environment/identity.js +85 -0
  140. package/dist/environment/init-application.d.ts +333 -0
  141. package/dist/environment/init-application.js +726 -0
  142. package/dist/environment/install-policy-observation.d.ts +71 -0
  143. package/dist/environment/install-policy-observation.js +284 -0
  144. package/dist/environment/install-policy.d.ts +48 -0
  145. package/dist/environment/install-policy.js +96 -0
  146. package/dist/environment/instance.d.ts +33 -0
  147. package/dist/environment/instance.js +122 -0
  148. package/dist/environment/instruction-pointer.d.ts +19 -0
  149. package/dist/environment/instruction-pointer.js +144 -0
  150. package/dist/environment/lifecycle-composition.d.ts +31 -0
  151. package/dist/environment/lifecycle-composition.js +742 -0
  152. package/dist/environment/lifecycle-stage.d.ts +120 -0
  153. package/dist/environment/lifecycle-stage.js +408 -0
  154. package/dist/environment/lifecycle.d.ts +75 -0
  155. package/dist/environment/lifecycle.js +354 -0
  156. package/dist/environment/logs.d.ts +132 -0
  157. package/dist/environment/logs.js +519 -0
  158. package/dist/environment/map-limit.d.ts +2 -0
  159. package/dist/environment/map-limit.js +13 -0
  160. package/dist/environment/mcp-observation.d.ts +9 -0
  161. package/dist/environment/mcp-observation.js +46 -0
  162. package/dist/environment/observations.d.ts +46 -0
  163. package/dist/environment/observations.js +346 -0
  164. package/dist/environment/operator-application.d.ts +79 -0
  165. package/dist/environment/operator-application.js +197 -0
  166. package/dist/environment/ports.d.ts +182 -0
  167. package/dist/environment/ports.js +1205 -0
  168. package/dist/environment/posture-observation.d.ts +68 -0
  169. package/dist/environment/posture-observation.js +253 -0
  170. package/dist/environment/presence.d.ts +4 -0
  171. package/dist/environment/presence.js +26 -0
  172. package/dist/environment/read-composition.d.ts +32 -0
  173. package/dist/environment/read-composition.js +397 -0
  174. package/dist/environment/readiness-composition.d.ts +57 -0
  175. package/dist/environment/readiness-composition.js +151 -0
  176. package/dist/environment/reclaim.d.ts +370 -0
  177. package/dist/environment/reclaim.js +1940 -0
  178. package/dist/environment/repository-identity.d.ts +13 -0
  179. package/dist/environment/repository-identity.js +108 -0
  180. package/dist/environment/runtime-measurement-record.d.ts +38 -0
  181. package/dist/environment/runtime-measurement-record.js +111 -0
  182. package/dist/environment/runtime-measurement.d.ts +27 -0
  183. package/dist/environment/runtime-measurement.js +224 -0
  184. package/dist/environment/runtime-probe-residue.d.ts +43 -0
  185. package/dist/environment/runtime-probe-residue.js +148 -0
  186. package/dist/environment/runtime-probe.d.ts +72 -0
  187. package/dist/environment/runtime-probe.js +725 -0
  188. package/dist/environment/runtime.d.ts +551 -0
  189. package/dist/environment/runtime.js +2405 -0
  190. package/dist/environment/seed.d.ts +16 -0
  191. package/dist/environment/seed.js +43 -0
  192. package/dist/environment/selftest-application.d.ts +86 -0
  193. package/dist/environment/selftest-application.js +713 -0
  194. package/dist/environment/sensitive.d.ts +3 -0
  195. package/dist/environment/sensitive.js +48 -0
  196. package/dist/environment/served-checkout-grants.d.ts +53 -0
  197. package/dist/environment/served-checkout-grants.js +182 -0
  198. package/dist/environment/setup-observation.d.ts +62 -0
  199. package/dist/environment/setup-observation.js +1473 -0
  200. package/dist/environment/setup.d.ts +43 -0
  201. package/dist/environment/setup.js +176 -0
  202. package/dist/environment/sibling-checkouts.d.ts +119 -0
  203. package/dist/environment/sibling-checkouts.js +254 -0
  204. package/dist/environment/sibling-instructions.d.ts +33 -0
  205. package/dist/environment/sibling-instructions.js +224 -0
  206. package/dist/environment/sibling-observation.d.ts +27 -0
  207. package/dist/environment/sibling-observation.js +45 -0
  208. package/dist/environment/sibling-pull.d.ts +23 -0
  209. package/dist/environment/sibling-pull.js +95 -0
  210. package/dist/environment/sibling-registration.d.ts +45 -0
  211. package/dist/environment/sibling-registration.js +538 -0
  212. package/dist/environment/stack-inputs.d.ts +18 -0
  213. package/dist/environment/stack-inputs.js +210 -0
  214. package/dist/environment/stack-inventory-prune.d.ts +31 -0
  215. package/dist/environment/stack-inventory-prune.js +129 -0
  216. package/dist/environment/stack-inventory-report.d.ts +44 -0
  217. package/dist/environment/stack-inventory-report.js +78 -0
  218. package/dist/environment/stack-inventory.d.ts +94 -0
  219. package/dist/environment/stack-inventory.js +418 -0
  220. package/dist/environment/state.d.ts +410 -0
  221. package/dist/environment/state.js +2153 -0
  222. package/dist/environment/templates.d.ts +140 -0
  223. package/dist/environment/templates.js +685 -0
  224. package/dist/environment/tool-registration.d.ts +9 -0
  225. package/dist/environment/tool-registration.js +92 -0
  226. package/dist/environment/upgrade-application.d.ts +19 -0
  227. package/dist/environment/upgrade-application.js +175 -0
  228. package/dist/environment-exec/execute.d.ts +105 -0
  229. package/dist/environment-exec/execute.js +1179 -0
  230. package/dist/environment-exec/libexec-program.d.ts +6 -0
  231. package/dist/environment-exec/libexec-program.js +22 -0
  232. package/dist/environment-exec/verified-digest.d.ts +4 -0
  233. package/dist/environment-exec/verified-digest.js +16 -0
  234. package/dist/exact-keys.d.ts +7 -0
  235. package/dist/exact-keys.js +15 -0
  236. package/dist/fix-catalogue.d.ts +32 -0
  237. package/dist/fix-catalogue.js +60 -0
  238. package/dist/freshness.d.ts +29 -0
  239. package/dist/freshness.js +75 -0
  240. package/dist/generated-environment/adopt.d.ts +16 -0
  241. package/dist/generated-environment/adopt.js +271 -0
  242. package/dist/generated-environment/command.d.ts +47 -0
  243. package/dist/generated-environment/command.js +75 -0
  244. package/dist/generated-environment/transaction.d.ts +186 -0
  245. package/dist/generated-environment/transaction.js +1770 -0
  246. package/dist/grading/evaluate.d.ts +71 -0
  247. package/dist/grading/evaluate.js +403 -0
  248. package/dist/grading/grade.d.ts +33 -0
  249. package/dist/grading/grade.js +57 -0
  250. package/dist/guards/answer-confirmation.d.ts +41 -0
  251. package/dist/guards/answer-confirmation.js +109 -0
  252. package/dist/guards/evaluator.d.ts +130 -0
  253. package/dist/guards/evaluator.js +1258 -0
  254. package/dist/guards/harness-adapter.d.ts +17 -0
  255. package/dist/guards/harness-adapter.js +57 -0
  256. package/dist/guards/host.d.ts +8 -0
  257. package/dist/guards/host.js +10 -0
  258. package/dist/guards/invocation-parser.d.ts +66 -0
  259. package/dist/guards/invocation-parser.js +595 -0
  260. package/dist/guards/local-identity.d.ts +44 -0
  261. package/dist/guards/local-identity.js +129 -0
  262. package/dist/guards/policy-change.d.ts +43 -0
  263. package/dist/guards/policy-change.js +159 -0
  264. package/dist/guards/policy-pin.d.ts +13 -0
  265. package/dist/guards/policy-pin.js +177 -0
  266. package/dist/guards/protected-locations.d.ts +62 -0
  267. package/dist/guards/protected-locations.js +461 -0
  268. package/dist/guards/read-only.d.ts +37 -0
  269. package/dist/guards/read-only.js +315 -0
  270. package/dist/init/command.d.ts +41 -0
  271. package/dist/init/command.js +330 -0
  272. package/dist/init/derive.d.ts +53 -0
  273. package/dist/init/derive.js +819 -0
  274. package/dist/init/draft.d.ts +140 -0
  275. package/dist/init/draft.js +1228 -0
  276. package/dist/init/render.d.ts +47 -0
  277. package/dist/init/render.js +104 -0
  278. package/dist/init/scaffold.d.ts +53 -0
  279. package/dist/init/scaffold.js +121 -0
  280. package/dist/invocation.d.ts +13 -0
  281. package/dist/invocation.js +20 -0
  282. package/dist/package-metadata.d.ts +9 -0
  283. package/dist/package-metadata.js +19 -0
  284. package/dist/readiness.d.ts +53 -0
  285. package/dist/readiness.js +88 -0
  286. package/dist/references/named.d.ts +24 -0
  287. package/dist/references/named.js +27 -0
  288. package/dist/refusal.d.ts +15 -0
  289. package/dist/refusal.js +7 -0
  290. package/dist/registry-derivation.d.ts +31 -0
  291. package/dist/registry-derivation.js +32 -0
  292. package/dist/registry-resolve/command.d.ts +47 -0
  293. package/dist/registry-resolve/command.js +226 -0
  294. package/dist/registry-resolve/registry.d.ts +68 -0
  295. package/dist/registry-resolve/registry.js +292 -0
  296. package/dist/registry-resolve/render-shell.d.ts +18 -0
  297. package/dist/registry-resolve/render-shell.js +36 -0
  298. package/dist/repair.d.ts +29 -0
  299. package/dist/repair.js +8 -0
  300. package/dist/repository-path.d.ts +9 -0
  301. package/dist/repository-path.js +16 -0
  302. package/dist/schema-json.d.ts +1 -0
  303. package/dist/schema-json.js +177 -0
  304. package/dist/schema.d.ts +1289 -0
  305. package/dist/schema.js +985 -0
  306. package/dist/setup/command.d.ts +4 -0
  307. package/dist/setup/command.js +4 -0
  308. package/dist/sha256.d.ts +1 -0
  309. package/dist/sha256.js +4 -0
  310. package/dist/surfaces/adoption.d.ts +41 -0
  311. package/dist/surfaces/adoption.js +217 -0
  312. package/dist/surfaces/consumer-instructions.d.ts +20 -0
  313. package/dist/surfaces/consumer-instructions.js +43 -0
  314. package/dist/surfaces/contract.d.ts +42 -0
  315. package/dist/surfaces/contract.js +169 -0
  316. package/dist/surfaces/core-declarations.d.ts +24 -0
  317. package/dist/surfaces/core-declarations.js +79 -0
  318. package/dist/surfaces/development-markers.d.ts +1 -0
  319. package/dist/surfaces/development-markers.js +18 -0
  320. package/dist/surfaces/generator-adapter.d.ts +71 -0
  321. package/dist/surfaces/generator-adapter.js +809 -0
  322. package/dist/surfaces/harness-registry.d.ts +260 -0
  323. package/dist/surfaces/harness-registry.js +146 -0
  324. package/dist/surfaces/mcp.d.ts +145 -0
  325. package/dist/surfaces/mcp.js +349 -0
  326. package/dist/surfaces/merge.d.ts +30 -0
  327. package/dist/surfaces/merge.js +105 -0
  328. package/dist/surfaces/ownership.d.ts +190 -0
  329. package/dist/surfaces/ownership.js +795 -0
  330. package/dist/surfaces/projection.d.ts +136 -0
  331. package/dist/surfaces/projection.js +716 -0
  332. package/dist/surfaces/render.d.ts +79 -0
  333. package/dist/surfaces/render.js +636 -0
  334. package/dist/surfaces/restrictions.d.ts +130 -0
  335. package/dist/surfaces/restrictions.js +447 -0
  336. package/dist/surfaces/selftest.d.ts +162 -0
  337. package/dist/surfaces/selftest.js +393 -0
  338. package/dist/surfaces/skill-contract.d.ts +85 -0
  339. package/dist/surfaces/skill-contract.js +449 -0
  340. package/dist/surfaces/sync.d.ts +57 -0
  341. package/dist/surfaces/sync.js +164 -0
  342. package/dist/team-metadata.d.ts +41 -0
  343. package/dist/team-metadata.js +513 -0
  344. package/dist/testing/gates.d.ts +91 -0
  345. package/dist/testing/gates.js +182 -0
  346. package/dist/testing/hooks.d.ts +59 -0
  347. package/dist/testing/hooks.js +139 -0
  348. package/dist/testing/test-protection.d.ts +34 -0
  349. package/dist/testing/test-protection.js +137 -0
  350. package/dist/testing/verdict.d.ts +29 -0
  351. package/dist/testing/verdict.js +62 -0
  352. package/dist/testing/weakening.d.ts +15 -0
  353. package/dist/testing/weakening.js +30 -0
  354. package/dist/work-orders/application-closure.d.ts +7 -0
  355. package/dist/work-orders/application-closure.js +76 -0
  356. package/dist/work-orders/application-context.d.ts +162 -0
  357. package/dist/work-orders/application-context.js +137 -0
  358. package/dist/work-orders/application-decisions.d.ts +27 -0
  359. package/dist/work-orders/application-decisions.js +121 -0
  360. package/dist/work-orders/application-grading.d.ts +11 -0
  361. package/dist/work-orders/application-grading.js +212 -0
  362. package/dist/work-orders/application.d.ts +6 -0
  363. package/dist/work-orders/application.js +223 -0
  364. package/dist/work-orders/composition.d.ts +101 -0
  365. package/dist/work-orders/composition.js +1202 -0
  366. package/dist/work-orders/contract.d.ts +77 -0
  367. package/dist/work-orders/contract.js +140 -0
  368. package/dist/work-orders/decisions.d.ts +23 -0
  369. package/dist/work-orders/decisions.js +55 -0
  370. package/dist/work-orders/store.d.ts +207 -0
  371. package/dist/work-orders/store.js +291 -0
  372. package/docs/README.md +68 -0
  373. package/docs/architecture.md +136 -0
  374. package/docs/capability-matrix.md +58 -0
  375. package/docs/cli-reference.md +807 -0
  376. package/docs/command-list.md +62 -0
  377. package/docs/compose-patterns.md +99 -0
  378. package/docs/concepts.md +173 -0
  379. package/docs/configuration-essentials.md +177 -0
  380. package/docs/configuration-reference.md +636 -0
  381. package/docs/docs-check.md +76 -0
  382. package/docs/environment.md +948 -0
  383. package/docs/extending.md +43 -0
  384. package/docs/faq.md +113 -0
  385. package/docs/getting-started.md +692 -0
  386. package/docs/harness-surfaces.md +500 -0
  387. package/docs/joining-a-team.md +76 -0
  388. package/docs/release-policy.md +49 -0
  389. package/docs/safety-and-autonomy.md +463 -0
  390. package/docs/troubleshooting.md +382 -0
  391. package/docs/tutorial.md +171 -0
  392. package/docs/work-and-browser.md +420 -0
  393. package/libexec/browser-operation.cjs +270 -0
  394. package/libexec/fence-marker.cjs +101 -0
  395. package/libexec/fence-marker.d.cts +24 -0
  396. package/libexec/fenced-group-runner.cjs +77 -0
  397. package/libexec/fenced-supervisor.cjs +137 -0
  398. package/libexec/generated-filesystem.cjs +731 -0
  399. package/libexec/install-filesystem.cjs +225 -0
  400. package/libexec/rulesync-generator.NOTICE.md +1112 -0
  401. package/libexec/rulesync-generator.cjs +743 -0
  402. package/libexec/surface-generator-worker.cjs +266 -0
  403. package/libexec/surface-output-reader.cjs +99 -0
  404. package/libexec/surface-scratch-cleanup.cjs +14 -0
  405. package/libexec/validate-harness-evidence.d.mts +183 -0
  406. package/libexec/validate-harness-evidence.mjs +1312 -0
  407. package/package.json +74 -4
  408. package/surfaces/README.md +33 -0
  409. package/surfaces/agents/evaluator.agent.md +76 -0
  410. package/surfaces/guards/bash-guard.sh +48 -0
  411. package/surfaces/guards/claude.adapter.json +25 -0
  412. package/surfaces/guards/codex.adapter.json +24 -0
  413. package/surfaces/guards/opencode.adapter.json +25 -0
  414. package/surfaces/references/browser.md +63 -0
  415. package/surfaces/references/test-data-and-personas.md +84 -0
  416. package/surfaces/references/testing-tiers.md +11 -0
  417. package/surfaces/skills/cockpit-browser.skill.md +59 -0
  418. package/surfaces/skills/cockpit-explain.skill.md +32 -0
  419. package/surfaces/skills/cockpit-fix.skill.md +37 -0
  420. package/surfaces/skills/cockpit-setup.skill.md +39 -0
  421. package/surfaces/skills/cockpit-work.skill.md +34 -0
  422. package/surfaces/skills/collection.json +5 -0
  423. package/surfaces/skills/procedures/explain.md +66 -0
  424. package/surfaces/skills/procedures/fix.md +95 -0
  425. package/surfaces/skills/procedures/setup.md +452 -0
  426. package/surfaces/skills/procedures/work.md +134 -0
@@ -0,0 +1,14 @@
1
+ import type { CockpitConfig } from '../schema.js';
2
+ import { type EnvironmentDiagnostic, RefusalError } from './contract.js';
3
+ export type DeclaredRuntime = 'compose' | 'none';
4
+ export declare function declaredRuntime(environment: Pick<CockpitConfig['environment'], 'compose_files'>): DeclaredRuntime;
5
+ export declare function declaresNothingToRun(environment: Pick<CockpitConfig['environment'], 'compose_files' | 'machine'>): boolean;
6
+ /** The one refusal every runtime command gives a cockpit that declares no environment. */
7
+ export declare function runtimeNotDeclared(target: string): EnvironmentDiagnostic;
8
+ /** A service named on the command line that the stack does not declare: a wrong name, not a runtime failure. */
9
+ export declare function serviceNotDeclared(service: string, declared: readonly string[]): EnvironmentDiagnostic;
10
+ /** Carries a declaration refusal through owners whose only failure channel is a thrown error. */
11
+ export declare class DeclarationRefusalError extends RefusalError {
12
+ readonly diagnostic: EnvironmentDiagnostic;
13
+ constructor(diagnostic: EnvironmentDiagnostic);
14
+ }
@@ -0,0 +1,39 @@
1
+ import { ENVIRONMENT_CODES, RefusalError } from './contract.js';
2
+ export function declaredRuntime(environment) {
3
+ return environment.compose_files.length > 0 ? 'compose' : 'none';
4
+ }
5
+ // A machine floor alone still has something to measure: preflight checks this laptop against it,
6
+ // so only a cockpit that declares no runtime and no floor has nothing for runtime commands to do.
7
+ export function declaresNothingToRun(environment) {
8
+ return declaredRuntime(environment) === 'none' && environment.machine === undefined;
9
+ }
10
+ /** The one refusal every runtime command gives a cockpit that declares no environment. */
11
+ export function runtimeNotDeclared(target) {
12
+ return {
13
+ severity: 'error',
14
+ // A literal, so the diagnostic inventory captures the fix beside the code.
15
+ code: 'ENVIRONMENT_NOT_DECLARED',
16
+ message: 'this cockpit declares no runtime environment, so there is nothing to start, stop, observe or measure; sync and check publish and verify the harness surfaces only',
17
+ target,
18
+ fix: 'declare environment.compose_files = ["compose.yml"] to run your Compose file (for a small app with none, npx --no cockpit init <cockpit root> --scaffold-compose <app dir> --port <port> writes a starting one), then run npx --no cockpit sync --config <your cockpit.toml>',
19
+ };
20
+ }
21
+ /** A service named on the command line that the stack does not declare: a wrong name, not a runtime failure. */
22
+ export function serviceNotDeclared(service, declared) {
23
+ return {
24
+ severity: 'error',
25
+ code: 'SERVICE_NOT_DECLARED',
26
+ message: `this stack declares no service ${service}; it declares ${declared.length === 0 ? 'no services' : declared.join(', ')}`,
27
+ target: service,
28
+ fix: 'rerun with --service set to one of the declared services',
29
+ };
30
+ }
31
+ /** Carries a declaration refusal through owners whose only failure channel is a thrown error. */
32
+ export class DeclarationRefusalError extends RefusalError {
33
+ diagnostic;
34
+ constructor(diagnostic) {
35
+ super(diagnostic.message);
36
+ this.name = 'DeclarationRefusalError';
37
+ this.diagnostic = diagnostic;
38
+ }
39
+ }
@@ -0,0 +1,29 @@
1
+ import type { ExecuteProbeOutcome } from '../environment-exec/execute.js';
2
+ import { type DownCommandAdapters, type ResetCommandAdapters } from './application/lifecycle-context.js';
3
+ import { type ExecutionStep } from './contract.js';
4
+ import type { RuntimeMeasurementProbeAuthority } from './runtime.js';
5
+ export interface DestructiveCompositionInput {
6
+ readonly configPath: string;
7
+ readonly env: Readonly<Record<string, string | undefined>>;
8
+ readonly sessionId: string;
9
+ readonly timeoutMs: number;
10
+ readonly dockerContext: string;
11
+ readonly activeProfiles?: readonly string[];
12
+ readonly runtimeMeasurementProbeAuthority?: RuntimeMeasurementProbeAuthority | (() => RuntimeMeasurementProbeAuthority);
13
+ }
14
+ type Executor = (step: ExecutionStep) => Promise<ExecuteProbeOutcome>;
15
+ export type DestructiveDaemonSelection = Readonly<{
16
+ kind: 'complete';
17
+ dockerContext: string;
18
+ }> | Readonly<{
19
+ kind: 'refusal';
20
+ adapters: DestructiveAdapters;
21
+ }>;
22
+ /**
23
+ * Names the one Docker context down and reset delete from, fixed before any adapter exists so
24
+ * every discovery and deletion step of the command addresses that context.
25
+ */
26
+ export declare function selectDestructiveDaemon(env: Readonly<Record<string, string | undefined>>, timeoutMs: number, execute: Executor): Promise<DestructiveDaemonSelection>;
27
+ type DestructiveAdapters = DownCommandAdapters & ResetCommandAdapters;
28
+ export declare function createDestructiveCommandAdapters(rawInput: DestructiveCompositionInput, execute: Executor): DestructiveAdapters;
29
+ export {};
@@ -0,0 +1,333 @@
1
+ import { resolve } from 'node:path';
2
+ import { admitLocalDockerEndpoint } from './docker-endpoint.js';
3
+ import { selectLocalDockerDaemon } from './docker-daemon.js';
4
+ import { cockpitCommand } from '../fix-catalogue.js';
5
+ import { loadCockpitConfig, consumeLoadedConfigProjection } from '../config/load.js';
6
+ import { issueDestructiveRunContext, noticeLifecycleRun, } from './application/lifecycle-context.js';
7
+ import { ENVIRONMENT_CODES, forwardedRefusal } from './contract.js';
8
+ import { decodeCoordinationRecord, liveHolderMessage, observeProcessStart, processHost, readActiveStackInventory, releaseDeadSessionHolders } from './claims.js';
9
+ import { declaresNothingToRun, runtimeNotDeclared } from './declaration.js';
10
+ import { resolveDockerExecutable, resolvePathRemovalExecutable } from './executable.js';
11
+ import { composeProjectName } from './identity.js';
12
+ import { createLifecycleCommandAdapters } from './lifecycle-composition.js';
13
+ import { deriveEntrypoints, observeRetainedPortFamily, projectRetainedPortFamilyResult, } from './ports.js';
14
+ import { discoverReclaim } from './reclaim.js';
15
+ import { readState } from './state.js';
16
+ import { earlierNameRefusalMessage, findStackUnderEarlierName } from './lifecycle-stage.js';
17
+ function captureInput(value) {
18
+ try {
19
+ if (!value || typeof value !== 'object' || Array.isArray(value))
20
+ return undefined;
21
+ const descriptors = Object.getOwnPropertyDescriptors(value);
22
+ const keys = ['configPath', 'env', 'sessionId', 'timeoutMs', 'dockerContext'];
23
+ const optionalKeys = ['activeProfiles', 'runtimeMeasurementProbeAuthority'].filter((key) => descriptors[key] !== undefined);
24
+ if (Reflect.ownKeys(descriptors).length !== keys.length + optionalKeys.length
25
+ || keys.some((key) => !descriptors[key] || !('value' in descriptors[key]))
26
+ || optionalKeys.some((key) => !('value' in descriptors[key])))
27
+ return undefined;
28
+ const configPath = descriptors.configPath.value;
29
+ const rawEnvironment = descriptors.env.value;
30
+ const sessionId = descriptors.sessionId.value;
31
+ const timeoutMs = descriptors.timeoutMs.value;
32
+ const dockerContext = descriptors.dockerContext.value;
33
+ const activeProfiles = descriptors.activeProfiles?.value;
34
+ const runtimeMeasurementProbeAuthority = descriptors.runtimeMeasurementProbeAuthority?.value;
35
+ if (typeof configPath !== 'string' || configPath.length === 0 || configPath.includes('\0')
36
+ || typeof sessionId !== 'string' || sessionId.length === 0 || sessionId.includes('\0')
37
+ || typeof timeoutMs !== 'number' || !Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 30_000
38
+ || typeof dockerContext !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/.test(dockerContext)
39
+ || activeProfiles !== undefined && (!Array.isArray(activeProfiles) || activeProfiles.length > 64
40
+ || new Set(activeProfiles).size !== activeProfiles.length
41
+ || activeProfiles.some((profile) => typeof profile !== 'string' || !/^[a-z0-9][a-z0-9_.-]*$/.test(profile)))
42
+ || !rawEnvironment || typeof rawEnvironment !== 'object' || Array.isArray(rawEnvironment))
43
+ return undefined;
44
+ const env = {};
45
+ for (const [name, entry] of Object.entries(rawEnvironment)) {
46
+ if (name.length === 0 || name.includes('\0') || name.includes('=')
47
+ || entry !== undefined && (typeof entry !== 'string' || entry.includes('\0')))
48
+ return undefined;
49
+ env[name] = entry;
50
+ }
51
+ // A local DOCKER_HOST is selected through Docker's `default` context, which reports that
52
+ // endpoint; dropping it addressed whatever the default context named instead. TLS and
53
+ // remote hosts stay refused.
54
+ if (env.DOCKER_HOST !== undefined && (admitLocalDockerEndpoint(env.DOCKER_HOST) === undefined
55
+ || dockerContext !== 'default' || env.DOCKER_CONTEXT !== undefined)
56
+ || env.DOCKER_TLS_VERIFY !== undefined || env.DOCKER_CERT_PATH !== undefined
57
+ || env.DOCKER_CONTEXT !== undefined && env.DOCKER_CONTEXT !== dockerContext)
58
+ return undefined;
59
+ return {
60
+ configPath: resolve(configPath),
61
+ env,
62
+ sessionId,
63
+ timeoutMs,
64
+ dockerContext,
65
+ ...(activeProfiles === undefined ? {} : { activeProfiles: [...activeProfiles].sort() }),
66
+ ...(runtimeMeasurementProbeAuthority === undefined ? {} : { runtimeMeasurementProbeAuthority }),
67
+ };
68
+ }
69
+ catch { // A throwing accessor or proxy trap makes the input malformed; the caller refuses it.
70
+ return undefined;
71
+ }
72
+ }
73
+ function refusal(target, message = 'destructive run authority is unavailable or does not match current state', code = ENVIRONMENT_CODES.LIFECYCLE_EVIDENCE_INVALID) {
74
+ return forwardedRefusal([{ severity: 'error', code, message, target }]);
75
+ }
76
+ function sameSource(left, right) {
77
+ return left.path === right.path && left.byteLength === right.byteLength && left.sha256 === right.sha256;
78
+ }
79
+ function executionEnvironment(env) {
80
+ return Object.fromEntries(Object.entries(env)
81
+ .filter((entry) => (['PATH', 'TMPDIR', 'LANG', 'LC_ALL'].includes(entry[0]) && typeof entry[1] === 'string'))
82
+ .sort(([left], [right]) => left.localeCompare(right)));
83
+ }
84
+ /**
85
+ * Names the one Docker context down and reset delete from, fixed before any adapter exists so
86
+ * every discovery and deletion step of the command addresses that context.
87
+ */
88
+ export async function selectDestructiveDaemon(env, timeoutMs, execute) {
89
+ const daemon = await selectLocalDockerDaemon(env, timeoutMs, execute, { command: 'down and reset', localOnly: 'down and reset never delete from a remote daemon' });
90
+ return daemon.kind === 'refusal'
91
+ ? { kind: 'refusal', adapters: refusingAdapters(execute, daemon.diagnostic) }
92
+ : { kind: 'complete', dockerContext: daemon.dockerContext };
93
+ }
94
+ async function observeReclaim(input, context, cwd, execute) {
95
+ const [runtimeExecutable, pathExecutable] = await Promise.all([
96
+ resolveDockerExecutable(input.env),
97
+ resolvePathRemovalExecutable(),
98
+ ]);
99
+ if (runtimeExecutable.state !== 'available' || pathExecutable.state !== 'available')
100
+ return undefined;
101
+ const discovery = await discoverReclaim({
102
+ executable: runtimeExecutable.value,
103
+ cwd,
104
+ env: executionEnvironment(input.env),
105
+ stackId: context.stackId,
106
+ cockpitId: context.cockpitId,
107
+ timeoutMs: input.timeoutMs,
108
+ context: input.dockerContext,
109
+ ...(input.env.DOCKER_HOST === undefined ? {} : { host: input.env.DOCKER_HOST }),
110
+ }, execute);
111
+ if (!discovery)
112
+ return undefined;
113
+ if ('diagnostics' in discovery)
114
+ return forwardedRefusal(discovery.diagnostics);
115
+ return { discovery, runtimeExecutable, pathExecutable };
116
+ }
117
+ // Adapters that load nothing. A cockpit with no runtime has nothing to stop or reset; that
118
+ // outranks any runtime-input problem, so it is reported before `reason` or the generic refusal.
119
+ function refusingAdapters(execute, reason) {
120
+ return {
121
+ load: async (request) => {
122
+ const loaded = typeof request?.configPath === 'string' ? await loadCockpitConfig(request.configPath) : undefined;
123
+ const diagnostic = loaded?.kind === 'complete' && declaresNothingToRun(loaded.result.config.environment)
124
+ ? runtimeNotDeclared(loaded.result.source.path) : reason;
125
+ return diagnostic === undefined ? refusal(request?.configPath ?? 'destructive')
126
+ : { kind: 'refusal', status: 2, result: null, diagnostics: [diagnostic] };
127
+ },
128
+ observe: async () => undefined,
129
+ execute,
130
+ };
131
+ }
132
+ export function createDestructiveCommandAdapters(rawInput, execute) {
133
+ const input = captureInput(rawInput);
134
+ if (!input || typeof execute !== 'function')
135
+ return refusingAdapters(execute);
136
+ const lifecycleInput = {
137
+ configPath: input.configPath,
138
+ env: input.env.DOCKER_HOST === undefined ? { ...input.env, DOCKER_CONTEXT: input.dockerContext } : input.env,
139
+ sessionId: input.sessionId,
140
+ timeoutMs: input.timeoutMs,
141
+ ...(input.activeProfiles === undefined ? {} : { activeProfiles: input.activeProfiles }),
142
+ ...(input.runtimeMeasurementProbeAuthority === undefined ? {} : { runtimeMeasurementProbeAuthority: input.runtimeMeasurementProbeAuthority }),
143
+ };
144
+ const lifecycle = createLifecycleCommandAdapters(lifecycleInput, execute);
145
+ const issued = new WeakMap();
146
+ // The checkout root runtime readiness resolved for each context, so a reclaim-only
147
+ // observation reuses it instead of re-measuring the runtime.
148
+ const readinessRoots = new WeakMap();
149
+ // Config, coordination and reclaim discovery, the evidence each destructive step re-reads.
150
+ const observeReclaimTargets = async (context, configuration, cwd) => {
151
+ const coordinationAddress = context.namespace.paths.coordination(context.stackId);
152
+ const stored = await readState(coordinationAddress);
153
+ if (stored.kind !== 'complete')
154
+ return undefined;
155
+ const reclaim = await observeReclaim(input, context, cwd, execute);
156
+ if (!reclaim)
157
+ return undefined;
158
+ if ('diagnostics' in reclaim)
159
+ return reclaim;
160
+ // Policy rows select installers. They do not identify an instantiated cache or
161
+ // its owning root, so treating their logical volume names as cache authority
162
+ // could authorize deletion of unrelated data.
163
+ const declaredCacheIds = [];
164
+ const dependencyCaches = [];
165
+ const common = {
166
+ stackId: context.stackId,
167
+ cockpitId: context.cockpitId,
168
+ configSha256: context.runtimeSha256,
169
+ coordinationRecord: stored.value,
170
+ coordinationAddress,
171
+ requesterHolderId: context.holderId,
172
+ declaredCacheIds,
173
+ discovery: reclaim.discovery,
174
+ cwd,
175
+ env: executionEnvironment(input.env),
176
+ timeoutMs: input.timeoutMs,
177
+ };
178
+ return {
179
+ instance: context.instance,
180
+ down: {
181
+ ...common,
182
+ executable: reclaim.runtimeExecutable.value,
183
+ dependencyCaches,
184
+ pathExecutable: reclaim.pathExecutable.value,
185
+ },
186
+ reset: {
187
+ ...common,
188
+ expectedCoordinationRevision: stored.value.revision,
189
+ resettableVolumes: [...configuration.config.environment.resettable_volumes],
190
+ composeProject: composeProjectName({ cockpitName: configuration.config.cockpit.name, stackId: context.stackId }),
191
+ generatedHostPaths: configuration.config.environment.generated_host_paths.map((declaration) => ({
192
+ root: cwd,
193
+ path: resolve(cwd, declaration),
194
+ declaration,
195
+ })),
196
+ runtimeExecutable: reclaim.runtimeExecutable.value,
197
+ pathExecutable: reclaim.pathExecutable.value,
198
+ },
199
+ };
200
+ };
201
+ const currentConfiguration = async (context) => {
202
+ const loaded = await loadCockpitConfig(context.configPath);
203
+ if (loaded.kind === 'refusal')
204
+ return loaded;
205
+ if (loaded.kind !== 'complete')
206
+ return undefined;
207
+ const configuration = consumeLoadedConfigProjection(loaded.result);
208
+ return configuration && sameSource(context.source, configuration.source) ? configuration : undefined;
209
+ };
210
+ return {
211
+ async load(request) {
212
+ if (request.configPath !== resolve(input.configPath))
213
+ return refusal(request.configPath);
214
+ const loaded = await lifecycle.load(request);
215
+ if (loaded.kind !== 'complete') {
216
+ return loaded.kind === 'refusal' ? loaded : refusal(request.configPath);
217
+ }
218
+ const context = loaded.result;
219
+ const reaped = await releaseDeadSessionHolders({
220
+ namespace: context.namespace, stackId: context.stackId,
221
+ successor: { holderId: context.holderId, checkoutId: context.checkoutId },
222
+ now: new Date().toISOString(), observe: (pid) => observeProcessStart(pid, processHost(execute)),
223
+ });
224
+ if (reaped.kind === 'refusal')
225
+ return forwardedRefusal(reaped.diagnostics);
226
+ // A restore released above leaves data that may be half applied; the warning rides on
227
+ // whatever this load returns.
228
+ let claim;
229
+ const outcome = await (async () => {
230
+ let inventory = await readActiveStackInventory(context.namespace);
231
+ if (inventory.kind !== 'complete')
232
+ return refusal(context.stackId);
233
+ const currentRecord = inventory.value.find(({ stackId }) => stackId === context.stackId)?.record;
234
+ if (!currentRecord?.holders.some(({ holderId, checkoutId }) => (holderId === context.holderId && checkoutId === context.checkoutId))) {
235
+ // The active inventory omits a stack whose final holder released it, so the
236
+ // coordination record itself says whether this stack ever ran.
237
+ const stored = await readState(context.namespace.paths.coordination(context.stackId));
238
+ if (stored.kind === 'missing') {
239
+ const earlier = await findStackUnderEarlierName({ namespace: context.namespace, cockpitId: context.cockpitId, checkoutId: context.checkoutId });
240
+ if (earlier.kind === 'refusal')
241
+ return refusal(earlier.target, earlier.message, earlier.code);
242
+ if (earlier.name !== undefined)
243
+ return refusal(context.stackId, earlierNameRefusalMessage(context.source.path, earlier.name), ENVIRONMENT_CODES.STACK_RECORDED_UNDER_EARLIER_NAME);
244
+ return refusal(context.stackId, `this checkout has never claimed the stack, so down and reset have nothing to act on; run \`${cockpitCommand('up')}\` first`);
245
+ }
246
+ const coordination = stored.kind === 'complete' ? decodeCoordinationRecord(stored.value, context.stackId) : undefined;
247
+ if (!coordination)
248
+ return refusal(context.stackId);
249
+ if (coordination.holders.length > 0) {
250
+ return refusal(context.stackId, liveHolderMessage(coordination.holders), ENVIRONMENT_CODES.CLAIM_CO_TENANT);
251
+ }
252
+ // `sleep` and an ended `session` release the final holder and stop the runtime,
253
+ // but its containers, networks and images remain. Claiming the stack here, as
254
+ // `up` would without starting anything, gives down the holder authority to retire
255
+ // them; refusing sent the operator to start a stack only to remove it. The
256
+ // application gives the claim back when the run reserves no drain.
257
+ let claimRefusal;
258
+ claim = await lifecycle.withAcquiredPorts(context, async ({ leaseResult }) => leaseResult, (diagnostics) => { claimRefusal = diagnostics; return undefined; });
259
+ if (claimRefusal)
260
+ return forwardedRefusal(claimRefusal);
261
+ if (claim?.kind !== 'complete' || claim.change !== 'acquired')
262
+ return refusal(context.stackId, 'the stopped stack could not be claimed for down or reset');
263
+ inventory = await readActiveStackInventory(context.namespace);
264
+ if (inventory.kind !== 'complete')
265
+ return refusal(context.stackId);
266
+ }
267
+ const claimInventory = inventory.value.flatMap(({ stackId, record }) => (record.holders.map(({ checkoutId }) => ({ stackId, checkoutId }))));
268
+ const current = { stackId: context.stackId, checkoutId: context.checkoutId };
269
+ const destructive = issueDestructiveRunContext({
270
+ lifecycle: context,
271
+ instance: {
272
+ launcher: current,
273
+ claimInventory,
274
+ },
275
+ ...claim ? { claim } : {},
276
+ });
277
+ if (destructive.kind === 'complete')
278
+ issued.set(destructive.result, context);
279
+ return destructive;
280
+ })();
281
+ return outcome;
282
+ },
283
+ async observe(context) {
284
+ const lifecycleContext = issued.get(context);
285
+ if (!lifecycleContext)
286
+ return undefined;
287
+ const configuration = await currentConfiguration(context);
288
+ if (!configuration || 'diagnostics' in configuration)
289
+ return configuration;
290
+ const retained = await observeRetainedPortFamily({
291
+ namespace: context.namespace,
292
+ stackId: context.stackId,
293
+ holderId: context.holderId,
294
+ checkoutId: context.checkoutId,
295
+ config: 'recorded',
296
+ });
297
+ if (retained.kind !== 'complete')
298
+ return forwardedRefusal(retained.diagnostics);
299
+ const entrypoints = deriveEntrypoints({
300
+ lease: retained.lease,
301
+ declarations: context.entrypointDerivatives,
302
+ });
303
+ if (entrypoints.kind !== 'complete')
304
+ return forwardedRefusal(entrypoints.diagnostics);
305
+ const ports = await projectRetainedPortFamilyResult({ retainedResult: retained, entrypointResult: entrypoints });
306
+ if (!ports)
307
+ return undefined;
308
+ let runtimeRefusal;
309
+ const readiness = await lifecycle.withRuntimeReadiness(lifecycleContext, async (value) => value, ports, (diagnostics) => { runtimeRefusal = forwardedRefusal(diagnostics); return undefined; }, 'teardown');
310
+ if (runtimeRefusal)
311
+ return runtimeRefusal;
312
+ if (!readiness)
313
+ return undefined;
314
+ readinessRoots.set(context, readiness.topology.cwd);
315
+ const targets = await observeReclaimTargets(context, configuration, readiness.topology.cwd);
316
+ if (!targets || 'diagnostics' in targets)
317
+ return targets;
318
+ return { ...targets, runtime: readiness.lifecycle, ports };
319
+ },
320
+ // Runtime readiness proves the runtime the plan was made for; the steps of a drain that
321
+ // plan already reserved need only fresh reclaim evidence against the same checkout root.
322
+ async observeReclaim(context) {
323
+ const cwd = readinessRoots.get(context);
324
+ if (!issued.has(context) || cwd === undefined)
325
+ return undefined;
326
+ const configuration = await currentConfiguration(context);
327
+ if (!configuration || 'diagnostics' in configuration)
328
+ return configuration;
329
+ return observeReclaimTargets(context, configuration, cwd);
330
+ },
331
+ execute,
332
+ };
333
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Names the one local Docker daemon a command addresses, before the command does any work, so
3
+ * `down`, `reset` and `runtime measure` choose a daemon by one rule. It observes Docker's own
4
+ * context configuration through the supplied `execute`; it never spawns a process itself.
5
+ */
6
+ import { type ExecuteProbeOutcome } from '../environment-exec/execute.js';
7
+ import { type Diagnostic, type ExecutionStep } from './contract.js';
8
+ type Executor = (step: ExecutionStep) => Promise<ExecuteProbeOutcome>;
9
+ export type LocalDockerDaemon = Readonly<{
10
+ kind: 'complete';
11
+ dockerContext: string;
12
+ endpoint: string;
13
+ source: string;
14
+ }> | Readonly<{
15
+ kind: 'refusal';
16
+ diagnostic: Diagnostic;
17
+ }>;
18
+ export interface DaemonUse {
19
+ readonly command: string;
20
+ readonly localOnly: string;
21
+ }
22
+ /**
23
+ * A local DOCKER_HOST is taken as given, through Docker's `default` context. Otherwise the context
24
+ * is the one DOCKER_CONTEXT names or, with neither set, the active one, read once here so the
25
+ * caller can pin it for every later step: reading it per step lets a `docker context use` mid-run
26
+ * point one step at one daemon and the next at another. Either way the context must resolve to a
27
+ * local Unix socket, so a remote daemon is refused however it was named.
28
+ */
29
+ export declare function selectLocalDockerDaemon(env: Readonly<Record<string, string | undefined>>, timeoutMs: number, execute: Executor, use: DaemonUse): Promise<LocalDockerDaemon>;
30
+ export {};
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Names the one local Docker daemon a command addresses, before the command does any work, so
3
+ * `down`, `reset` and `runtime measure` choose a daemon by one rule. It observes Docker's own
4
+ * context configuration through the supplied `execute`; it never spawns a process itself.
5
+ */
6
+ import { authenticatedExecutionOutcome } from '../environment-exec/execute.js';
7
+ import { ENVIRONMENT_CODES } from './contract.js';
8
+ import { admitLocalDockerEndpoint } from './docker-endpoint.js';
9
+ import { resolveDockerExecutable } from './executable.js';
10
+ const DOCKER_CONTEXT_NAME = /^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/;
11
+ async function readContext(execute, executable, env, timeoutMs, id, args) {
12
+ const step = {
13
+ id,
14
+ argv: [executable.canonicalPath, ...args],
15
+ argv0: executable.invocationPath,
16
+ // The context lookup reads only Docker's client configuration, and the config's own
17
+ // directory may not exist yet; a missing config is reported by the command, not here.
18
+ cwd: '/', env, timeoutMs,
19
+ stdoutLimitBytes: 1_024, stderrLimitBytes: 4_096,
20
+ paths: [], ports: [],
21
+ labels: { purpose: id },
22
+ expected: [],
23
+ consumedFiles: [{
24
+ path: executable.canonicalPath, sha256: executable.sha256,
25
+ maxBytes: 536_870_912, argvIndexes: [0], executable: true,
26
+ executionMode: executable.executionMode,
27
+ }],
28
+ filesystemChecks: [],
29
+ compensation: [],
30
+ };
31
+ const outcome = authenticatedExecutionOutcome(await execute(step), step);
32
+ if (outcome?.kind !== 'complete' || outcome.stderr.byteLength !== 0)
33
+ return undefined;
34
+ const text = outcome.stdout.toString('utf8');
35
+ // Docker's final line ending is framing; trimming more would rewrite the endpoint's identity.
36
+ return Buffer.from(text, 'utf8').equals(outcome.stdout) ? text.replace(/\r?\n$/, '') : undefined;
37
+ }
38
+ /**
39
+ * A local DOCKER_HOST is taken as given, through Docker's `default` context. Otherwise the context
40
+ * is the one DOCKER_CONTEXT names or, with neither set, the active one, read once here so the
41
+ * caller can pin it for every later step: reading it per step lets a `docker context use` mid-run
42
+ * point one step at one daemon and the next at another. Either way the context must resolve to a
43
+ * local Unix socket, so a remote daemon is refused however it was named.
44
+ */
45
+ export async function selectLocalDockerDaemon(env, timeoutMs, execute, use) {
46
+ const refuse = (code, message, target) => ({
47
+ kind: 'refusal', diagnostic: { severity: 'error', code, message, target },
48
+ });
49
+ if (env.DOCKER_HOST !== undefined) {
50
+ return admitLocalDockerEndpoint(env.DOCKER_HOST) === undefined
51
+ ? refuse('CLI_USAGE_INVALID', `DOCKER_HOST is not a local Docker endpoint, and ${use.localOnly}; fix: unset DOCKER_HOST to use the active Docker context, or set DOCKER_HOST to a local Unix socket`, 'DOCKER_HOST')
52
+ : { kind: 'complete', dockerContext: 'default', endpoint: env.DOCKER_HOST, source: 'DOCKER_HOST' };
53
+ }
54
+ const named = env.DOCKER_CONTEXT;
55
+ if (named !== undefined && !DOCKER_CONTEXT_NAME.test(named)) {
56
+ return refuse('CLI_USAGE_INVALID', `DOCKER_CONTEXT ${JSON.stringify(named.slice(0, 128))} is not a Docker context name; fix: set it to a local context from \`docker context ls\`, or unset it to use the active context`, 'DOCKER_CONTEXT');
57
+ }
58
+ const executable = await resolveDockerExecutable(env);
59
+ if (executable.state !== 'available')
60
+ return refuse(ENVIRONMENT_CODES.RUNTIME_UNAVAILABLE, executable.reason, 'docker');
61
+ // Only the search path: Docker then reads the operator's own context store, as `up` does.
62
+ const stepEnv = { ...(env.PATH === undefined ? {} : { PATH: env.PATH }) };
63
+ const context = named ?? await readContext(execute, executable.value, stepEnv, timeoutMs, 'runtime:daemon:context', ['context', 'show']);
64
+ if (context === undefined || !DOCKER_CONTEXT_NAME.test(context)) {
65
+ return refuse(ENVIRONMENT_CODES.RUNTIME_UNAVAILABLE, `${use.command} could not read the active Docker context from \`docker context show\`; fix: run \`docker context show\` to see why, or set DOCKER_CONTEXT to the local context to use`, 'docker context');
66
+ }
67
+ const which = named === undefined ? `active Docker context ${context}` : `Docker context ${context} named by DOCKER_CONTEXT`;
68
+ const target = `docker context ${context}`;
69
+ const endpoint = await readContext(execute, executable.value, stepEnv, timeoutMs, 'runtime:daemon:endpoint', ['context', 'inspect', context, '--format', '{{.Endpoints.docker.Host}}']);
70
+ if (endpoint === undefined) {
71
+ return refuse(ENVIRONMENT_CODES.RUNTIME_UNAVAILABLE, `${use.command} could not read the endpoint of the ${which}; fix: run \`docker context inspect ${context}\` to see why`, target);
72
+ }
73
+ if (admitLocalDockerEndpoint(endpoint) === undefined) {
74
+ const select = named === undefined ? 'select a local context with `docker context use <name>`' : 'set DOCKER_CONTEXT to a local context, or unset it';
75
+ return refuse(ENVIRONMENT_CODES.RUNTIME_UNAVAILABLE, `the ${which} points at ${endpoint}, not a local Unix socket, and ${use.localOnly}; fix: ${select}, then retry`, target);
76
+ }
77
+ return { kind: 'complete', dockerContext: context, endpoint, source: target };
78
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Classifies local Docker transports without rewriting endpoint identity. Context observation and
3
+ * execution authentication remain with the runtime owners; syntax alone grants neither.
4
+ */
5
+ export declare function parseLocalDockerEndpoint(value: unknown): Readonly<{
6
+ transport: 'unix';
7
+ endpoint: string;
8
+ }> | undefined;
9
+ /** Admits transport syntax for this process without granting native execution or state authority. */
10
+ export declare function admitLocalDockerEndpoint(value: unknown): ReturnType<typeof parseLocalDockerEndpoint>;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Classifies local Docker transports without rewriting endpoint identity. Context observation and
3
+ * execution authentication remain with the runtime owners; syntax alone grants neither.
4
+ */
5
+ export function parseLocalDockerEndpoint(value) {
6
+ // Docker trims host input. Reject that alias rather than bind authority to a different string.
7
+ if (typeof value !== 'string' || value.trim() !== value || /[\u0000-\u001f\u007f]/.test(value))
8
+ return undefined;
9
+ if (!value.startsWith('unix://'))
10
+ return undefined;
11
+ const path = value.slice('unix://'.length);
12
+ // Docker passes this raw pathname to the socket transport: spaces and URI punctuation are literal.
13
+ return path.startsWith('/') && !path.startsWith('//') && path.length > 1
14
+ ? { transport: 'unix', endpoint: value } : undefined;
15
+ }
16
+ /** Admits transport syntax for this process without granting native execution or state authority. */
17
+ export function admitLocalDockerEndpoint(value) {
18
+ return process.platform === 'darwin' || process.platform === 'linux' ? parseLocalDockerEndpoint(value) : undefined;
19
+ }
@@ -0,0 +1,46 @@
1
+ import { type ExecuteProbeOutcome } from '../environment-exec/execute.js';
2
+ import { type EnvironmentObservation, type ExecutionStep, type JsonSnapshot, type StackId } from './contract.js';
3
+ export declare const VARLOCK_INSTALL_URL = "https://varlock.dev";
4
+ export declare const observationDeclarations: readonly [{
5
+ readonly id: 'env-schema';
6
+ readonly owner: "env-schema-observation";
7
+ readonly postures: readonly ["environment"];
8
+ readonly stages: readonly [{
9
+ readonly stage: 'bootstrap';
10
+ readonly disposition: 'required';
11
+ }, {
12
+ readonly stage: 'steady';
13
+ readonly disposition: 'required';
14
+ }];
15
+ readonly code: "ENV_SCHEMA_UNHEALTHY";
16
+ readonly isIssued: typeof isEnvSchemaObservation;
17
+ readonly issuedAt: typeof observationIssuedAt;
18
+ }];
19
+ declare function isEnvSchemaObservation(value: unknown): value is EnvironmentObservation;
20
+ declare function observationIssuedAt(value: unknown): number | undefined;
21
+ export interface EnvSchemaSibling {
22
+ readonly slug: string;
23
+ /** Directory as declared in cockpit.toml; only used to tell the operator where to run varlock. */
24
+ readonly dir: string;
25
+ readonly root: string;
26
+ }
27
+ /**
28
+ * Observes every sibling that contains `.env.schema`. Returns one aggregate observation per
29
+ * stack, with the per-sibling status in its measured value. `env` is the caller's environment:
30
+ * a secret provider may need its own variables to resolve.
31
+ */
32
+ export declare function observeEnvSchemas(input: {
33
+ readonly stackId: StackId;
34
+ readonly siblings: readonly EnvSchemaSibling[];
35
+ readonly env: Readonly<Record<string, string | undefined>>;
36
+ readonly timeoutMs: number;
37
+ }, options: {
38
+ readonly execute: (step: ExecutionStep) => Promise<ExecuteProbeOutcome>;
39
+ }): Promise<readonly EnvironmentObservation[]>;
40
+ /** Siblings whose schema was skipped because varlock is not installed, from a passing row. */
41
+ export declare function envSchemaToolMissing(check: {
42
+ readonly owner: string;
43
+ readonly verdict: string;
44
+ readonly measured?: JsonSnapshot;
45
+ }): readonly string[];
46
+ export {};