@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,71 @@
1
+ import { type InstallPolicy as InstallPolicyValue } from '../schema.js';
2
+ import { ENVIRONMENT_CODES, type CheckoutId, type SourceProvenance } from './contract.js';
3
+ declare const OWNER = "install-policy-lockfile-observation";
4
+ interface FileIdentity {
5
+ readonly dev: string;
6
+ readonly ino: string;
7
+ readonly mode: string;
8
+ readonly nlink: string;
9
+ readonly size: string;
10
+ readonly mtimeNs: string;
11
+ readonly ctimeNs: string;
12
+ }
13
+ interface AncestorIdentity {
14
+ readonly canonicalPath: string;
15
+ readonly identity: FileIdentity;
16
+ }
17
+ interface AvailableLockfile {
18
+ readonly state: 'available';
19
+ readonly relativePath: string;
20
+ readonly canonicalPath: string;
21
+ readonly identity: FileIdentity;
22
+ readonly ancestors: readonly AncestorIdentity[];
23
+ }
24
+ interface MissingLockfile {
25
+ readonly state: 'missing';
26
+ readonly relativePath: string;
27
+ readonly ancestors: readonly AncestorIdentity[];
28
+ }
29
+ type ObservedLockfile = AvailableLockfile | MissingLockfile;
30
+ interface ObservationBinding {
31
+ readonly source: SourceProvenance;
32
+ readonly siblingIndex: number;
33
+ readonly siblingSlug: string;
34
+ readonly checkoutRoot: string;
35
+ readonly checkoutId: CheckoutId;
36
+ readonly rootIdentity: FileIdentity;
37
+ readonly catalogSha256: string;
38
+ readonly lockfiles: readonly ObservedLockfile[];
39
+ readonly observedAt: string;
40
+ readonly validThrough: string;
41
+ }
42
+ export type InstallPolicyLockfileObservation = ({
43
+ readonly state: 'available';
44
+ readonly producer: typeof OWNER;
45
+ } & ObservationBinding) | {
46
+ readonly state: 'unavailable' | 'failed';
47
+ readonly producer: typeof OWNER;
48
+ readonly code: typeof ENVIRONMENT_CODES.INSTALL_POLICY_OBSERVATION_UNAVAILABLE | typeof ENVIRONMENT_CODES.INSTALL_POLICY_OBSERVATION_INVALID;
49
+ readonly reason: string;
50
+ };
51
+ export interface InstallPolicyObservationContext {
52
+ readonly source: SourceProvenance;
53
+ readonly siblingIndex: number;
54
+ readonly siblingSlug: string;
55
+ readonly checkoutRoot: string;
56
+ readonly checkoutId: CheckoutId;
57
+ readonly policies: readonly InstallPolicyValue[];
58
+ readonly evaluatedAt: number;
59
+ }
60
+ export interface ConsumedInstallPolicyObservation extends ObservationBinding {
61
+ }
62
+ declare const installPolicyProjectionBrand: unique symbol;
63
+ export interface InstallPolicyProjection {
64
+ readonly [installPolicyProjectionBrand]: true;
65
+ }
66
+ type SynchronousResult<T> = T extends PromiseLike<unknown> ? never : T;
67
+ export declare function observeInstallPolicyLockfiles(input: unknown): Promise<InstallPolicyLockfileObservation>;
68
+ export declare function withInstallPolicyProjection<T>(observation: unknown, expected: InstallPolicyObservationContext, use: (projection: InstallPolicyProjection) => SynchronousResult<T>): Promise<SynchronousResult<T> | undefined>;
69
+ export declare function consumeInstallPolicyProjection(projection: InstallPolicyProjection): ConsumedInstallPolicyObservation | undefined;
70
+ export declare function matchesInstallPolicyCatalog(observation: ConsumedInstallPolicyObservation, policies: readonly InstallPolicyValue[]): boolean;
71
+ export {};
@@ -0,0 +1,284 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { lstat, realpath } from 'node:fs/promises';
3
+ import { isAbsolute, join, normalize, relative, sep } from 'node:path';
4
+ import { InstallPolicy } from '../schema.js';
5
+ import { hasErrorCode, RefusalError, ENVIRONMENT_CODES, errorCause, isCanonicalTimestamp, snapshotJson, } from './contract.js';
6
+ import { checkoutId as deriveCheckoutId } from './identity.js';
7
+ const OWNER = 'install-policy-lockfile-observation';
8
+ const CHECKOUT_ID = /^checkout:[a-f0-9]{64}$/;
9
+ const SLUG = /^[a-z0-9][a-z0-9-]*$/;
10
+ const MAX_VALIDITY_MS = 60_000;
11
+ const issuedObservations = new WeakMap();
12
+ const issuedProjections = new WeakMap();
13
+ function isPromiseLike(value) {
14
+ if ((typeof value !== 'object' || value === null) && typeof value !== 'function')
15
+ return false;
16
+ try {
17
+ return typeof Reflect.get(value, 'then') === 'function';
18
+ }
19
+ catch { // A throwing getter on caller-supplied data is treated as promise-like, which the caller refuses.
20
+ return true;
21
+ }
22
+ }
23
+ function confined(root, candidate) {
24
+ const fromRoot = relative(root, candidate);
25
+ return fromRoot === '' || (fromRoot !== '..' && !fromRoot.startsWith(`..${sep}`) && !isAbsolute(fromRoot));
26
+ }
27
+ function identity(stat) {
28
+ return {
29
+ dev: stat.dev.toString(),
30
+ ino: stat.ino.toString(),
31
+ mode: stat.mode.toString(),
32
+ nlink: stat.nlink.toString(),
33
+ size: stat.size.toString(),
34
+ mtimeNs: stat.mtimeNs.toString(),
35
+ ctimeNs: stat.ctimeNs.toString(),
36
+ };
37
+ }
38
+ function sameIdentity(left, right) {
39
+ return Object.keys(left).every((key) => left[key] === right[key]);
40
+ }
41
+ function sameSource(left, right) {
42
+ return left.path === right.path && left.byteLength === right.byteLength && left.sha256 === right.sha256;
43
+ }
44
+ function validSource(value) {
45
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
46
+ return false;
47
+ const source = value;
48
+ return typeof source.path === 'string' && !source.path.includes('\0')
49
+ && isAbsolute(source.path) && normalize(source.path) === source.path
50
+ && Number.isSafeInteger(source.byteLength) && source.byteLength >= 0
51
+ && typeof source.sha256 === 'string' && /^[a-f0-9]{64}$/.test(source.sha256);
52
+ }
53
+ function validRelativePath(path) {
54
+ return path.length > 0 && !/[\x00-\x1f\x7f]/.test(path) && !path.includes('\\') && !isAbsolute(path)
55
+ && !/^[A-Za-z][A-Za-z0-9+.-]*:/.test(path)
56
+ && path.split('/').every((part) => part.length > 0 && part !== '.' && part !== '..');
57
+ }
58
+ function snapshotPolicies(value) {
59
+ const snapshot = snapshotJson(value);
60
+ if (!Array.isArray(snapshot) || snapshot.length > 4_096)
61
+ return undefined;
62
+ const parsed = snapshot.map((row) => InstallPolicy.safeParse(row));
63
+ if (parsed.some((row) => !row.success))
64
+ return undefined;
65
+ const policies = parsed.map((row) => row.data);
66
+ const selectors = policies.map(({ toolchain, lockfile }) => `${toolchain}\0${lockfile}`);
67
+ return new Set(selectors).size === selectors.length
68
+ ? policies
69
+ : undefined;
70
+ }
71
+ function catalogSha256(policies) {
72
+ const rows = policies.map((policy) => JSON.stringify(policy)).sort();
73
+ return createHash('sha256').update(JSON.stringify(rows)).digest('hex');
74
+ }
75
+ async function stableRoot(path) {
76
+ try {
77
+ const before = await lstat(path, { bigint: true });
78
+ if (!before.isDirectory() || before.isSymbolicLink())
79
+ return { reason: 'it is not a plain directory' };
80
+ const canonicalPath = await realpath(path);
81
+ const after = await lstat(canonicalPath, { bigint: true });
82
+ const beforeIdentity = identity(before);
83
+ const afterIdentity = identity(after);
84
+ return canonicalPath === path && after.isDirectory() && !after.isSymbolicLink()
85
+ && sameIdentity(beforeIdentity, afterIdentity)
86
+ ? { canonicalPath, identity: afterIdentity }
87
+ : { reason: 'it is not canonical or changed while it was read' };
88
+ }
89
+ catch (error) {
90
+ return { reason: errorCause(error) };
91
+ }
92
+ }
93
+ async function inspectLockfile(root, relativePath) {
94
+ if (!validRelativePath(relativePath))
95
+ return 'invalid';
96
+ const ancestors = [];
97
+ const parts = relativePath.split('/');
98
+ let current = root;
99
+ for (let index = 0; index < parts.length; index += 1) {
100
+ current = join(current, parts[index]);
101
+ if (!confined(root, current))
102
+ return 'invalid';
103
+ try {
104
+ const before = await lstat(current, { bigint: true });
105
+ if (before.isSymbolicLink())
106
+ return 'invalid';
107
+ const canonicalPath = await realpath(current);
108
+ const after = await lstat(canonicalPath, { bigint: true });
109
+ const beforeIdentity = identity(before);
110
+ const afterIdentity = identity(after);
111
+ if (!confined(root, canonicalPath) || canonicalPath !== current
112
+ || after.isSymbolicLink() || !sameIdentity(beforeIdentity, afterIdentity))
113
+ return 'invalid';
114
+ if (index < parts.length - 1) {
115
+ if (!after.isDirectory())
116
+ return 'invalid';
117
+ ancestors.push({ canonicalPath, identity: afterIdentity });
118
+ continue;
119
+ }
120
+ if (!after.isFile() || after.nlink !== 1n)
121
+ return 'invalid';
122
+ return {
123
+ state: 'available',
124
+ relativePath,
125
+ canonicalPath,
126
+ identity: afterIdentity,
127
+ ancestors,
128
+ };
129
+ }
130
+ catch (error) {
131
+ if (!hasErrorCode(error, 'ENOENT'))
132
+ return 'invalid';
133
+ return {
134
+ state: 'missing',
135
+ relativePath,
136
+ ancestors,
137
+ };
138
+ }
139
+ }
140
+ return 'invalid';
141
+ }
142
+ function sameObservation(left, right) {
143
+ if (left.state !== right.state || left.relativePath !== right.relativePath
144
+ || left.ancestors.length !== right.ancestors.length)
145
+ return false;
146
+ for (let index = 0; index < left.ancestors.length; index += 1) {
147
+ const leftAncestor = left.ancestors[index];
148
+ const rightAncestor = right.ancestors[index];
149
+ if (leftAncestor.canonicalPath !== rightAncestor.canonicalPath
150
+ || !sameIdentity(leftAncestor.identity, rightAncestor.identity))
151
+ return false;
152
+ }
153
+ return left.state === 'missing' || (right.state === 'available'
154
+ && left.canonicalPath === right.canonicalPath && sameIdentity(left.identity, right.identity));
155
+ }
156
+ function failure(state, reason) {
157
+ return {
158
+ state,
159
+ producer: OWNER,
160
+ code: state === 'unavailable'
161
+ ? ENVIRONMENT_CODES.INSTALL_POLICY_OBSERVATION_UNAVAILABLE
162
+ : ENVIRONMENT_CODES.INSTALL_POLICY_OBSERVATION_INVALID,
163
+ reason,
164
+ };
165
+ }
166
+ export async function observeInstallPolicyLockfiles(input) {
167
+ const snapshot = snapshotJson(input);
168
+ if (!snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot)) {
169
+ return failure('failed', 'install policy observation input is malformed');
170
+ }
171
+ const value = snapshot;
172
+ const expectedKeys = ['checkoutId', 'checkoutRoot', 'observedAt', 'policies', 'siblingIndex', 'siblingSlug', 'source'];
173
+ const policies = snapshotPolicies(value.policies);
174
+ if (Object.keys(value).sort().join('\0') !== expectedKeys.join('\0')
175
+ || !validSource(value.source)
176
+ || !Number.isSafeInteger(value.siblingIndex) || value.siblingIndex < 0
177
+ || typeof value.siblingSlug !== 'string' || !SLUG.test(value.siblingSlug)
178
+ || typeof value.checkoutRoot !== 'string' || !isAbsolute(value.checkoutRoot)
179
+ || normalize(value.checkoutRoot) !== value.checkoutRoot
180
+ || typeof value.checkoutId !== 'string' || !CHECKOUT_ID.test(value.checkoutId)
181
+ || !policies || !isCanonicalTimestamp(value.observedAt)) {
182
+ return failure('failed', 'install policy observation input is malformed');
183
+ }
184
+ const issuedAt = Date.now();
185
+ const observedAt = Date.parse(value.observedAt);
186
+ if (observedAt > issuedAt || issuedAt - observedAt > MAX_VALIDITY_MS) {
187
+ return failure('failed', 'install policy observation time is outside the freshness window');
188
+ }
189
+ const root = await stableRoot(value.checkoutRoot);
190
+ if ('reason' in root)
191
+ return failure('unavailable', `checkout root is unavailable: ${root.reason}`);
192
+ if (deriveCheckoutId({ checkoutPath: root.canonicalPath }) !== value.checkoutId) {
193
+ return failure('failed', 'checkout root does not match its declared identity');
194
+ }
195
+ const rows = [];
196
+ const lockfiles = [...new Set(policies.map((policy) => policy.lockfile))].sort();
197
+ for (const relativePath of lockfiles) {
198
+ const observed = await inspectLockfile(root.canonicalPath, relativePath);
199
+ if (observed === 'invalid')
200
+ return failure('failed', `lockfile path is invalid: ${relativePath}`);
201
+ rows.push(observed);
202
+ }
203
+ const binding = {
204
+ source: { ...value.source },
205
+ siblingIndex: value.siblingIndex,
206
+ siblingSlug: value.siblingSlug,
207
+ checkoutRoot: root.canonicalPath,
208
+ checkoutId: value.checkoutId,
209
+ rootIdentity: root.identity,
210
+ catalogSha256: catalogSha256(policies),
211
+ lockfiles: rows,
212
+ observedAt: value.observedAt,
213
+ validThrough: new Date(observedAt + MAX_VALIDITY_MS).toISOString(),
214
+ };
215
+ const observation = { state: 'available', producer: OWNER, ...binding };
216
+ issuedObservations.set(observation, binding);
217
+ return observation;
218
+ }
219
+ export async function withInstallPolicyProjection(observation, expected, use) {
220
+ if (observation === null || typeof observation !== 'object')
221
+ return undefined;
222
+ const binding = issuedObservations.get(observation);
223
+ issuedObservations.delete(observation);
224
+ const snapshot = snapshotJson(expected);
225
+ if (!binding || !snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot) || typeof use !== 'function')
226
+ return undefined;
227
+ const context = snapshot;
228
+ const expectedKeys = ['checkoutId', 'checkoutRoot', 'evaluatedAt', 'policies', 'siblingIndex', 'siblingSlug', 'source'];
229
+ const policies = snapshotPolicies(context.policies);
230
+ const trustedCurrentTime = Date.now();
231
+ if (Object.keys(context).sort().join('\0') !== expectedKeys.join('\0')
232
+ || !validSource(context.source) || !policies
233
+ || !Number.isSafeInteger(context.siblingIndex) || !Number.isSafeInteger(context.evaluatedAt)
234
+ || binding.siblingIndex !== context.siblingIndex || binding.siblingSlug !== context.siblingSlug
235
+ || binding.checkoutRoot !== context.checkoutRoot || binding.checkoutId !== context.checkoutId
236
+ || !sameSource(binding.source, context.source)
237
+ || binding.catalogSha256 !== catalogSha256(policies)
238
+ || context.evaluatedAt !== Date.parse(binding.observedAt)
239
+ || context.evaluatedAt > trustedCurrentTime
240
+ || trustedCurrentTime > Date.parse(binding.validThrough))
241
+ return undefined;
242
+ const root = await stableRoot(binding.checkoutRoot);
243
+ if ('reason' in root || !sameIdentity(root.identity, binding.rootIdentity)
244
+ || deriveCheckoutId({ checkoutPath: root.canonicalPath }) !== binding.checkoutId)
245
+ return undefined;
246
+ for (const lockfile of binding.lockfiles) {
247
+ const current = await inspectLockfile(binding.checkoutRoot, lockfile.relativePath);
248
+ if (current === 'invalid' || !sameObservation(lockfile, current))
249
+ return undefined;
250
+ }
251
+ const projection = {};
252
+ issuedProjections.set(projection, binding);
253
+ try {
254
+ const result = use(projection);
255
+ if (isPromiseLike(result)) {
256
+ // The caller receives the contract error immediately; observing the invalid result prevents
257
+ // a later rejection from becoming detached process state.
258
+ void Promise.resolve(result).catch(() => undefined);
259
+ throw new RefusalError('install policy projection callback must be synchronous');
260
+ }
261
+ return result;
262
+ }
263
+ finally {
264
+ issuedProjections.delete(projection);
265
+ }
266
+ }
267
+ export function consumeInstallPolicyProjection(projection) {
268
+ try {
269
+ if (projection === null || typeof projection !== 'object')
270
+ return undefined;
271
+ const binding = issuedProjections.get(projection);
272
+ if (!binding)
273
+ return undefined;
274
+ issuedProjections.delete(projection);
275
+ return binding;
276
+ }
277
+ catch { // A throwing accessor or proxy trap on the projection makes it malformed; the caller refuses it.
278
+ return undefined;
279
+ }
280
+ }
281
+ export function matchesInstallPolicyCatalog(observation, policies) {
282
+ const snapshot = snapshotPolicies(policies);
283
+ return snapshot !== undefined && observation.catalogSha256 === catalogSha256(snapshot);
284
+ }
@@ -0,0 +1,48 @@
1
+ import { type InstallPolicy as InstallPolicyValue, type Sibling as SiblingValue } from '../schema.js';
2
+ import { ENVIRONMENT_CODES, type CheckoutId, type SourceProvenance } from './contract.js';
3
+ import { type InstallPolicyProjection } from './install-policy-observation.js';
4
+ export declare const GUARD_PROJECT_COMMAND_RENDERED_BYTES = 32768;
5
+ export declare function renderGuardProjectCommand(argv: readonly string[]): {
6
+ readonly kind: 'complete';
7
+ readonly command: string;
8
+ } | {
9
+ readonly kind: 'unavailable';
10
+ readonly reason: string;
11
+ };
12
+ export interface InstallPolicyResolutionInput {
13
+ readonly source: SourceProvenance;
14
+ readonly policies: readonly InstallPolicyValue[];
15
+ readonly siblingIndex: number;
16
+ readonly sibling: SiblingValue;
17
+ readonly checkoutRoot?: string;
18
+ readonly checkoutId?: CheckoutId;
19
+ readonly projection?: InstallPolicyProjection;
20
+ }
21
+ export interface ResolvedInstallPolicyBinding {
22
+ readonly source: SourceProvenance;
23
+ readonly siblingIndex: number;
24
+ readonly diagnostics: Readonly<{
25
+ readonly catalogIndex: number;
26
+ }>;
27
+ readonly siblingSlug: string;
28
+ readonly checkoutRoot: string;
29
+ readonly checkoutId: CheckoutId;
30
+ readonly policy: InstallPolicyValue;
31
+ }
32
+ export type InstallPolicyResolution = {
33
+ readonly kind: 'complete';
34
+ readonly bindings: readonly ResolvedInstallPolicyBinding[];
35
+ } | {
36
+ readonly kind: 'unavailable';
37
+ readonly code: typeof ENVIRONMENT_CODES.INSTALL_POLICY_OBSERVATION_UNAVAILABLE;
38
+ readonly siblingIndex: number;
39
+ readonly siblingSlug: string;
40
+ readonly reason: string;
41
+ } | {
42
+ readonly kind: 'refusal';
43
+ readonly code: typeof ENVIRONMENT_CODES.INSTALL_POLICY_MISSING | typeof ENVIRONMENT_CODES.INSTALL_POLICY_AMBIGUOUS;
44
+ readonly siblingIndex: number;
45
+ readonly siblingSlug: string;
46
+ readonly candidates: readonly string[];
47
+ };
48
+ export declare function resolveInstallPolicies(root: InstallPolicyResolutionInput): InstallPolicyResolution;
@@ -0,0 +1,96 @@
1
+ import { isAbsolute, normalize } from 'node:path';
2
+ import { GuardCommandArgv, InstallPolicy, Sibling } from '../schema.js';
3
+ import { ENVIRONMENT_CODES, snapshotJson } from './contract.js';
4
+ import { consumeInstallPolicyProjection, matchesInstallPolicyCatalog, } from './install-policy-observation.js';
5
+ export const GUARD_PROJECT_COMMAND_RENDERED_BYTES = 32_768;
6
+ export function renderGuardProjectCommand(argv) {
7
+ const parsed = GuardCommandArgv.safeParse(snapshotJson(argv));
8
+ if (!parsed.success)
9
+ return { kind: 'unavailable', reason: 'project command argv exceeds the scalar or word bounds' };
10
+ const command = parsed.data.map(word => `'${word.replaceAll("'", "'\\''")}'`).join(' ');
11
+ return Buffer.byteLength(command) < GUARD_PROJECT_COMMAND_RENDERED_BYTES
12
+ ? { kind: 'complete', command }
13
+ : { kind: 'unavailable', reason: 'project command rendering exceeds the byte bound' };
14
+ }
15
+ function unavailable(siblingIndex, siblingSlug, reason) {
16
+ return {
17
+ kind: 'unavailable',
18
+ code: ENVIRONMENT_CODES.INSTALL_POLICY_OBSERVATION_UNAVAILABLE,
19
+ siblingIndex,
20
+ siblingSlug,
21
+ reason,
22
+ };
23
+ }
24
+ function sourceProvenance(source) {
25
+ return typeof source.path === 'string' && !source.path.includes('\0')
26
+ && isAbsolute(source.path) && normalize(source.path) === source.path
27
+ && Number.isSafeInteger(source.byteLength) && source.byteLength >= 0
28
+ && typeof source.sha256 === 'string' && /^[a-f0-9]{64}$/.test(source.sha256)
29
+ ? { path: source.path, byteLength: source.byteLength, sha256: source.sha256 }
30
+ : undefined;
31
+ }
32
+ export function resolveInstallPolicies(root) {
33
+ const source = sourceProvenance(root.source);
34
+ const siblingIndex = root.siblingIndex;
35
+ const sibling = Sibling.safeParse(root.sibling);
36
+ if (!source || !Array.isArray(root.policies) || !Number.isSafeInteger(siblingIndex) || siblingIndex < 0 || !sibling.success) {
37
+ return unavailable(Number.isSafeInteger(siblingIndex) ? siblingIndex : 0, sibling.success ? sibling.data.slug : 'configuration', 'install policy resolution input is invalid');
38
+ }
39
+ const policies = root.policies.map((policy) => InstallPolicy.safeParse(policy));
40
+ if (policies.some((policy) => !policy.success)) {
41
+ return unavailable(siblingIndex, sibling.data.slug, 'install policy catalog is invalid');
42
+ }
43
+ const catalog = policies.map((policy) => policy.data);
44
+ const selectors = catalog.map(({ toolchain, lockfile }) => `${toolchain}\0${lockfile}`);
45
+ if (new Set(selectors).size !== selectors.length) {
46
+ return unavailable(siblingIndex, sibling.data.slug, 'install policy catalog is invalid');
47
+ }
48
+ if (sibling.data.toolchain === 'none')
49
+ return { kind: 'complete', bindings: [] };
50
+ if (typeof root.checkoutRoot !== 'string' || typeof root.checkoutId !== 'string') {
51
+ return unavailable(siblingIndex, sibling.data.slug, 'authenticated lockfile evidence is unavailable');
52
+ }
53
+ const observation = consumeInstallPolicyProjection(root.projection);
54
+ if (!observation)
55
+ return unavailable(siblingIndex, sibling.data.slug, 'authenticated lockfile evidence is unavailable');
56
+ if (!matchesInstallPolicyCatalog(observation, catalog)
57
+ || observation.siblingIndex !== siblingIndex || observation.siblingSlug !== sibling.data.slug
58
+ || observation.checkoutRoot !== root.checkoutRoot || observation.checkoutId !== root.checkoutId
59
+ || observation.source.path !== source.path || observation.source.byteLength !== source.byteLength
60
+ || observation.source.sha256 !== source.sha256) {
61
+ return unavailable(siblingIndex, sibling.data.slug, 'authenticated lockfile evidence does not match the sibling');
62
+ }
63
+ const present = new Set(observation.lockfiles
64
+ .filter((lockfile) => lockfile.state === 'available')
65
+ .map(({ relativePath }) => relativePath));
66
+ const matches = catalog.flatMap((candidate, catalogIndex) => candidate.toolchain === sibling.data.toolchain && present.has(candidate.lockfile)
67
+ ? [{ catalogIndex, policy: candidate }]
68
+ : []);
69
+ if (matches.length !== 1) {
70
+ const candidates = matches.map(({ policy }) => `${policy.toolchain}:${policy.lockfile}`).sort();
71
+ return {
72
+ kind: 'refusal',
73
+ code: matches.length === 0 ? ENVIRONMENT_CODES.INSTALL_POLICY_MISSING : ENVIRONMENT_CODES.INSTALL_POLICY_AMBIGUOUS,
74
+ siblingIndex,
75
+ siblingSlug: sibling.data.slug,
76
+ candidates,
77
+ };
78
+ }
79
+ const selected = matches[0];
80
+ for (const kind of ['build', 'test']) {
81
+ const argv = selected.policy[kind];
82
+ if (argv && renderGuardProjectCommand(argv).kind !== 'complete') {
83
+ return unavailable(siblingIndex, sibling.data.slug, `${kind} project command rendering exceeds the byte bound`);
84
+ }
85
+ }
86
+ const binding = {
87
+ source,
88
+ siblingIndex,
89
+ diagnostics: { catalogIndex: selected.catalogIndex },
90
+ siblingSlug: sibling.data.slug,
91
+ checkoutRoot: observation.checkoutRoot,
92
+ checkoutId: observation.checkoutId,
93
+ policy: selected.policy,
94
+ };
95
+ return { kind: 'complete', bindings: [binding] };
96
+ }
@@ -0,0 +1,33 @@
1
+ import type { CheckoutId, StackId } from './contract.js';
2
+ export interface InstanceCandidate {
3
+ readonly stackId: StackId;
4
+ readonly checkoutId: CheckoutId;
5
+ }
6
+ export interface ResolveInstanceInput {
7
+ readonly explicit?: InstanceCandidate;
8
+ readonly served: InstanceCandidate;
9
+ readonly launcher: InstanceCandidate;
10
+ readonly mountedSet: readonly CheckoutId[];
11
+ }
12
+ export interface InstanceResolution extends InstanceCandidate {
13
+ readonly kind: 'attach' | 'isolate';
14
+ readonly source: 'explicit' | 'served' | 'launcher';
15
+ }
16
+ export interface SelectDestructiveInstanceInput {
17
+ readonly explicit?: InstanceCandidate;
18
+ readonly served?: InstanceCandidate;
19
+ readonly launcher?: InstanceCandidate;
20
+ readonly claimInventory: readonly InstanceCandidate[];
21
+ }
22
+ export type DestructiveInstanceSelection = Readonly<{
23
+ kind: 'selected';
24
+ source: 'explicit' | 'served' | 'launcher';
25
+ stackId: StackId;
26
+ checkoutId: CheckoutId;
27
+ }> | Readonly<{
28
+ kind: 'refusal';
29
+ reason: 'ambiguous' | 'identity-conflict' | 'identity-mismatch' | 'missing-authority';
30
+ candidates: readonly InstanceCandidate[];
31
+ }>;
32
+ export declare function selectDestructiveInstance(input: SelectDestructiveInstanceInput): DestructiveInstanceSelection;
33
+ export declare function resolveInstance(input: ResolveInstanceInput): InstanceResolution;
@@ -0,0 +1,122 @@
1
+ import { RefusalError } from './contract.js';
2
+ const STACK_ID = /^stack:[a-f0-9]{64}$/;
3
+ const CHECKOUT_ID = /^checkout:[a-f0-9]{64}$/;
4
+ function candidate(value, field, operation = 'resolveInstance') {
5
+ if (value === null
6
+ || typeof value !== 'object'
7
+ || typeof value.stackId !== 'string'
8
+ || !STACK_ID.test(value.stackId)
9
+ || typeof value.checkoutId !== 'string'
10
+ || !CHECKOUT_ID.test(value.checkoutId)) {
11
+ throw new RefusalError(`${operation}: ${field} candidate is malformed`);
12
+ }
13
+ return value;
14
+ }
15
+ function destructiveCandidate(value, field) {
16
+ if (value === null || typeof value !== 'object')
17
+ return candidate(value, field, 'selectDestructiveInstance');
18
+ const stackId = value.stackId;
19
+ const checkoutId = value.checkoutId;
20
+ return candidate({ stackId, checkoutId }, field, 'selectDestructiveInstance');
21
+ }
22
+ function candidateKey(value) {
23
+ return `${value.stackId}\0${value.checkoutId}`;
24
+ }
25
+ function canonicalCandidates(values) {
26
+ const unique = new Map();
27
+ for (const value of values)
28
+ unique.set(candidateKey(value), value);
29
+ return Array.from(unique.values(), (value) => ({ ...value })).sort((left, right) => {
30
+ if (left.stackId !== right.stackId)
31
+ return left.stackId < right.stackId ? -1 : 1;
32
+ return left.checkoutId < right.checkoutId ? -1 : left.checkoutId === right.checkoutId ? 0 : 1;
33
+ });
34
+ }
35
+ function conflictingStackIds(values) {
36
+ const checkoutsByStack = new Map();
37
+ for (const value of values) {
38
+ const checkouts = checkoutsByStack.get(value.stackId) ?? new Set();
39
+ checkouts.add(value.checkoutId);
40
+ checkoutsByStack.set(value.stackId, checkouts);
41
+ }
42
+ return new Set(Array.from(checkoutsByStack)
43
+ .filter(([, checkouts]) => checkouts.size > 1)
44
+ .map(([stackId]) => stackId));
45
+ }
46
+ function destructiveRefusal(reason, candidates) {
47
+ return { kind: 'refusal', reason, candidates: canonicalCandidates(candidates) };
48
+ }
49
+ export function selectDestructiveInstance(input) {
50
+ if (input === null || typeof input !== 'object') {
51
+ throw new RefusalError('selectDestructiveInstance: input is malformed');
52
+ }
53
+ const explicitValue = input.explicit;
54
+ const servedValue = input.served;
55
+ const launcherValue = input.launcher;
56
+ const inventoryValue = input.claimInventory;
57
+ const explicit = explicitValue === undefined ? undefined : destructiveCandidate(explicitValue, 'explicit');
58
+ const served = servedValue === undefined ? undefined : destructiveCandidate(servedValue, 'served');
59
+ const launcher = launcherValue === undefined ? undefined : destructiveCandidate(launcherValue, 'launcher');
60
+ if (!Array.isArray(inventoryValue)) {
61
+ throw new RefusalError('selectDestructiveInstance: claimInventory is malformed');
62
+ }
63
+ const inventory = canonicalCandidates(inventoryValue.map((value) => destructiveCandidate(value, 'claimInventory')));
64
+ const conflictingStacks = conflictingStackIds(inventory);
65
+ const inventoryKeys = new Set(inventory.map(candidateKey));
66
+ if (explicit !== undefined) {
67
+ if (conflictingStacks.has(explicit.stackId)) {
68
+ return destructiveRefusal('identity-conflict', inventory.filter((value) => value.stackId === explicit.stackId));
69
+ }
70
+ return inventoryKeys.has(candidateKey(explicit))
71
+ ? { kind: 'selected', source: 'explicit', ...explicit }
72
+ : destructiveRefusal('identity-mismatch', inventory);
73
+ }
74
+ const authorities = [
75
+ ...(served === undefined ? [] : [{ source: 'served', value: served }]),
76
+ ...(launcher === undefined ? [] : [{ source: 'launcher', value: launcher }]),
77
+ ];
78
+ if (authorities.length === 0)
79
+ return destructiveRefusal('missing-authority', inventory);
80
+ const authorityCandidates = canonicalCandidates(authorities.map(({ value }) => value));
81
+ const authorityConflict = conflictingStackIds(authorityCandidates);
82
+ if (authorityConflict.size > 0) {
83
+ return destructiveRefusal('identity-conflict', authorityCandidates.filter((value) => authorityConflict.has(value.stackId)));
84
+ }
85
+ const relevantStacks = new Set(authorityCandidates.map(({ stackId }) => stackId));
86
+ const relevantInventoryConflicts = new Set(Array.from(conflictingStacks).filter((stackId) => relevantStacks.has(stackId)));
87
+ if (relevantInventoryConflicts.size > 0) {
88
+ return destructiveRefusal('identity-conflict', inventory.filter((value) => relevantInventoryConflicts.has(value.stackId)));
89
+ }
90
+ const relevant = authorities.filter(({ value }) => inventoryKeys.has(candidateKey(value)));
91
+ const distinct = canonicalCandidates(relevant.map(({ value }) => value));
92
+ if (distinct.length === 0)
93
+ return destructiveRefusal('identity-mismatch', inventory);
94
+ if (distinct.length > 1)
95
+ return destructiveRefusal('ambiguous', distinct);
96
+ const selected = relevant[0];
97
+ return { kind: 'selected', source: selected.source, ...selected.value };
98
+ }
99
+ export function resolveInstance(input) {
100
+ if (input === null || typeof input !== 'object') {
101
+ throw new RefusalError('resolveInstance: input is malformed');
102
+ }
103
+ const served = candidate(input.served, 'served');
104
+ const launcher = candidate(input.launcher, 'launcher');
105
+ const explicit = input.explicit === undefined ? undefined : candidate(input.explicit, 'explicit');
106
+ if (!Array.isArray(input.mountedSet)
107
+ || input.mountedSet.some((value) => typeof value !== 'string' || !CHECKOUT_ID.test(value))) {
108
+ throw new RefusalError('resolveInstance: mountedSet contains a malformed checkout identity');
109
+ }
110
+ const mounted = new Set(input.mountedSet);
111
+ const selected = explicit === undefined
112
+ ? mounted.has(served.checkoutId)
113
+ ? { source: 'served', value: served }
114
+ : { source: 'launcher', value: launcher }
115
+ : { source: 'explicit', value: explicit };
116
+ return {
117
+ kind: mounted.has(selected.value.checkoutId) ? 'attach' : 'isolate',
118
+ source: selected.source,
119
+ stackId: selected.value.stackId,
120
+ checkoutId: selected.value.checkoutId,
121
+ };
122
+ }
@@ -0,0 +1,19 @@
1
+ export declare const INSTRUCTION_POINTER_MARKERS: Readonly<{
2
+ begin: "<!-- cockpit:instruction-pointer:start -->";
3
+ end: "<!-- cockpit:instruction-pointer:end -->";
4
+ }>;
5
+ export type InstructionPointerResult = Readonly<{
6
+ kind: 'offered' | 'written' | 'unchanged';
7
+ path: string;
8
+ target: string;
9
+ }> | Readonly<{
10
+ kind: 'refusal';
11
+ path: string;
12
+ reason: string;
13
+ }>;
14
+ /** Appends one bounded marked block; bytes outside that block always remain product-owned. */
15
+ export declare function synchronizeInstructionPointer(input: Readonly<{
16
+ cockpitRoot: string;
17
+ siblingRoot: string;
18
+ write: boolean;
19
+ }>): Promise<InstructionPointerResult>;