@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,4 @@
1
+ import type { SetupCommandAdapters, SetupCommandInput, SetupCommandResult } from '../environment/application/setup.js';
2
+ import type { SetupApplicationOutcome } from '../environment/application/setup.js';
3
+ export type { SetupCommandAdapters, SetupCommandInput, SetupCommandResult };
4
+ export declare function setupCommand(input: SetupCommandInput, adapters: SetupCommandAdapters): Promise<SetupApplicationOutcome>;
@@ -0,0 +1,4 @@
1
+ import { runSetup } from '../environment/application/setup.js';
2
+ export function setupCommand(input, adapters) {
3
+ return runSetup(input, adapters);
4
+ }
@@ -0,0 +1 @@
1
+ export declare function sha256Hex(value: string | Uint8Array): string;
package/dist/sha256.js ADDED
@@ -0,0 +1,4 @@
1
+ import { createHash } from 'node:crypto';
2
+ export function sha256Hex(value) {
3
+ return createHash('sha256').update(value).digest('hex');
4
+ }
@@ -0,0 +1,41 @@
1
+ import { type AdoptableSurfacePath } from './contract.js';
2
+ export type AdoptionDiagnostic = Readonly<{
3
+ code: 'SURFACE_ADOPTION_REFUSED';
4
+ message: string;
5
+ target: string;
6
+ }>;
7
+ export type AdoptedSettingsInspection = Readonly<{
8
+ kind: 'complete';
9
+ value: Record<string, unknown>;
10
+ }> | Readonly<{
11
+ kind: 'refusal';
12
+ diagnostic: AdoptionDiagnostic;
13
+ }>;
14
+ export type AdoptedSurfaceMerge = Readonly<{
15
+ kind: 'complete';
16
+ bytes: string;
17
+ }> | Readonly<{
18
+ kind: 'refusal';
19
+ diagnostic: AdoptionDiagnostic;
20
+ }>;
21
+ export declare function adoptedCopyPath(path: AdoptableSurfacePath): string;
22
+ /**
23
+ * Refuse, by key, everything in an adopted file that could switch off or route around the guard,
24
+ * or that carries an authority cockpit declares elsewhere. Sources for each key:
25
+ * - `disableAllHooks`: the guard evaluator names it as the switch that turns Claude's hook off.
26
+ * - `permissions.defaultMode = "bypassPermissions"`: starts every Claude session with no prompts.
27
+ * - `hooks.*` naming the guard transport: would re-register or shadow the guard hook (both
28
+ * restriction adapters register it as a PreToolUse hook in these files).
29
+ * - `permissions.additionalDirectories`, `enabledMcpjsonServers`: written from the declared
30
+ * directory grants and approved MCP servers.
31
+ * - `mcp_servers`: written from the approved MCP servers.
32
+ * - `features.codex_hooks = false`: the generator treats it as Codex's hook feature switch.
33
+ */
34
+ export declare function inspectAdoptedSettings(path: AdoptableSurfacePath, bytes: string, file?: string): AdoptedSettingsInspection;
35
+ /**
36
+ * Render one adopted harness settings file: the team's keys plus cockpit's. Hooks follow the same
37
+ * composition rule as two cockpit producers of one file; Claude permission rules are unioned with
38
+ * cockpit's deny kept authoritative; any other key is the team's unless cockpit writes it, and then
39
+ * the two must agree.
40
+ */
41
+ export declare function mergeAdoptedSurface(path: AdoptableSurfacePath, adoptedBytes: string, cockpitBytes: string | undefined): AdoptedSurfaceMerge;
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Owns the merge of a team's adopted harness settings file with cockpit's rendering of the same
3
+ * path, and the refusals that stop an adopted file from switching off or bypassing the guard.
4
+ *
5
+ * It is pure: callers read the adopted copy and supply cockpit's rendered bytes. It does not
6
+ * decide which files are adopted (cockpit.toml's `[[surfaces.adopted]]` rows do), and it never
7
+ * writes; the generated application publishes the merged bytes as an ordinary whole-file surface.
8
+ */
9
+ import { parse as parseToml, stringify as stringifyToml, TomlError } from 'smol-toml';
10
+ import { parseJsonText } from '../environment/contract.js';
11
+ import { ADOPTED_SURFACE_ROOT } from './contract.js';
12
+ import { composeHookSettings } from './render.js';
13
+ // Every guard transport is published below this directory; an adopted hook that names it is
14
+ // re-registering or shadowing the guard rather than adding a team hook.
15
+ const GUARD_DIRECTORY = '.cockpit/guards/';
16
+ export function adoptedCopyPath(path) {
17
+ return `${ADOPTED_SURFACE_ROOT}/${path}`;
18
+ }
19
+ function record(value) {
20
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
21
+ && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
22
+ }
23
+ function refusal(file, key, reason) {
24
+ return { kind: 'refusal', diagnostic: { code: 'SURFACE_ADOPTION_REFUSED', target: `${file}#${key}`,
25
+ message: `adopted settings in ${file} set \`${key}\`, which ${reason}; remove \`${key}\` from ${file} and re-run npx --no cockpit sync --config <your cockpit.toml>` } };
26
+ }
27
+ function parse(path, bytes, file) {
28
+ const invalid = (reason) => ({ kind: 'refusal', diagnostic: { code: 'SURFACE_ADOPTION_REFUSED', target: file,
29
+ message: `${reason}; fix it and re-run npx --no cockpit sync --config <your cockpit.toml>` } });
30
+ let value;
31
+ if (path === '.codex/config.toml') {
32
+ try {
33
+ value = parseToml(bytes);
34
+ }
35
+ catch (error) {
36
+ if (!(error instanceof TomlError))
37
+ throw error;
38
+ return invalid(`${file} is not valid TOML at line ${error.line}, column ${error.column}`);
39
+ }
40
+ }
41
+ else {
42
+ const parsed = parseJsonText(bytes, file, 'one settings object');
43
+ if ('refusal' in parsed)
44
+ return invalid(parsed.refusal);
45
+ value = parsed.value;
46
+ }
47
+ if (!record(value))
48
+ return { kind: 'refusal', diagnostic: { code: 'SURFACE_ADOPTION_REFUSED', target: file,
49
+ message: `${file} must hold one settings object at its root; fix it and re-run npx --no cockpit sync --config <your cockpit.toml>` } };
50
+ return { kind: 'complete', value };
51
+ }
52
+ function guardHookReference(value, file) {
53
+ const hooks = value.hooks;
54
+ if (hooks === undefined)
55
+ return undefined;
56
+ if (!record(hooks))
57
+ return refusal(file, 'hooks', 'must be an object of hook events for cockpit to keep its guard hook beside the team\'s');
58
+ for (const [event, rows] of Object.entries(hooks)) {
59
+ if (!Array.isArray(rows))
60
+ return refusal(file, `hooks.${event}`, 'must be a list of hook entries');
61
+ if (JSON.stringify(rows).includes(GUARD_DIRECTORY)) {
62
+ return refusal(file, `hooks.${event}`, 'registers or overrides cockpit\'s guard hook; cockpit adds that hook itself');
63
+ }
64
+ }
65
+ return undefined;
66
+ }
67
+ /**
68
+ * Refuse, by key, everything in an adopted file that could switch off or route around the guard,
69
+ * or that carries an authority cockpit declares elsewhere. Sources for each key:
70
+ * - `disableAllHooks`: the guard evaluator names it as the switch that turns Claude's hook off.
71
+ * - `permissions.defaultMode = "bypassPermissions"`: starts every Claude session with no prompts.
72
+ * - `hooks.*` naming the guard transport: would re-register or shadow the guard hook (both
73
+ * restriction adapters register it as a PreToolUse hook in these files).
74
+ * - `permissions.additionalDirectories`, `enabledMcpjsonServers`: written from the declared
75
+ * directory grants and approved MCP servers.
76
+ * - `mcp_servers`: written from the approved MCP servers.
77
+ * - `features.codex_hooks = false`: the generator treats it as Codex's hook feature switch.
78
+ */
79
+ export function inspectAdoptedSettings(path, bytes, file = adoptedCopyPath(path)) {
80
+ const parsed = parse(path, bytes, file);
81
+ if (parsed.kind !== 'complete')
82
+ return parsed;
83
+ const value = parsed.value;
84
+ if (path === '.claude/settings.json') {
85
+ if (Object.hasOwn(value, 'disableAllHooks') && value.disableAllHooks !== false) {
86
+ return refusal(file, 'disableAllHooks', 'switches off every hook, including cockpit\'s guard');
87
+ }
88
+ const permissions = value.permissions;
89
+ if (permissions !== undefined && !record(permissions))
90
+ return refusal(file, 'permissions', 'must be an object');
91
+ if (permissions?.defaultMode === 'bypassPermissions') {
92
+ return refusal(file, 'permissions.defaultMode', 'is "bypassPermissions" and starts every session with no permission prompts');
93
+ }
94
+ if (permissions && Object.hasOwn(permissions, 'additionalDirectories')) {
95
+ return refusal(file, 'permissions.additionalDirectories', 'cockpit writes from the declared sibling directory grants; declare the directory as a sibling instead');
96
+ }
97
+ if (Object.hasOwn(value, 'enabledMcpjsonServers')) {
98
+ return refusal(file, 'enabledMcpjsonServers', 'cockpit writes from the approved MCP servers; approve the server under [mcp] instead');
99
+ }
100
+ }
101
+ if (path === '.codex/config.toml') {
102
+ if (Object.hasOwn(value, 'mcp_servers')) {
103
+ return refusal(file, 'mcp_servers', 'cockpit writes from the approved MCP servers; approve the server under [mcp] instead');
104
+ }
105
+ const features = value.features;
106
+ if (record(features) && Object.hasOwn(features, 'codex_hooks') && features.codex_hooks !== true) {
107
+ return refusal(file, 'features.codex_hooks', 'switches off Codex hooks, including cockpit\'s guard');
108
+ }
109
+ }
110
+ if (path !== '.codex/config.toml') {
111
+ const hookRefusal = guardHookReference(value, file);
112
+ if (hookRefusal)
113
+ return hookRefusal;
114
+ }
115
+ return parsed;
116
+ }
117
+ function same(left, right) {
118
+ return JSON.stringify(left) === JSON.stringify(right);
119
+ }
120
+ function owned(file, key) {
121
+ return refusal(file, key, 'cockpit writes with a different value');
122
+ }
123
+ function strings(value) {
124
+ return Array.isArray(value) && value.every(item => typeof item === 'string');
125
+ }
126
+ /**
127
+ * Claude permission rules are unioned. Claude evaluates deny before allow, and the merge keeps that
128
+ * true in the file as well: a rule cockpit denies never also appears as a team allow or ask.
129
+ */
130
+ function mergePermissions(cockpit, adopted, file) {
131
+ const base = cockpit ?? {};
132
+ const team = adopted ?? {};
133
+ if (!record(base) || !record(team))
134
+ return refusal(file, 'permissions', 'must be an object');
135
+ const result = { ...base };
136
+ for (const key of ['allow', 'ask', 'deny']) {
137
+ if (base[key] !== undefined && !strings(base[key]))
138
+ return refusal(file, `permissions.${key}`, 'cockpit could not read as a list of rules');
139
+ if (team[key] !== undefined && !strings(team[key]))
140
+ return refusal(file, `permissions.${key}`, 'must be a list of permission rules');
141
+ }
142
+ const denied = new Set(strings(base.deny) ? base.deny : []);
143
+ for (const key of ['allow', 'ask', 'deny']) {
144
+ if (base[key] === undefined && team[key] === undefined)
145
+ continue;
146
+ const rules = [...new Set([...(base[key] ?? []), ...(team[key] ?? [])])];
147
+ result[key] = key === 'deny' ? rules : rules.filter(rule => !denied.has(rule));
148
+ }
149
+ for (const [key, value] of Object.entries(team)) {
150
+ if (key === 'allow' || key === 'ask' || key === 'deny')
151
+ continue;
152
+ if (Object.hasOwn(result, key) && !same(result[key], value))
153
+ return owned(file, `permissions.${key}`);
154
+ result[key] = value;
155
+ }
156
+ return { kind: 'complete', value: result };
157
+ }
158
+ /** Tables merge key by key; any value cockpit also writes must match it exactly. */
159
+ function mergeTables(cockpit, adopted, file, prefix = '') {
160
+ const result = { ...cockpit };
161
+ for (const [key, value] of Object.entries(adopted)) {
162
+ const name = prefix === '' ? key : `${prefix}.${key}`;
163
+ if (!Object.hasOwn(result, key)) {
164
+ result[key] = value;
165
+ continue;
166
+ }
167
+ const current = result[key];
168
+ if (record(current) && record(value)) {
169
+ const merged = mergeTables(current, value, file, name);
170
+ if (merged.kind !== 'complete')
171
+ return merged;
172
+ result[key] = merged.value;
173
+ }
174
+ else if (!same(current, value))
175
+ return owned(file, name);
176
+ }
177
+ return { kind: 'complete', value: result };
178
+ }
179
+ /**
180
+ * Render one adopted harness settings file: the team's keys plus cockpit's. Hooks follow the same
181
+ * composition rule as two cockpit producers of one file; Claude permission rules are unioned with
182
+ * cockpit's deny kept authoritative; any other key is the team's unless cockpit writes it, and then
183
+ * the two must agree.
184
+ */
185
+ export function mergeAdoptedSurface(path, adoptedBytes, cockpitBytes) {
186
+ const file = adoptedCopyPath(path);
187
+ const inspected = inspectAdoptedSettings(path, adoptedBytes, file);
188
+ if (inspected.kind !== 'complete')
189
+ return inspected;
190
+ if (cockpitBytes === undefined)
191
+ return { kind: 'complete', bytes: adoptedBytes };
192
+ const rendered = parse(path, cockpitBytes, path);
193
+ if (rendered.kind !== 'complete')
194
+ return { kind: 'refusal', diagnostic: { code: 'SURFACE_ADOPTION_REFUSED', target: path,
195
+ message: `cockpit's rendering of ${path} could not be read for merging` } };
196
+ const adopted = inspected.value;
197
+ const cockpit = rendered.value;
198
+ if (path === '.codex/config.toml') {
199
+ const merged = mergeTables(cockpit, adopted, file);
200
+ return merged.kind === 'complete' ? { kind: 'complete', bytes: stringifyToml(merged.value) } : merged;
201
+ }
202
+ let base = cockpit;
203
+ let team = adopted;
204
+ if (path === '.claude/settings.json') {
205
+ const permissions = mergePermissions(cockpit.permissions, adopted.permissions, file);
206
+ if (permissions.kind !== 'complete')
207
+ return permissions;
208
+ const { permissions: _teamPermissions, ...rest } = adopted;
209
+ base = { ...cockpit, permissions: permissions.value };
210
+ team = rest;
211
+ }
212
+ const composed = composeHookSettings([base, team]);
213
+ if (composed.kind !== 'complete')
214
+ return composed.reason === 'divergent' ? owned(file, composed.key)
215
+ : refusal(file, composed.key, 'is not shaped as a hook registration');
216
+ return { kind: 'complete', bytes: `${JSON.stringify(composed.value, null, 2)}\n` };
217
+ }
@@ -0,0 +1,20 @@
1
+ export interface ConsumerInstructionsInput {
2
+ readonly name: string;
3
+ readonly configFile: string;
4
+ readonly siblings: readonly Readonly<{
5
+ dir: string;
6
+ purpose: string;
7
+ acquire: 'auto' | 'manual' | 'none';
8
+ }>[];
9
+ readonly hasStack: boolean;
10
+ readonly guards: Readonly<{
11
+ declaredDatabaseHosts: readonly string[];
12
+ declaredVendorHosts: readonly string[];
13
+ pushRefusedBranches: readonly string[];
14
+ }>;
15
+ readonly skills: readonly Readonly<{
16
+ name: string;
17
+ description: string | undefined;
18
+ }>[];
19
+ }
20
+ export declare function renderConsumerInstructions(input: ConsumerInstructionsInput): string;
@@ -0,0 +1,43 @@
1
+ // Owns: the opening section of the AGENTS.md / CLAUDE.md that `cockpit sync` writes into a
2
+ // consumer's cockpit: what the cockpit is, how to work in it, the rules and their reasons, and
3
+ // which skills exist. Must not: read files, invent values the configuration does not declare, or
4
+ // restate what a skill already says (it points at the skill instead).
5
+ // Hands off to: generated-application/, which supplies the facts, and render.ts, which places
6
+ // the text in the shared instruction region beside the testing-tier guide.
7
+ //
8
+ // Why it is short: this text loads into every agent session, and adherence falls as it grows.
9
+ // Every command is spelled through cockpitCommand so an agent can run it exactly as written.
10
+ import { cockpitCommand } from '../fix-catalogue.js';
11
+ const HOSTS_SHOWN = 5;
12
+ const inline = (value) => value.replace(/\s+/g, ' ').replaceAll('`', "'").trim();
13
+ const cell = (value) => inline(value).replaceAll('|', '\\|');
14
+ const code = (value) => `\`${inline(value)}\``;
15
+ function hosts(label, declared) {
16
+ if (declared.length === 0)
17
+ return `${label}: not declared`;
18
+ const shown = declared.slice(0, HOSTS_SHOWN).map(code).join(', ');
19
+ return `${label}: ${shown}${declared.length > HOSTS_SHOWN ? ` and ${declared.length - HOSTS_SHOWN} more in \`[guards]\`` : ''}`;
20
+ }
21
+ export function renderConsumerInstructions(input) {
22
+ const run = (command, args) => code(cockpitCommand(command, { config: input.configFile, ...(args === undefined ? {} : { args }) }));
23
+ const acquire = { auto: `${run('setup')} clones it`, manual: 'a person clones it', none: 'already on disk' };
24
+ const { declaredDatabaseHosts, declaredVendorHosts, pushRefusedBranches } = input.guards;
25
+ const noHosts = declaredDatabaseHosts.length + declaredVendorHosts.length === 0;
26
+ const lines = [
27
+ '# What this is', '',
28
+ `This is the ${code(input.name)} cockpit. It gives every agent the same instructions, skills and guards for the repositories below${input.hasStack ? ', and starts them against your working copies' : ''}.`,
29
+ '',
30
+ '| Directory | Purpose | How it reaches disk |', '| --- | --- | --- |',
31
+ ...input.siblings.map(row => `| ${code(row.dir)} | ${cell(row.purpose)} | ${row.acquire}: ${acquire[row.acquire]} |`),
32
+ '',
33
+ '# How to work here', '',
34
+ ];
35
+ if (input.hasStack)
36
+ lines.push(`- Run ${run('session', '-- <command>')} to start the stack, run the command against it and release the stack, so nothing is left holding ports; the command gets each leased port under its \`[ports.bases]\` name and each URL as \`COCKPIT_ENTRYPOINT_<NAME>\`. ${run('up')} and ${run('down')} do it by hand (down deletes containers); ${run('doctor')} explains a stack that will not start.`);
37
+ lines.push(`- Every cockpit command takes \`--config ${inline(input.configFile)}\`. After editing that file, run ${run('sync', '--dry-run')} to preview the generated files, ${run('sync')} to write them and ${run('check')} to confirm nothing drifted. Generated files are committed and compared byte for byte, so an unsynced edit fails review.`, '', '# Rules and why', '');
38
+ lines.push(`- Never touch a non-local environment. The guard denies commands that reach a declared non-local host (${hosts('database hosts', declaredDatabaseHosts)}; ${hosts('vendor endpoints', declaredVendorHosts)}). A local mistake is cheap; a production one is not.${noHosts ? ' With none declared the guard cannot recognise one, so ask before running anything that might reach a hosted service.' : ''}`);
39
+ if (pushRefusedBranches.length > 0)
40
+ lines.push(`- Do not push to ${pushRefusedBranches.map(code).join(' or ')}. The guard refuses it, because those branches are shared and a bad push reaches everyone.`);
41
+ lines.push(`- Do not hand-edit generated files; edit ${code(input.configFile)} and sync. ${run('check')} reports a hand edit as drift and sync refuses to overwrite it; to recover, undo the edit (or delete a file cockpit wrote whole), then sync.`, '', '# Skills', '', ...input.skills.map(skill => `- ${code(skill.name)}: ${skill.description ? inline(skill.description) : 'not declared'}`));
42
+ return lines.join('\n') + '\n';
43
+ }
@@ -0,0 +1,42 @@
1
+ import { type SurfaceTarget } from './harness-registry.js';
2
+ export { SURFACE_TARGETS, type SurfaceTarget } from './harness-registry.js';
3
+ export declare const SURFACE_FEATURES: readonly ["rules", "mcp", "subagents", "skills", "hooks", "permissions"];
4
+ export declare const SURFACE_BUNDLE_FORMATS: readonly ["claudecode-plugin"];
5
+ export declare const SURFACE_FILE_MAX_BYTES = 65536;
6
+ export declare const ADOPTABLE_SURFACE_PATHS: readonly [".claude/settings.json", ".codex/config.toml", ".codex/hooks.json"];
7
+ export type AdoptableSurfacePath = typeof ADOPTABLE_SURFACE_PATHS[number];
8
+ export declare const ADOPTED_SURFACE_ROOT = "cockpit/adopted";
9
+ export declare const SURFACE_OUTPUT_MAX_BYTES = 4194304;
10
+ export declare const SURFACE_OUTPUT_MAX_FILES = 256;
11
+ export type SurfaceFeature = typeof SURFACE_FEATURES[number];
12
+ export type SurfaceBundleFormat = typeof SURFACE_BUNDLE_FORMATS[number];
13
+ export interface SurfaceSourceFile {
14
+ readonly path: string;
15
+ readonly bytes: string;
16
+ }
17
+ export interface SurfaceBatch {
18
+ readonly targets: readonly SurfaceTarget[];
19
+ readonly features: readonly SurfaceFeature[];
20
+ readonly sources: readonly SurfaceSourceFile[];
21
+ readonly expectedOutputs: Readonly<Partial<Record<SurfaceTarget, readonly string[]>>>;
22
+ }
23
+ export interface SurfaceBundleBatch {
24
+ readonly format: SurfaceBundleFormat;
25
+ readonly features: readonly SurfaceFeature[];
26
+ readonly sources: readonly SurfaceSourceFile[];
27
+ readonly expectedOutputs: readonly string[];
28
+ }
29
+ export interface RenderedSurfaceFile {
30
+ readonly target: SurfaceTarget;
31
+ readonly path: string;
32
+ readonly bytes: string;
33
+ readonly sha256: string;
34
+ }
35
+ /** Whether a path segment names a directory no surface may read or write through. */
36
+ export declare function reservedPathSegment(segment: string): boolean;
37
+ /** A bounded relative POSIX path with no empty, dot, parent or reserved segment. */
38
+ export declare function safeSurfacePath(value: unknown): value is string;
39
+ export declare function surfaceSourcesMatchFeature(input: unknown, feature: SurfaceFeature): boolean;
40
+ export declare function captureSurfaceBatch(input: unknown): SurfaceBatch | undefined;
41
+ export declare function captureSurfaceBundleBatch(input: unknown): SurfaceBundleBatch | undefined;
42
+ export declare function bundleSurfaceFiles(input: readonly RenderedSurfaceFile[]): readonly SurfaceSourceFile[] | undefined;
@@ -0,0 +1,169 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { snapshotGeneratedJson, snapshotJson } from '../environment/contract.js';
3
+ import { SURFACE_TARGETS } from './harness-registry.js';
4
+ import { exactKeys } from '../exact-keys.js';
5
+ export { SURFACE_TARGETS } from './harness-registry.js';
6
+ export const SURFACE_FEATURES = Object.freeze(['rules', 'mcp', 'subagents', 'skills', 'hooks', 'permissions']);
7
+ export const SURFACE_BUNDLE_FORMATS = Object.freeze(['claudecode-plugin']);
8
+ export const SURFACE_FILE_MAX_BYTES = 65_536;
9
+ // The harness settings files cockpit renders whole and a team may already keep its own copy of.
10
+ // Adoption moves the team's bytes under ADOPTED_SURFACE_ROOT and renders a merge of both; every
11
+ // other surface path is either cockpit's alone or already shares a marked region.
12
+ export const ADOPTABLE_SURFACE_PATHS = Object.freeze(['.claude/settings.json', '.codex/config.toml', '.codex/hooks.json']);
13
+ export const ADOPTED_SURFACE_ROOT = 'cockpit/adopted';
14
+ export const SURFACE_OUTPUT_MAX_BYTES = 4_194_304;
15
+ export const SURFACE_OUTPUT_MAX_FILES = 256;
16
+ const TARGETS = new Set(SURFACE_TARGETS);
17
+ const FEATURES = new Set(SURFACE_FEATURES);
18
+ const CLAUDE_PLUGIN_FEATURES = new Set(['mcp', 'subagents', 'skills', 'hooks']);
19
+ const SHA256 = /^[a-f0-9]{64}$/;
20
+ const RULE_PATH = /^rules\/[^/]+\.md$/;
21
+ const SUBAGENT_PATH = /^subagents\/[^/]+\.md$/;
22
+ const SKILL_PATH = /^skills\/([a-z0-9][a-z0-9-]*)\/(.+)$/;
23
+ // A generated file under Git's directory could install a hook; one under node_modules would be
24
+ // shadowed or wiped by the next install. Folded because the default macOS and Windows filesystems
25
+ // resolve `.GIT` and `Node_Modules` to the same directories. Upper-casing also folds characters
26
+ // such as `ſ`, which lower-casing leaves alone but case-insensitive filesystems treat as `s`.
27
+ const RESERVED_SEGMENTS = new Set(['.GIT', 'NODE_MODULES']);
28
+ /** Whether a path segment names a directory no surface may read or write through. */
29
+ export function reservedPathSegment(segment) {
30
+ return RESERVED_SEGMENTS.has(segment.normalize('NFC').toUpperCase());
31
+ }
32
+ /** A bounded relative POSIX path with no empty, dot, parent or reserved segment. */
33
+ export function safeSurfacePath(value) {
34
+ return typeof value === 'string' && value.length > 0 && value.length <= 4096 && !value.startsWith('/')
35
+ && !/^[a-z]:[/\\]/i.test(value) && !/[\\\x00-\x1f\x7f]/.test(value)
36
+ && value.split('/').every(part => part !== '' && part !== '.' && part !== '..' && !reservedPathSegment(part));
37
+ }
38
+ function isObject(value) {
39
+ return value !== undefined && value !== null && typeof value === 'object' && !Array.isArray(value);
40
+ }
41
+ function stringArray(value) {
42
+ return Array.isArray(value) && value.length > 0 && value.every(item => typeof item === 'string')
43
+ ? value
44
+ : undefined;
45
+ }
46
+ function uniqueValues(values) {
47
+ return new Set(values).size === values.length;
48
+ }
49
+ function sourceFeature(path) {
50
+ if (RULE_PATH.test(path))
51
+ return 'rules';
52
+ if (path === 'mcp.jsonc')
53
+ return 'mcp';
54
+ if (SUBAGENT_PATH.test(path))
55
+ return 'subagents';
56
+ if (SKILL_PATH.test(path))
57
+ return 'skills';
58
+ if (path === 'hooks.jsonc')
59
+ return 'hooks';
60
+ if (path === 'permissions.jsonc')
61
+ return 'permissions';
62
+ return undefined;
63
+ }
64
+ function validSourceFiles(value, requested) {
65
+ if (!Array.isArray(value) || value.length === 0)
66
+ return false;
67
+ const paths = new Set();
68
+ const supplied = new Set();
69
+ const skillRoots = new Set();
70
+ const skillDefinitions = new Set();
71
+ for (const item of value) {
72
+ if (!isObject(item) || !exactKeys(item, ['path', 'bytes'])
73
+ || typeof item.path !== 'string' || typeof item.bytes !== 'string'
74
+ || Buffer.byteLength(item.bytes) > SURFACE_FILE_MAX_BYTES
75
+ || !safeSurfacePath(item.path) || paths.has(item.path))
76
+ return false;
77
+ const feature = sourceFeature(item.path);
78
+ if (!feature || !requested.has(feature))
79
+ return false;
80
+ paths.add(item.path);
81
+ supplied.add(feature);
82
+ const skill = SKILL_PATH.exec(item.path);
83
+ if (skill) {
84
+ const root = skill[1];
85
+ skillRoots.add(root);
86
+ if (skill[2] === 'SKILL.md')
87
+ skillDefinitions.add(root);
88
+ }
89
+ }
90
+ return [...requested].every(feature => supplied.has(feature))
91
+ && [...skillRoots].every(root => skillDefinitions.has(root));
92
+ }
93
+ export function surfaceSourcesMatchFeature(input, feature) {
94
+ return FEATURES.has(feature) && validSourceFiles(snapshotJson(input), new Set([feature]));
95
+ }
96
+ function validExpectedOutputs(value, targets) {
97
+ if (!isObject(value) || !exactKeys(value, targets))
98
+ return false;
99
+ for (const target of targets) {
100
+ const paths = stringArray(value[target]);
101
+ if (!paths || !uniqueValues(paths) || paths.some(path => !safeSurfacePath(path)))
102
+ return false;
103
+ }
104
+ return true;
105
+ }
106
+ export function captureSurfaceBatch(input) {
107
+ const snapshot = snapshotJson(input);
108
+ if (!isObject(snapshot) || !exactKeys(snapshot, ['targets', 'features', 'sources', 'expectedOutputs']))
109
+ return undefined;
110
+ const targets = stringArray(snapshot.targets);
111
+ const features = stringArray(snapshot.features);
112
+ if (!targets || !uniqueValues(targets) || !targets.every(target => TARGETS.has(target))
113
+ || !features || !uniqueValues(features) || !features.every(feature => FEATURES.has(feature)))
114
+ return undefined;
115
+ const admittedTargets = targets;
116
+ const admittedFeatures = features;
117
+ if (!validSourceFiles(snapshot.sources, new Set(admittedFeatures))
118
+ || !validExpectedOutputs(snapshot.expectedOutputs, admittedTargets))
119
+ return undefined;
120
+ return snapshot;
121
+ }
122
+ export function captureSurfaceBundleBatch(input) {
123
+ const snapshot = snapshotJson(input);
124
+ if (!isObject(snapshot) || !exactKeys(snapshot, ['format', 'features', 'sources', 'expectedOutputs'])
125
+ || snapshot.format !== 'claudecode-plugin')
126
+ return undefined;
127
+ const features = stringArray(snapshot.features);
128
+ const expectedOutputs = stringArray(snapshot.expectedOutputs);
129
+ if (!features || !uniqueValues(features)
130
+ || !features.every(feature => CLAUDE_PLUGIN_FEATURES.has(feature))
131
+ || !expectedOutputs || !uniqueValues(expectedOutputs) || expectedOutputs.some(path => !safeSurfacePath(path))
132
+ || !validSourceFiles(snapshot.sources, new Set(features)))
133
+ return undefined;
134
+ return snapshot;
135
+ }
136
+ function renderedFile(value) {
137
+ if (!isObject(value) || !exactKeys(value, ['target', 'path', 'bytes', 'sha256'])
138
+ || typeof value.target !== 'string' || !TARGETS.has(value.target)
139
+ || typeof value.path !== 'string' || !safeSurfacePath(value.path)
140
+ || typeof value.bytes !== 'string' || Buffer.byteLength(value.bytes) > SURFACE_FILE_MAX_BYTES
141
+ || typeof value.sha256 !== 'string' || !SHA256.test(value.sha256)
142
+ || createHash('sha256').update(value.bytes).digest('hex') !== value.sha256)
143
+ return undefined;
144
+ return value;
145
+ }
146
+ export function bundleSurfaceFiles(input) {
147
+ const snapshot = snapshotGeneratedJson(input);
148
+ if (!Array.isArray(snapshot) || snapshot.length === 0 || snapshot.length > SURFACE_OUTPUT_MAX_FILES)
149
+ return undefined;
150
+ const paths = new Set();
151
+ const bundled = [];
152
+ let totalBytes = 0;
153
+ for (const item of snapshot) {
154
+ const admitted = renderedFile(item);
155
+ if (!admitted)
156
+ return undefined;
157
+ const path = `${admitted.target}/${admitted.path}`;
158
+ if (paths.has(path))
159
+ return undefined;
160
+ totalBytes += Buffer.byteLength(admitted.bytes);
161
+ if (totalBytes > SURFACE_OUTPUT_MAX_BYTES)
162
+ return undefined;
163
+ paths.add(path);
164
+ bundled.push({ path, bytes: admitted.bytes });
165
+ }
166
+ bundled.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
167
+ const bounded = snapshotGeneratedJson(bundled);
168
+ return Array.isArray(bounded) ? bounded : undefined;
169
+ }
@@ -0,0 +1,24 @@
1
+ import type { SurfaceDeclaration } from '../schema.js';
2
+ import type { SurfaceTarget } from './contract.js';
3
+ export declare const CORE_EVALUATOR_ASSET: 'agents/evaluator.agent.md';
4
+ export declare const CORE_SKILL_PROCEDURES: Readonly<{
5
+ readonly 'cockpit-setup': 'procedures/setup.md';
6
+ readonly 'cockpit-explain': 'procedures/explain.md';
7
+ readonly 'cockpit-fix': 'procedures/fix.md';
8
+ readonly 'cockpit-work': 'procedures/work.md';
9
+ }>;
10
+ export declare const CORE_PROCEDURE_ASSETS: readonly ["skills/procedures/setup.md", "skills/procedures/explain.md", "skills/procedures/fix.md", "skills/procedures/work.md"];
11
+ export declare const CORE_SKILL_ASSETS: readonly ["skills/collection.json", "skills/cockpit-setup.skill.md", "skills/cockpit-explain.skill.md", "skills/cockpit-fix.skill.md", "skills/cockpit-work.skill.md", "skills/procedures/setup.md", "skills/procedures/explain.md", "skills/procedures/fix.md", "skills/procedures/work.md"];
12
+ type CoreAsset = Readonly<{
13
+ bytes: string;
14
+ }>;
15
+ /** Each shipped skill's entry point and its own procedure, as neutral skill sources. */
16
+ export declare function shippedSkillSources(assets: ReadonlyMap<string, CoreAsset>, tools: readonly SurfaceTarget[]): readonly Readonly<{
17
+ name: string;
18
+ sources: readonly Readonly<{
19
+ path: string;
20
+ bytes: string;
21
+ }>[];
22
+ }>[] | undefined;
23
+ export declare function coreSurfaceDeclarations(assets: ReadonlyMap<string, CoreAsset>, tools: readonly SurfaceTarget[]): readonly SurfaceDeclaration[] | undefined;
24
+ export {};