@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,235 @@
1
+ import type { ExecuteProbeOutcome, ForegroundProcessInput, ForegroundProcessOutcome } from '../../environment-exec/execute.js';
2
+ import { type CheckoutId, type EnvironmentCommandOutcome, type EnvironmentDiagnostic, type EnvironmentObservation, type ExecutionStep, type HolderId, type SourceProvenance, type StackId } from '../contract.js';
3
+ import type { ExecutableResolution } from '../executable.js';
4
+ import { CockpitConfig, type EntrypointDerivative } from '../../schema.js';
5
+ import { type StateNamespace } from '../state.js';
6
+ import type { RuntimeInputs, LifecycleStageProjection } from '../lifecycle-stage.js';
7
+ import { type ConsumedSetupCheckoutObservation, type SetupCheckoutProjection } from '../setup-observation.js';
8
+ import { type LoadedConfigProjection } from '../../config/load.js';
9
+ import { type RegistryDerivationResult } from '../../registry-derivation.js';
10
+ import type { LeasePortFamilyResult, PortFamilyConfig, PortLeaseProjection } from '../ports.js';
11
+ import type { RuntimeLifecycleProjection, RuntimeTopologyEvidence } from '../runtime.js';
12
+ import type { PlanResetInput, PlanTeardownInput, ResetTargetInput } from '../reclaim.js';
13
+ import { type SelectDestructiveInstanceInput } from '../instance.js';
14
+ export interface UpCommandInput {
15
+ readonly configPath: string;
16
+ }
17
+ export interface SleepCommandInput {
18
+ readonly configPath: string;
19
+ }
20
+ export interface SessionCommandInput {
21
+ readonly configPath: string;
22
+ readonly argv: readonly [string, ...string[]];
23
+ readonly cwd: string;
24
+ readonly env: Readonly<Record<string, string>>;
25
+ }
26
+ export interface LifecycleRunContext {
27
+ readonly configPath: string;
28
+ readonly source: SourceProvenance;
29
+ /** Identifies the stack: its ownership labels, generation, saved progress and data history. */
30
+ readonly runtimeSha256: string;
31
+ readonly namespace: StateNamespace;
32
+ readonly cockpitId: ConsumedSetupCheckoutObservation['cockpitId'];
33
+ readonly checkoutId: CheckoutId;
34
+ readonly stackId: StackId;
35
+ readonly holderId: HolderId;
36
+ readonly ports: PortFamilyConfig;
37
+ readonly entrypointDerivatives: readonly EntrypointDerivative[];
38
+ }
39
+ export interface LifecycleRunContextInput {
40
+ readonly configPath: string;
41
+ readonly checkout: SetupCheckoutProjection;
42
+ readonly configuration: LoadedConfigProjection;
43
+ readonly namespace: StateNamespace;
44
+ readonly stackId: StackId;
45
+ readonly holderId: HolderId;
46
+ readonly sessionId: string;
47
+ }
48
+ export interface RuntimeReadiness {
49
+ readonly topology: RuntimeTopologyEvidence;
50
+ readonly lifecycle: RuntimeLifecycleProjection;
51
+ readonly hostObservations: readonly EnvironmentObservation[];
52
+ readonly runtimeObservations: readonly EnvironmentObservation[];
53
+ /** The digest of each file this runtime is started from, by the name a person edits. */
54
+ readonly inputs: RuntimeInputs;
55
+ /** The Compose profiles this runtime activates, sorted. */
56
+ readonly activeProfiles: readonly string[];
57
+ }
58
+ export interface AcquiredPorts {
59
+ readonly leaseResult: LeasePortFamilyResult;
60
+ readonly projection: PortLeaseProjection;
61
+ readonly retainOnFailure: () => void;
62
+ }
63
+ export type ReadinessRefusal<T> = (diagnostics: readonly EnvironmentDiagnostic[]) => T;
64
+ export type RuntimeReadinessPurpose = 'teardown';
65
+ interface LifecycleCommandAdapters {
66
+ load(input: UpCommandInput | SleepCommandInput): Promise<EnvironmentCommandOutcome<LifecycleRunContext>>;
67
+ execute(step: ExecutionStep): Promise<ExecuteProbeOutcome>;
68
+ withRuntimeReadiness<T>(context: LifecycleRunContext, use: (runtime: RuntimeReadiness) => Promise<T>, ports?: PortLeaseProjection, refuse?: ReadinessRefusal<T>, purpose?: RuntimeReadinessPurpose): Promise<T | undefined>;
69
+ }
70
+ type SeedOutcome = Readonly<{
71
+ kind: 'none' | 'current' | 'ran';
72
+ }> | Readonly<{
73
+ kind: 'refusal';
74
+ diagnostics: readonly EnvironmentDiagnostic[];
75
+ }>;
76
+ export interface UpCommandAdapters extends LifecycleCommandAdapters {
77
+ /** Runs environment.seed once the stack is healthy, when a resettable volume is newer than the last seed. */
78
+ seed?(context: LifecycleRunContext, up: Extract<UpCommandResult, {
79
+ kind: 'complete';
80
+ }>['result']): Promise<SeedOutcome>;
81
+ /**
82
+ * Records the siblings' lockfiles and rebuild inputs the stack runs on; warnings when it cannot.
83
+ * A resumed stack keeps the record of its start, because resuming restarts nothing.
84
+ */
85
+ recordStackInputs?(context: LifecycleRunContext, change: 'started' | 'resumed' | 'unchanged'): Promise<readonly EnvironmentDiagnostic[]>;
86
+ withLifecycleStage<T>(context: LifecycleRunContext, use: (stage: LifecycleStageProjection) => Promise<T>, refuse?: ReadinessRefusal<T>): Promise<T | undefined>;
87
+ withAcquiredPorts<T>(context: LifecycleRunContext, use: (ports: AcquiredPorts) => Promise<T>, refuse?: ReadinessRefusal<T>): Promise<T | undefined>;
88
+ }
89
+ export interface SleepCommandAdapters extends LifecycleCommandAdapters {
90
+ }
91
+ export interface SessionCommandAdapters {
92
+ up(input: UpCommandInput): Promise<UpCommandResult>;
93
+ sleep(input: SleepCommandInput): Promise<SleepCommandResult>;
94
+ resolveExecutable(name: string, env: Readonly<Record<string, string>>): Promise<ExecutableResolution>;
95
+ executeForeground(input: ForegroundProcessInput, options: {
96
+ signal?: AbortSignal;
97
+ }): Promise<ForegroundProcessOutcome>;
98
+ readonly signal?: AbortSignal;
99
+ }
100
+ export interface DownCommandInput {
101
+ readonly configPath: string;
102
+ }
103
+ export interface ResetCommandInput {
104
+ readonly configPath: string;
105
+ }
106
+ export interface DestructiveRunContext extends LifecycleRunContext {
107
+ readonly instance: SelectDestructiveInstanceInput;
108
+ }
109
+ export interface DestructiveObservation {
110
+ readonly instance: SelectDestructiveInstanceInput;
111
+ readonly runtime: RuntimeLifecycleProjection;
112
+ readonly ports: PortLeaseProjection;
113
+ readonly down: Omit<PlanTeardownInput, 'expectedDiscoveryDigest' | 'consent' | 'continuation' | 'recoveredReservation'>;
114
+ readonly reset: Omit<PlanResetInput, 'confirmationDigest' | 'consent' | 'continuation' | 'recoveredReservation'>;
115
+ }
116
+ /** The evidence a step of an already-reserved drain re-reads: no runtime readiness, no ports. */
117
+ export type DestructiveReclaimObservation = Pick<DestructiveObservation, 'instance' | 'down' | 'reset'>;
118
+ export interface DestructiveCommandAdapters {
119
+ load(input: DownCommandInput | ResetCommandInput): Promise<EnvironmentCommandOutcome<DestructiveRunContext>>;
120
+ observe(context: DestructiveRunContext): Promise<DestructiveObservation | DestructiveObservationRefusal | undefined>;
121
+ /** Reclaim evidence only, after `observe` measured the runtime for the same context. */
122
+ observeReclaim?(context: DestructiveRunContext): Promise<DestructiveReclaimObservation | DestructiveObservationRefusal | undefined>;
123
+ execute(step: ExecutionStep): Promise<ExecuteProbeOutcome>;
124
+ }
125
+ export type DestructiveObservationRefusal = Extract<EnvironmentCommandOutcome<never>, {
126
+ kind: 'refusal';
127
+ }>;
128
+ export interface DownCommandAdapters extends DestructiveCommandAdapters {
129
+ }
130
+ export interface ResetCommandAdapters extends DestructiveCommandAdapters {
131
+ }
132
+ export type DownCommandResult = EnvironmentCommandOutcome<Readonly<{
133
+ stackId: StackId;
134
+ change: 'removed' | 'unchanged';
135
+ }>>;
136
+ interface ResetPreviewResult {
137
+ readonly stackId: StackId;
138
+ readonly planDigest: string;
139
+ readonly targets: readonly ResetTargetInput[];
140
+ readonly noop: boolean;
141
+ }
142
+ export type ResetCommandResult = Readonly<{
143
+ kind: 'preview';
144
+ status: 0;
145
+ diagnostics: readonly EnvironmentDiagnostic[];
146
+ result: ResetPreviewResult;
147
+ }> | Readonly<{
148
+ kind: 'refusal';
149
+ status: 2;
150
+ diagnostics: readonly EnvironmentDiagnostic[];
151
+ result: null;
152
+ }>;
153
+ export type OperatorResetResult = EnvironmentCommandOutcome<Readonly<{
154
+ stackId: StackId;
155
+ change: 'reset' | 'unchanged';
156
+ /** On `reset`: what the approved plan removed, as its preview listed them. */
157
+ targets?: readonly ResetTargetInput[];
158
+ }>>;
159
+ export interface OperatorResetSession {
160
+ readonly preview: Extract<ResetCommandResult, {
161
+ kind: 'preview';
162
+ }>;
163
+ decide(decision: 'approve' | 'decline'): Promise<OperatorResetResult>;
164
+ }
165
+ interface DestructiveRunContextInput {
166
+ readonly lifecycle: LifecycleRunContext;
167
+ readonly instance: SelectDestructiveInstanceInput;
168
+ /** The holder claim the load took on a stack no session held, so this run could read it. */
169
+ readonly claim?: LeasePortFamilyResult;
170
+ }
171
+ export type UpCommandResult = EnvironmentCommandOutcome<Readonly<{
172
+ stackId: StackId;
173
+ change: 'started' | 'resumed' | 'unchanged';
174
+ /** Each `[ports.bases]` name with its leased port, the values the stack's Compose files read. */
175
+ ports: PortLeaseProjection['lease']['ports'];
176
+ entrypoints: PortLeaseProjection['entrypoints'];
177
+ coldStart?: Readonly<{
178
+ measuredMillis: number;
179
+ limitMillis: number;
180
+ headroomMillis: number;
181
+ }>;
182
+ /** Present when environment.seed is declared: whether this up ran it or found the data current. */
183
+ seed?: 'ran' | 'current';
184
+ }>>;
185
+ export type SleepCommandResult = EnvironmentCommandOutcome<Readonly<{
186
+ stackId: StackId;
187
+ change: 'retained' | 'released' | 'stopped' | 'unchanged';
188
+ }>>;
189
+ export type SessionCommandResult = Readonly<{
190
+ kind: 'complete';
191
+ status: number;
192
+ diagnostics: readonly EnvironmentDiagnostic[];
193
+ result: Readonly<{
194
+ child: Readonly<{
195
+ exitCode: number;
196
+ signal: NodeJS.Signals | null;
197
+ }>;
198
+ sleep: Extract<SleepCommandResult, {
199
+ kind: 'complete';
200
+ }>['result'];
201
+ }>;
202
+ }> | Readonly<{
203
+ kind: 'refusal';
204
+ status: number;
205
+ diagnostics: readonly EnvironmentDiagnostic[];
206
+ result: null;
207
+ }>;
208
+ export declare const issuedLifecycleRuns: WeakSet<object>;
209
+ export declare function noticeLifecycleRun(context: LifecycleRunContext, diagnostic: EnvironmentDiagnostic): void;
210
+ export declare function withLifecycleRunNotices<Result extends {
211
+ readonly diagnostics: readonly EnvironmentDiagnostic[];
212
+ }>(context: LifecycleRunContext, result: Result): Result;
213
+ export declare const issuedDestructiveRuns: WeakSet<object>;
214
+ export declare const provisionalClaims: WeakMap<DestructiveRunContext, LeasePortFamilyResult>;
215
+ type EffectiveConfigurationResult = Readonly<{
216
+ kind: 'complete';
217
+ source: SourceProvenance;
218
+ runtimeSha256: string;
219
+ config: CockpitConfig;
220
+ }> | Readonly<{
221
+ kind: 'unavailable';
222
+ }> | Extract<RegistryDerivationResult, {
223
+ kind: 'refusal';
224
+ }>;
225
+ export declare function consumeEffectiveConfiguration(configuration: LoadedConfigProjection): EffectiveConfigurationResult;
226
+ export declare function registryRefusalMessage(result: Extract<EffectiveConfigurationResult, {
227
+ kind: 'refusal';
228
+ }>): string;
229
+ export declare function issueDestructiveRunContext(input: DestructiveRunContextInput): EnvironmentCommandOutcome<DestructiveRunContext>;
230
+ export declare function issueLifecycleRunContext(input: LifecycleRunContextInput): EnvironmentCommandOutcome<LifecycleRunContext>;
231
+ export declare function withLifecycleConfiguration<T>(context: LifecycleRunContext, use: (configuration: LoadedConfigProjection) => Promise<T>): Promise<T | undefined>;
232
+ export declare function lifecycleContextRefusal(message?: string): Extract<EnvironmentCommandOutcome<LifecycleRunContext>, {
233
+ kind: 'refusal';
234
+ }>;
235
+ export {};
@@ -0,0 +1,154 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { ENVIRONMENT_CODES, errorCause, } from '../contract.js';
3
+ import { CockpitConfig } from '../../schema.js';
4
+ import { authenticateStateNamespace } from '../state.js';
5
+ import { holderId as deriveHolderId, stackId as deriveStackId } from '../identity.js';
6
+ import { consumeSetupCheckoutProjection } from '../setup-observation.js';
7
+ import { loadCockpitConfig, consumeLoadedConfigProjection } from '../../config/load.js';
8
+ import { deriveRegistry } from '../../registry-derivation.js';
9
+ import { selectDestructiveInstance } from '../instance.js';
10
+ import { ownerDiagnostic, sameSource } from './shared.js';
11
+ export const issuedLifecycleRuns = new WeakSet();
12
+ // Warnings an owner raised while a run held its context, such as an interrupted restore released
13
+ // with its data possibly half applied. The command's result carries them whatever its outcome:
14
+ // dropping one left a person working on partial data with nobody told.
15
+ const lifecycleRunNotices = new WeakMap();
16
+ export function noticeLifecycleRun(context, diagnostic) {
17
+ const notices = lifecycleRunNotices.get(context) ?? [];
18
+ notices.push({ ...diagnostic });
19
+ lifecycleRunNotices.set(context, notices);
20
+ }
21
+ export function withLifecycleRunNotices(context, result) {
22
+ const notices = lifecycleRunNotices.get(context);
23
+ lifecycleRunNotices.delete(context);
24
+ return notices ? { ...result, diagnostics: [...result.diagnostics, ...notices] } : result;
25
+ }
26
+ const lifecycleConfigurationSources = new WeakMap();
27
+ export const issuedDestructiveRuns = new WeakSet();
28
+ export const provisionalClaims = new WeakMap();
29
+ export function consumeEffectiveConfiguration(configuration) {
30
+ const loaded = consumeLoadedConfigProjection(configuration);
31
+ if (!loaded)
32
+ return { kind: 'unavailable' };
33
+ const derived = deriveRegistry(loaded.config);
34
+ return derived.kind === 'complete'
35
+ ? { kind: 'complete', source: loaded.source, runtimeSha256: loaded.runtimeSha256, config: derived.result.config }
36
+ : derived;
37
+ }
38
+ export function registryRefusalMessage(result) {
39
+ return `effective registry refused (${result.code}): ${result.message}`;
40
+ }
41
+ export function issueDestructiveRunContext(input) {
42
+ try {
43
+ if (!input || typeof input !== 'object' || Array.isArray(input))
44
+ return lifecycleContextRefusal();
45
+ const descriptors = Object.getOwnPropertyDescriptors(input);
46
+ if (Reflect.ownKeys(descriptors).length !== (descriptors.claim ? 3 : 2)
47
+ || !('value' in descriptors.lifecycle) || !('value' in descriptors.instance)
48
+ || descriptors.claim && !('value' in descriptors.claim))
49
+ return lifecycleContextRefusal();
50
+ const lifecycle = descriptors.lifecycle.value;
51
+ const instance = descriptors.instance.value;
52
+ const claim = descriptors.claim?.value;
53
+ const namespace = authenticateStateNamespace(lifecycle?.namespace);
54
+ const selected = selectDestructiveInstance(instance);
55
+ if (!namespace || selected.kind !== 'selected' || selected.stackId !== lifecycle.stackId
56
+ || selected.checkoutId !== lifecycle.checkoutId || lifecycle.configPath !== resolve(lifecycle.configPath)) {
57
+ return lifecycleContextRefusal();
58
+ }
59
+ const context = { ...lifecycle, namespace, instance };
60
+ issuedDestructiveRuns.add(context);
61
+ if (claim)
62
+ provisionalClaims.set(context, claim);
63
+ return { kind: 'complete', status: 0, diagnostics: [], result: context };
64
+ }
65
+ catch (error) {
66
+ return lifecycleContextRefusal(`destructive run authority could not be read: ${errorCause(error)}`);
67
+ }
68
+ }
69
+ export function issueLifecycleRunContext(input) {
70
+ try {
71
+ if (!input || typeof input !== 'object' || Array.isArray(input))
72
+ return lifecycleContextRefusal();
73
+ const descriptors = Object.getOwnPropertyDescriptors(input);
74
+ const keys = ['checkout', 'configPath', 'configuration', 'namespace', 'stackId', 'holderId', 'sessionId'];
75
+ if (Reflect.ownKeys(descriptors).length !== keys.length
76
+ || keys.some((key) => !descriptors[key] || !('value' in descriptors[key])))
77
+ return lifecycleContextRefusal();
78
+ const checkout = consumeSetupCheckoutProjection(descriptors.checkout.value);
79
+ const requestedConfigPath = descriptors.configPath.value;
80
+ const loaded = consumeEffectiveConfiguration(descriptors.configuration.value);
81
+ const namespace = authenticateStateNamespace(descriptors.namespace.value);
82
+ const stackId = descriptors.stackId.value;
83
+ const holderId = descriptors.holderId.value;
84
+ const sessionId = descriptors.sessionId.value;
85
+ if (loaded.kind === 'refusal')
86
+ return lifecycleContextRefusal(registryRefusalMessage(loaded));
87
+ if (!checkout || loaded.kind !== 'complete' || !namespace || typeof requestedConfigPath !== 'string' || requestedConfigPath.length === 0
88
+ || requestedConfigPath.includes('\0') || resolve(requestedConfigPath) !== loaded.source.path
89
+ || typeof sessionId !== 'string'
90
+ || !sameSource(checkout.source, loaded.source)
91
+ || loaded.config.cockpit.name !== checkout.cockpitName)
92
+ return lifecycleContextRefusal();
93
+ const expectedStackId = deriveStackId({
94
+ cockpitId: checkout.cockpitId,
95
+ checkoutId: checkout.checkoutId,
96
+ variant: { kind: 'shared' },
97
+ });
98
+ const expectedHolderId = deriveHolderId({
99
+ stackId: expectedStackId,
100
+ checkoutId: checkout.checkoutId,
101
+ sessionId,
102
+ });
103
+ if (stackId !== expectedStackId || holderId !== expectedHolderId
104
+ || namespace.paths.lifecycle(expectedStackId).cockpitId !== checkout.cockpitId) {
105
+ return lifecycleContextRefusal();
106
+ }
107
+ const context = {
108
+ configPath: resolve(requestedConfigPath),
109
+ source: { ...loaded.source },
110
+ runtimeSha256: loaded.runtimeSha256,
111
+ namespace,
112
+ cockpitId: checkout.cockpitId,
113
+ checkoutId: checkout.checkoutId,
114
+ stackId: expectedStackId,
115
+ holderId: expectedHolderId,
116
+ ports: {
117
+ step: loaded.config.ports.step,
118
+ count: loaded.config.ports.count,
119
+ bases: { ...loaded.config.ports.bases },
120
+ },
121
+ entrypointDerivatives: loaded.config.environment.entrypoint_derivatives.map((value) => ({ ...value })),
122
+ };
123
+ issuedLifecycleRuns.add(context);
124
+ lifecycleConfigurationSources.set(context, Object.freeze({ source: context.source,
125
+ siblingsRoot: resolve(dirname(loaded.source.path), loaded.config.cockpit.siblings_root) }));
126
+ return { kind: 'complete', status: 0, diagnostics: [], result: context };
127
+ }
128
+ catch (error) {
129
+ return lifecycleContextRefusal(`lifecycle run authority could not be read: ${errorCause(error)}`);
130
+ }
131
+ }
132
+ export async function withLifecycleConfiguration(context, use) {
133
+ if (!context || typeof context !== 'object')
134
+ return undefined;
135
+ const expected = lifecycleConfigurationSources.get(context);
136
+ if (!expected)
137
+ return undefined;
138
+ // Each leaf consumes its own loader-issued handle; a copied parsed config has no authority.
139
+ const loaded = await loadCockpitConfig(expected.source.path);
140
+ if (loaded.kind !== 'complete' || !sameSource(expected.source, loaded.result.source))
141
+ return undefined;
142
+ try {
143
+ return await use(loaded.result);
144
+ }
145
+ finally {
146
+ consumeLoadedConfigProjection(loaded.result);
147
+ }
148
+ }
149
+ export function lifecycleContextRefusal(message = 'lifecycle run authority is unavailable or does not match the loaded configuration') {
150
+ return {
151
+ kind: 'refusal', status: 2, result: null,
152
+ diagnostics: [ownerDiagnostic(ENVIRONMENT_CODES.LIFECYCLE_EVIDENCE_INVALID, message, 'lifecycle')],
153
+ };
154
+ }
@@ -0,0 +1,25 @@
1
+ import { type EnvironmentDiagnostic, type ExecutionFence, type HolderId } from '../contract.js';
2
+ import { type StateRecord, type StateResult, type SkippedStateNamespace } from '../state.js';
3
+ import { type CurrentLifecycleRecord, type LifecycleRecordValue } from '../lifecycle-stage.js';
4
+ import { type PortLeaseProjection } from '../ports.js';
5
+ import { type DrainOutcome } from '../claims.js';
6
+ import { type LifecycleRunContext, type SleepCommandResult, type UpCommandResult } from './lifecycle-context.js';
7
+ export declare function lifecycleSuggestion(context: LifecycleRunContext, command: 'up' | 'down'): string;
8
+ export declare function readLifecycleRecord(context: LifecycleRunContext): Promise<CurrentLifecycleRecord | null | UpCommandResult>;
9
+ export declare function publishLifecycleRecord(context: LifecycleRunContext, expected: StateRecord | null, value: LifecycleRecordValue, transfer?: Readonly<{
10
+ readonly previousHolderId: HolderId;
11
+ readonly projection: PortLeaseProjection;
12
+ }>, rebind?: PortLeaseProjection): Promise<StateResult<StateRecord> | UpCommandResult>;
13
+ export declare function unreadableStateWarning(skipped: readonly SkippedStateNamespace[]): EnvironmentDiagnostic | undefined;
14
+ export declare function unheldStack(context: LifecycleRunContext): Promise<SleepCommandResult | undefined>;
15
+ export declare function repairRequired(context: LifecycleRunContext): Extract<SleepCommandResult, {
16
+ kind: 'refusal';
17
+ }>;
18
+ export declare function invalidateCompletedLifecycle(context: LifecycleRunContext, workBasisSha256: string, operationGeneration: string, purpose: 'sleep' | 'down'): Promise<Extract<SleepCommandResult, {
19
+ kind: 'refusal';
20
+ }> | undefined>;
21
+ export declare function publishDrainOutcomeRecord(context: LifecycleRunContext, outcome: DrainOutcome): Promise<Extract<SleepCommandResult, {
22
+ kind: 'refusal';
23
+ }> | undefined>;
24
+ export declare function publishDrainOutcome(context: LifecycleRunContext, outcome: DrainOutcome, fence: ExecutionFence): Promise<SleepCommandResult | undefined>;
25
+ export declare function exactCommandConfigPath(input: unknown): string | undefined;
@@ -0,0 +1,202 @@
1
+ import { dirname, join, resolve } from 'node:path';
2
+ import { cleanupFencedExecution } from '../../environment-exec/execute.js';
3
+ import { ENVIRONMENT_CODES, snapshotJson, forwardedRefusal, } from '../contract.js';
4
+ import { cockpitCommand } from '../../fix-catalogue.js';
5
+ import { abortStateTransaction, readState, transactState } from '../state.js';
6
+ import { decodeLifecycleRecord, resolveLifecycleStage } from '../lifecycle-stage.js';
7
+ import { inspectPortLeaseTransfer, revalidatePortLeaseProjection } from '../ports.js';
8
+ import { commitDrainOutcome, decodeCoordinationRecord } from '../claims.js';
9
+ import { lifecycleRefusal, ownerDiagnostic } from './shared.js';
10
+ import { withLifecycleConfiguration } from './lifecycle-context.js';
11
+ export function lifecycleSuggestion(context, command) {
12
+ return cockpitCommand(command, { config: context.source.path });
13
+ }
14
+ export async function readLifecycleRecord(context) {
15
+ const address = context.namespace.paths.lifecycle(context.stackId);
16
+ const result = await readState(address);
17
+ if (result.kind === 'missing') {
18
+ const stage = await resolveLifecycleStage({
19
+ namespace: context.namespace, stackId: context.stackId, observedAt: new Date().toISOString(),
20
+ });
21
+ if (stage.kind !== 'complete')
22
+ return forwardedRefusal(stage.diagnostics);
23
+ return stage.authority.stage === 'steady'
24
+ ? lifecycleRefusal(ENVIRONMENT_CODES.LIFECYCLE_PROGRESS_INVALID, 'seeded lifecycle history requires persisted progress', address.path)
25
+ : null;
26
+ }
27
+ if (result.kind !== 'complete') {
28
+ return lifecycleRefusal(result.code, result.message, result.target);
29
+ }
30
+ return decodeLifecycleRecord(result.value, context) ?? lifecycleRefusal(ENVIRONMENT_CODES.STATE_RECORD_MALFORMED, 'lifecycle progress record is malformed', address.path);
31
+ }
32
+ function lifecycleStateRecord(context, current, value, updatedAt) {
33
+ return {
34
+ format: 'cockpit-state/v1',
35
+ kind: 'lifecycle',
36
+ cockpitId: context.cockpitId,
37
+ subjectId: context.stackId,
38
+ revision: current === null ? 0 : current.revision + 1,
39
+ updatedAt,
40
+ value: snapshotJson(value),
41
+ };
42
+ }
43
+ export async function publishLifecycleRecord(context, expected, value, transfer, rebind) {
44
+ const address = context.namespace.paths.lifecycle(context.stackId);
45
+ const expectedBytes = JSON.stringify(expected);
46
+ const result = await transactState(context.namespace, address, { ownerId: context.holderId }, async (current) => {
47
+ if (JSON.stringify(current) !== expectedBytes)
48
+ return abortStateTransaction(lifecycleRefusal(ENVIRONMENT_CODES.LIFECYCLE_PROGRESS_INVALID, 'lifecycle progress changed during execution', address.path));
49
+ if (transfer) {
50
+ const ownership = await inspectPortLeaseTransfer({
51
+ namespace: context.namespace,
52
+ stackId: context.stackId,
53
+ holderId: context.holderId,
54
+ checkoutId: context.checkoutId,
55
+ previousHolderId: transfer.previousHolderId,
56
+ projection: transfer.projection,
57
+ });
58
+ if (ownership.kind === 'refusal')
59
+ return abortStateTransaction({
60
+ kind: 'refusal',
61
+ status: 2,
62
+ result: null,
63
+ diagnostics: ownership.diagnostics.map((diagnostic) => diagnostic.code === ENVIRONMENT_CODES.CLAIM_CO_TENANT
64
+ ? ownerDiagnostic(diagnostic.code, `lifecycle progress belongs to another active session; run \`${lifecycleSuggestion(context, 'up')}\` to resume it or \`${lifecycleSuggestion(context, 'down')}\` to release it`, diagnostic.target ?? context.stackId)
65
+ : diagnostic),
66
+ });
67
+ }
68
+ if (rebind && (!await withLifecycleConfiguration(context, async () => true)
69
+ || !await revalidatePortLeaseProjection({ projection: rebind, namespace: context.namespace }))) {
70
+ return abortStateTransaction(lifecycleRefusal(ENVIRONMENT_CODES.EXECUTION_PRECONDITION_CHANGED, `configuration or sole-holder lease changed before generated lifecycle refresh; rerun \`${lifecycleSuggestion(context, 'up')}\``, context.stackId, 'rerun npx --no cockpit up --config <your cockpit.toml> once nothing else is changing cockpit.toml or bringing the stack up'));
71
+ }
72
+ return lifecycleStateRecord(context, current, value, new Date().toISOString());
73
+ });
74
+ if ('aborted' in result)
75
+ return result.value;
76
+ if (result.kind === 'complete' || result.kind === 'indeterminate')
77
+ return result;
78
+ return result.kind === 'missing'
79
+ ? lifecycleRefusal(ENVIRONMENT_CODES.STATE_RECORD_MALFORMED, 'lifecycle progress publication returned no record', result.path)
80
+ : lifecycleRefusal(result.code, result.message, result.target);
81
+ }
82
+ // Port leases are machine-wide, so up reads every cockpit's state. Another cockpit's namespace this
83
+ // version cannot read is skipped there rather than refused; this cockpit's own unreadable state still
84
+ // refuses in the command itself. The skipped ones are named in a single warning with one cleanup
85
+ // command (`stacks prune`), and only by doctor: the folders belong to other cockpits, usually ones an earlier version
86
+ // left behind, and repeating them on every up (and so every session) buried each result under lines
87
+ // about cockpits the person was not working on. A port they still hold fails up on its own.
88
+ export function unreadableStateWarning(skipped) {
89
+ if (skipped.length === 0)
90
+ return undefined;
91
+ const directory = dirname(skipped[0].path);
92
+ const reasons = [...new Set(skipped.map(({ reason }) => reason))].join('; ');
93
+ const count = skipped.length === 1 ? '1 state folder of another cockpit' : `${skipped.length} state folders of other cockpits`;
94
+ return {
95
+ severity: 'warning',
96
+ code: ENVIRONMENT_CODES.STATE_RECORD_MALFORMED,
97
+ message: `${count} under ${directory} cannot be read by this cockpit version (${reasons}), so their claims and port leases were ignored`,
98
+ target: directory,
99
+ fix: `preview their removal with ${cockpitCommand('stacks prune')}, which removes those an earlier cockpit build left once none of their stacks is kept, then apply it with --apply`,
100
+ };
101
+ }
102
+ // `up` keeps a holder whenever containers may exist, so a stack no session holds has nothing running.
103
+ // Sleep then has nothing to stop; refusing with a co-tenant error sent people looking for a session
104
+ // that did not exist, after an `up` that never started anything or a second `sleep`.
105
+ export async function unheldStack(context) {
106
+ const stored = await readState(context.namespace.paths.coordination(context.stackId));
107
+ if (stored.kind !== 'complete')
108
+ return undefined;
109
+ const coordination = decodeCoordinationRecord(stored.value, context.stackId);
110
+ if (!coordination || coordination.holders.length > 0)
111
+ return undefined;
112
+ const reserved = coordination.lease !== null && !coordination.lease.released;
113
+ return {
114
+ kind: 'complete', status: 0,
115
+ diagnostics: [{
116
+ severity: 'warning', code: ENVIRONMENT_CODES.STACK_NOT_RUNNING, target: context.stackId,
117
+ message: reserved
118
+ ? `no session holds this stack, so nothing is running and sleep has nothing to stop; its port family stays reserved for the next up until \`${lifecycleSuggestion(context, 'down')}\` releases it`
119
+ : 'the stack is already asleep: no session holds it and its services are stopped, so sleep has nothing to do',
120
+ }],
121
+ result: { stackId: context.stackId, change: 'unchanged' },
122
+ };
123
+ }
124
+ export function repairRequired(context) {
125
+ return lifecycleRefusal(ENVIRONMENT_CODES.DRAIN_ATTEMPT_REPAIR_REQUIRED, 'cockpit cannot prove the interrupted sleep executor stopped, so it will not overlap it with another destructive action; preserve the coordination state for explicit repair', context.stackId);
126
+ }
127
+ export async function invalidateCompletedLifecycle(context, workBasisSha256, operationGeneration, purpose) {
128
+ const current = await readLifecycleRecord(context);
129
+ if (current !== null && 'kind' in current)
130
+ return forwardedRefusal(current.diagnostics);
131
+ const stored = current;
132
+ // `up` writes the lifecycle record before it starts a service, so without one nothing ever ran
133
+ // and there is no identity to retire. Writing one here left a record without lifecycle history,
134
+ // which the next `up` refused as malformed state.
135
+ if (stored === null)
136
+ return undefined;
137
+ if (purpose === 'down' && stored.value.teardownComplete === true
138
+ && stored.value.holderId === context.holderId && stored.value.workBasisSha256 === workBasisSha256
139
+ && stored.value.operationGeneration === operationGeneration)
140
+ return undefined;
141
+ // Sleep retains containers, so its replay still guards resume. Only a reconciled down
142
+ // retires that identity, before the final drain publication can release its claim.
143
+ const value = {
144
+ holderId: context.holderId,
145
+ workBasisSha256,
146
+ operationGeneration,
147
+ completedServices: [],
148
+ ...(purpose === 'down' ? { teardownComplete: true } : {
149
+ ...(stored.value.runtimeInputs ? { runtimeInputs: stored.value.runtimeInputs } : {}),
150
+ ...(stored.value.activeProfiles ? { activeProfiles: stored.value.activeProfiles } : {}),
151
+ }),
152
+ };
153
+ const publication = await publishLifecycleRecord(context, stored.record, value);
154
+ if ('status' in publication)
155
+ return forwardedRefusal(publication.diagnostics);
156
+ if (publication.kind === 'indeterminate')
157
+ return lifecycleRefusal(ENVIRONMENT_CODES.STATE_DURABILITY_INDETERMINATE, publication.message, publication.target);
158
+ if (publication.kind !== 'complete' || !decodeLifecycleRecord(publication.value, context)) {
159
+ return lifecycleRefusal(ENVIRONMENT_CODES.STATE_RECORD_MALFORMED, 'stopped lifecycle invalidation could not be verified', context.namespace.paths.lifecycle(context.stackId).path);
160
+ }
161
+ return undefined;
162
+ }
163
+ export async function publishDrainOutcomeRecord(context, outcome) {
164
+ const publication = await commitDrainOutcome({
165
+ outcome,
166
+ namespace: context.namespace,
167
+ stackId: context.stackId,
168
+ });
169
+ if ('diagnostics' in publication) {
170
+ return forwardedRefusal(publication.diagnostics);
171
+ }
172
+ if (publication.kind === 'indeterminate')
173
+ return lifecycleRefusal(ENVIRONMENT_CODES.STATE_DURABILITY_INDETERMINATE, publication.message, publication.target);
174
+ if (publication.kind !== 'complete') {
175
+ return publication.kind === 'missing'
176
+ ? lifecycleRefusal(ENVIRONMENT_CODES.STATE_RECORD_MALFORMED, 'drain outcome publication returned no record', publication.path)
177
+ : lifecycleRefusal(publication.code, publication.message, publication.target);
178
+ }
179
+ return undefined;
180
+ }
181
+ export async function publishDrainOutcome(context, outcome, fence) {
182
+ const published = await publishDrainOutcomeRecord(context, outcome);
183
+ if (published)
184
+ return published;
185
+ return await cleanupFencedExecution(fence) ? undefined : lifecycleRefusal(ENVIRONMENT_CODES.STATE_DURABILITY_INDETERMINATE, 'the drain outcome was published but its durable execution fence could not be removed', fence.markerPath);
186
+ }
187
+ export function exactCommandConfigPath(input) {
188
+ try {
189
+ if (!input || typeof input !== 'object' || Array.isArray(input))
190
+ return undefined;
191
+ const descriptors = Object.getOwnPropertyDescriptors(input);
192
+ if (Reflect.ownKeys(descriptors).length !== 1 || !descriptors.configPath || !('value' in descriptors.configPath)
193
+ || typeof descriptors.configPath.value !== 'string' || descriptors.configPath.value.length === 0
194
+ || descriptors.configPath.value.includes('\0'))
195
+ return undefined;
196
+ return resolve(descriptors.configPath.value);
197
+ }
198
+ catch {
199
+ // A throwing accessor or proxy trap makes the input malformed, which the caller refuses.
200
+ return undefined;
201
+ }
202
+ }
@@ -0,0 +1,18 @@
1
+ import { type EnvironmentDiagnostic, type LifecycleProgress } from '../contract.js';
2
+ import { type RuntimeServiceEvidence, type RuntimeServiceFailureEvidence, type RuntimeServiceObservation, type RuntimeTopologyEvidence } from '../runtime.js';
3
+ import { type SessionCommandAdapters, type SessionCommandInput, type SessionCommandResult, type SleepCommandAdapters, type SleepCommandInput, type SleepCommandResult, type UpCommandAdapters, type UpCommandInput, type UpCommandResult } from './lifecycle-context.js';
4
+ export { decodeLifecycleRecord } from '../lifecycle-stage.js';
5
+ type ServiceAdmission = {
6
+ readonly kind: 'complete';
7
+ readonly evidence: RuntimeServiceEvidence;
8
+ } | {
9
+ readonly kind: 'stale';
10
+ } | {
11
+ readonly kind: 'failure';
12
+ readonly logs?: RuntimeServiceFailureEvidence | RuntimeServiceObservation;
13
+ };
14
+ export declare function revalidateService(topology: RuntimeTopologyEvidence, completed: LifecycleProgress['completedServices'][number], adapters: Pick<UpCommandAdapters, 'execute'>): Promise<ServiceAdmission>;
15
+ export declare function collectFailureLogs(evidence: RuntimeServiceFailureEvidence | RuntimeServiceObservation | undefined, service: string, adapters: Pick<UpCommandAdapters, 'execute'>): Promise<readonly EnvironmentDiagnostic[]>;
16
+ export declare function runUp(input: UpCommandInput, adapters: UpCommandAdapters): Promise<UpCommandResult>;
17
+ export declare function runSession(input: SessionCommandInput, adapters: SessionCommandAdapters): Promise<SessionCommandResult>;
18
+ export declare function runSleep(input: SleepCommandInput, adapters: SleepCommandAdapters): Promise<SleepCommandResult>;