@b00dea/cockpit 0.0.0-stage → 0.1.0

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 (363) hide show
  1. package/CHANGELOG.md +375 -0
  2. package/LICENSE +21 -0
  3. package/README.md +22 -2
  4. package/bin/cockpit.mjs +33 -0
  5. package/cockpit.schema.json +2574 -0
  6. package/dist/autonomy.d.ts +44 -0
  7. package/dist/autonomy.js +156 -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 +62 -0
  11. package/dist/browser/commands.js +349 -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 +117 -0
  17. package/dist/browser/runtime.js +183 -0
  18. package/dist/browser/surfaces.d.ts +141 -0
  19. package/dist/browser/surfaces.js +556 -0
  20. package/dist/browser/ui-gate.d.ts +15 -0
  21. package/dist/browser/ui-gate.js +18 -0
  22. package/dist/cli-guard.d.ts +5 -0
  23. package/dist/cli-guard.js +71 -0
  24. package/dist/cli-main.d.ts +139 -0
  25. package/dist/cli-main.js +1405 -0
  26. package/dist/cli.d.ts +3 -0
  27. package/dist/cli.js +16 -0
  28. package/dist/command-table.d.ts +113 -0
  29. package/dist/command-table.js +512 -0
  30. package/dist/config/load.d.ts +171 -0
  31. package/dist/config/load.js +345 -0
  32. package/dist/config/sibling-toml.d.ts +48 -0
  33. package/dist/config/sibling-toml.js +160 -0
  34. package/dist/config/surface-tools-toml.d.ts +9 -0
  35. package/dist/config/surface-tools-toml.js +37 -0
  36. package/dist/config/verified-write.d.ts +43 -0
  37. package/dist/config/verified-write.js +89 -0
  38. package/dist/diagnostics.d.ts +26 -0
  39. package/dist/diagnostics.js +335 -0
  40. package/dist/emit.d.ts +22 -0
  41. package/dist/emit.js +43 -0
  42. package/dist/entrypoint-kinds.d.ts +3 -0
  43. package/dist/entrypoint-kinds.js +11 -0
  44. package/dist/environment/application/destructive.d.ts +6 -0
  45. package/dist/environment/application/destructive.js +425 -0
  46. package/dist/environment/application/doctor.d.ts +89 -0
  47. package/dist/environment/application/doctor.js +235 -0
  48. package/dist/environment/application/guard.d.ts +43 -0
  49. package/dist/environment/application/guard.js +622 -0
  50. package/dist/environment/application/health.d.ts +134 -0
  51. package/dist/environment/application/health.js +379 -0
  52. package/dist/environment/application/lifecycle-context.d.ts +228 -0
  53. package/dist/environment/application/lifecycle-context.js +154 -0
  54. package/dist/environment/application/lifecycle-state.d.ts +25 -0
  55. package/dist/environment/application/lifecycle-state.js +201 -0
  56. package/dist/environment/application/lifecycle.d.ts +17 -0
  57. package/dist/environment/application/lifecycle.js +729 -0
  58. package/dist/environment/application/logs.d.ts +45 -0
  59. package/dist/environment/application/logs.js +127 -0
  60. package/dist/environment/application/setup.d.ts +129 -0
  61. package/dist/environment/application/setup.js +741 -0
  62. package/dist/environment/application/shared.d.ts +11 -0
  63. package/dist/environment/application/shared.js +61 -0
  64. package/dist/environment/claims.d.ts +389 -0
  65. package/dist/environment/claims.js +1709 -0
  66. package/dist/environment/codex-hook-trust.d.ts +11 -0
  67. package/dist/environment/codex-hook-trust.js +185 -0
  68. package/dist/environment/compose-environment.d.ts +1 -0
  69. package/dist/environment/compose-environment.js +6 -0
  70. package/dist/environment/compose-ownership.d.ts +21 -0
  71. package/dist/environment/compose-ownership.js +117 -0
  72. package/dist/environment/compose-topology.d.ts +117 -0
  73. package/dist/environment/compose-topology.js +413 -0
  74. package/dist/environment/contract.d.ts +489 -0
  75. package/dist/environment/contract.js +761 -0
  76. package/dist/environment/declaration.d.ts +14 -0
  77. package/dist/environment/declaration.js +39 -0
  78. package/dist/environment/destructive-composition.d.ts +29 -0
  79. package/dist/environment/destructive-composition.js +333 -0
  80. package/dist/environment/docker-daemon.d.ts +30 -0
  81. package/dist/environment/docker-daemon.js +78 -0
  82. package/dist/environment/docker-endpoint.d.ts +10 -0
  83. package/dist/environment/docker-endpoint.js +19 -0
  84. package/dist/environment/env-schema-observation.d.ts +46 -0
  85. package/dist/environment/env-schema-observation.js +241 -0
  86. package/dist/environment/evidence.d.ts +136 -0
  87. package/dist/environment/evidence.js +437 -0
  88. package/dist/environment/executable.d.ts +26 -0
  89. package/dist/environment/executable.js +167 -0
  90. package/dist/environment/generated-application/authorities.d.ts +5 -0
  91. package/dist/environment/generated-application/authorities.js +61 -0
  92. package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
  93. package/dist/environment/generated-application/bootstrap-skill.js +328 -0
  94. package/dist/environment/generated-application/check.d.ts +13 -0
  95. package/dist/environment/generated-application/check.js +189 -0
  96. package/dist/environment/generated-application/custom-surface.d.ts +26 -0
  97. package/dist/environment/generated-application/custom-surface.js +289 -0
  98. package/dist/environment/generated-application/prepare.d.ts +29 -0
  99. package/dist/environment/generated-application/prepare.js +276 -0
  100. package/dist/environment/generated-application/publication.d.ts +33 -0
  101. package/dist/environment/generated-application/publication.js +547 -0
  102. package/dist/environment/generated-application/shared.d.ts +484 -0
  103. package/dist/environment/generated-application/shared.js +349 -0
  104. package/dist/environment/generated-application/surface-observation.d.ts +4 -0
  105. package/dist/environment/generated-application/surface-observation.js +69 -0
  106. package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
  107. package/dist/environment/generated-application/surface-outputs.js +389 -0
  108. package/dist/environment/generated-application/surfaces.d.ts +3 -0
  109. package/dist/environment/generated-application/surfaces.js +699 -0
  110. package/dist/environment/generated-application/sync.d.ts +6 -0
  111. package/dist/environment/generated-application/sync.js +109 -0
  112. package/dist/environment/git-observation.d.ts +183 -0
  113. package/dist/environment/git-observation.js +544 -0
  114. package/dist/environment/health-composition.d.ts +11 -0
  115. package/dist/environment/health-composition.js +628 -0
  116. package/dist/environment/host-observation.d.ts +56 -0
  117. package/dist/environment/host-observation.js +52 -0
  118. package/dist/environment/identity.d.ts +48 -0
  119. package/dist/environment/identity.js +85 -0
  120. package/dist/environment/init-application.d.ts +308 -0
  121. package/dist/environment/init-application.js +697 -0
  122. package/dist/environment/install-policy-observation.d.ts +71 -0
  123. package/dist/environment/install-policy-observation.js +284 -0
  124. package/dist/environment/install-policy.d.ts +48 -0
  125. package/dist/environment/install-policy.js +96 -0
  126. package/dist/environment/instance.d.ts +33 -0
  127. package/dist/environment/instance.js +122 -0
  128. package/dist/environment/instruction-pointer.d.ts +19 -0
  129. package/dist/environment/instruction-pointer.js +144 -0
  130. package/dist/environment/lifecycle-composition.d.ts +29 -0
  131. package/dist/environment/lifecycle-composition.js +675 -0
  132. package/dist/environment/lifecycle-stage.d.ts +115 -0
  133. package/dist/environment/lifecycle-stage.js +398 -0
  134. package/dist/environment/lifecycle.d.ts +75 -0
  135. package/dist/environment/lifecycle.js +354 -0
  136. package/dist/environment/logs.d.ts +132 -0
  137. package/dist/environment/logs.js +519 -0
  138. package/dist/environment/observations.d.ts +46 -0
  139. package/dist/environment/observations.js +344 -0
  140. package/dist/environment/operator-application.d.ts +50 -0
  141. package/dist/environment/operator-application.js +155 -0
  142. package/dist/environment/ports.d.ts +182 -0
  143. package/dist/environment/ports.js +1205 -0
  144. package/dist/environment/posture-observation.d.ts +68 -0
  145. package/dist/environment/posture-observation.js +253 -0
  146. package/dist/environment/read-composition.d.ts +27 -0
  147. package/dist/environment/read-composition.js +352 -0
  148. package/dist/environment/readiness-composition.d.ts +38 -0
  149. package/dist/environment/readiness-composition.js +130 -0
  150. package/dist/environment/reclaim.d.ts +333 -0
  151. package/dist/environment/reclaim.js +1835 -0
  152. package/dist/environment/repository-identity.d.ts +13 -0
  153. package/dist/environment/repository-identity.js +108 -0
  154. package/dist/environment/runtime-measurement-record.d.ts +38 -0
  155. package/dist/environment/runtime-measurement-record.js +111 -0
  156. package/dist/environment/runtime-measurement.d.ts +27 -0
  157. package/dist/environment/runtime-measurement.js +224 -0
  158. package/dist/environment/runtime-probe-residue.d.ts +43 -0
  159. package/dist/environment/runtime-probe-residue.js +148 -0
  160. package/dist/environment/runtime-probe.d.ts +72 -0
  161. package/dist/environment/runtime-probe.js +725 -0
  162. package/dist/environment/runtime.d.ts +505 -0
  163. package/dist/environment/runtime.js +2335 -0
  164. package/dist/environment/seed.d.ts +16 -0
  165. package/dist/environment/seed.js +43 -0
  166. package/dist/environment/selftest-application.d.ts +86 -0
  167. package/dist/environment/selftest-application.js +713 -0
  168. package/dist/environment/sensitive.d.ts +3 -0
  169. package/dist/environment/sensitive.js +48 -0
  170. package/dist/environment/setup-observation.d.ts +62 -0
  171. package/dist/environment/setup-observation.js +1473 -0
  172. package/dist/environment/setup.d.ts +43 -0
  173. package/dist/environment/setup.js +176 -0
  174. package/dist/environment/sibling-instructions.d.ts +33 -0
  175. package/dist/environment/sibling-instructions.js +224 -0
  176. package/dist/environment/sibling-registration.d.ts +45 -0
  177. package/dist/environment/sibling-registration.js +538 -0
  178. package/dist/environment/state.d.ts +371 -0
  179. package/dist/environment/state.js +2013 -0
  180. package/dist/environment/templates.d.ts +140 -0
  181. package/dist/environment/templates.js +685 -0
  182. package/dist/environment/tool-registration.d.ts +9 -0
  183. package/dist/environment/tool-registration.js +96 -0
  184. package/dist/environment/upgrade-application.d.ts +19 -0
  185. package/dist/environment/upgrade-application.js +175 -0
  186. package/dist/environment-exec/execute.d.ts +102 -0
  187. package/dist/environment-exec/execute.js +1175 -0
  188. package/dist/environment-exec/libexec-program.d.ts +6 -0
  189. package/dist/environment-exec/libexec-program.js +22 -0
  190. package/dist/environment-exec/verified-digest.d.ts +4 -0
  191. package/dist/environment-exec/verified-digest.js +16 -0
  192. package/dist/exact-keys.d.ts +7 -0
  193. package/dist/exact-keys.js +15 -0
  194. package/dist/fix-catalogue.d.ts +32 -0
  195. package/dist/fix-catalogue.js +60 -0
  196. package/dist/freshness.d.ts +29 -0
  197. package/dist/freshness.js +75 -0
  198. package/dist/generated-environment/adopt.d.ts +16 -0
  199. package/dist/generated-environment/adopt.js +275 -0
  200. package/dist/generated-environment/command.d.ts +47 -0
  201. package/dist/generated-environment/command.js +75 -0
  202. package/dist/generated-environment/transaction.d.ts +186 -0
  203. package/dist/generated-environment/transaction.js +1770 -0
  204. package/dist/grading/evaluate.d.ts +71 -0
  205. package/dist/grading/evaluate.js +403 -0
  206. package/dist/grading/grade.d.ts +33 -0
  207. package/dist/grading/grade.js +57 -0
  208. package/dist/guards/evaluator.d.ts +113 -0
  209. package/dist/guards/evaluator.js +1226 -0
  210. package/dist/guards/harness-adapter.d.ts +17 -0
  211. package/dist/guards/harness-adapter.js +57 -0
  212. package/dist/guards/host.d.ts +8 -0
  213. package/dist/guards/host.js +10 -0
  214. package/dist/guards/invocation-parser.d.ts +66 -0
  215. package/dist/guards/invocation-parser.js +595 -0
  216. package/dist/guards/local-identity.d.ts +40 -0
  217. package/dist/guards/local-identity.js +123 -0
  218. package/dist/guards/policy-pin.d.ts +13 -0
  219. package/dist/guards/policy-pin.js +175 -0
  220. package/dist/guards/protected-locations.d.ts +62 -0
  221. package/dist/guards/protected-locations.js +461 -0
  222. package/dist/guards/read-only.d.ts +37 -0
  223. package/dist/guards/read-only.js +315 -0
  224. package/dist/init/command.d.ts +40 -0
  225. package/dist/init/command.js +310 -0
  226. package/dist/init/derive.d.ts +51 -0
  227. package/dist/init/derive.js +715 -0
  228. package/dist/init/draft.d.ts +138 -0
  229. package/dist/init/draft.js +1205 -0
  230. package/dist/init/render.d.ts +35 -0
  231. package/dist/init/render.js +82 -0
  232. package/dist/init/scaffold.d.ts +53 -0
  233. package/dist/init/scaffold.js +121 -0
  234. package/dist/invocation.d.ts +13 -0
  235. package/dist/invocation.js +20 -0
  236. package/dist/package-metadata.d.ts +9 -0
  237. package/dist/package-metadata.js +19 -0
  238. package/dist/readiness.d.ts +53 -0
  239. package/dist/readiness.js +88 -0
  240. package/dist/references/named.d.ts +24 -0
  241. package/dist/references/named.js +27 -0
  242. package/dist/refusal.d.ts +15 -0
  243. package/dist/refusal.js +7 -0
  244. package/dist/registry-derivation.d.ts +31 -0
  245. package/dist/registry-derivation.js +32 -0
  246. package/dist/registry-resolve/command.d.ts +47 -0
  247. package/dist/registry-resolve/command.js +226 -0
  248. package/dist/registry-resolve/registry.d.ts +68 -0
  249. package/dist/registry-resolve/registry.js +292 -0
  250. package/dist/registry-resolve/render-shell.d.ts +18 -0
  251. package/dist/registry-resolve/render-shell.js +36 -0
  252. package/dist/repair.d.ts +29 -0
  253. package/dist/repair.js +8 -0
  254. package/dist/schema-json.d.ts +1 -0
  255. package/dist/schema-json.js +177 -0
  256. package/dist/schema.d.ts +1322 -0
  257. package/dist/schema.js +934 -0
  258. package/dist/setup/command.d.ts +4 -0
  259. package/dist/setup/command.js +4 -0
  260. package/dist/sha256.d.ts +1 -0
  261. package/dist/sha256.js +4 -0
  262. package/dist/surfaces/adoption.d.ts +41 -0
  263. package/dist/surfaces/adoption.js +217 -0
  264. package/dist/surfaces/consumer-instructions.d.ts +20 -0
  265. package/dist/surfaces/consumer-instructions.js +43 -0
  266. package/dist/surfaces/contract.d.ts +42 -0
  267. package/dist/surfaces/contract.js +169 -0
  268. package/dist/surfaces/core-declarations.d.ts +24 -0
  269. package/dist/surfaces/core-declarations.js +79 -0
  270. package/dist/surfaces/development-markers.d.ts +1 -0
  271. package/dist/surfaces/development-markers.js +18 -0
  272. package/dist/surfaces/generator-adapter.d.ts +71 -0
  273. package/dist/surfaces/generator-adapter.js +809 -0
  274. package/dist/surfaces/harness-registry.d.ts +180 -0
  275. package/dist/surfaces/harness-registry.js +117 -0
  276. package/dist/surfaces/mcp.d.ts +95 -0
  277. package/dist/surfaces/mcp.js +186 -0
  278. package/dist/surfaces/merge.d.ts +30 -0
  279. package/dist/surfaces/merge.js +105 -0
  280. package/dist/surfaces/ownership.d.ts +190 -0
  281. package/dist/surfaces/ownership.js +795 -0
  282. package/dist/surfaces/projection.d.ts +136 -0
  283. package/dist/surfaces/projection.js +681 -0
  284. package/dist/surfaces/render.d.ts +118 -0
  285. package/dist/surfaces/render.js +633 -0
  286. package/dist/surfaces/restrictions.d.ts +130 -0
  287. package/dist/surfaces/restrictions.js +447 -0
  288. package/dist/surfaces/selftest.d.ts +162 -0
  289. package/dist/surfaces/selftest.js +393 -0
  290. package/dist/surfaces/skill-contract.d.ts +85 -0
  291. package/dist/surfaces/skill-contract.js +449 -0
  292. package/dist/surfaces/sync.d.ts +57 -0
  293. package/dist/surfaces/sync.js +164 -0
  294. package/dist/team-metadata.d.ts +41 -0
  295. package/dist/team-metadata.js +512 -0
  296. package/dist/testing/gates.d.ts +91 -0
  297. package/dist/testing/gates.js +182 -0
  298. package/dist/testing/hooks.d.ts +59 -0
  299. package/dist/testing/hooks.js +139 -0
  300. package/dist/testing/verdict.d.ts +29 -0
  301. package/dist/testing/verdict.js +62 -0
  302. package/dist/work-orders/application.d.ts +99 -0
  303. package/dist/work-orders/application.js +383 -0
  304. package/dist/work-orders/composition.d.ts +124 -0
  305. package/dist/work-orders/composition.js +1010 -0
  306. package/dist/work-orders/contract.d.ts +61 -0
  307. package/dist/work-orders/contract.js +122 -0
  308. package/dist/work-orders/store.d.ts +158 -0
  309. package/dist/work-orders/store.js +197 -0
  310. package/docs/README.md +65 -0
  311. package/docs/architecture.md +136 -0
  312. package/docs/capability-matrix.md +50 -0
  313. package/docs/cli-reference.md +599 -0
  314. package/docs/command-list.md +51 -0
  315. package/docs/compose-patterns.md +99 -0
  316. package/docs/concepts.md +171 -0
  317. package/docs/configuration-essentials.md +172 -0
  318. package/docs/configuration-reference.md +621 -0
  319. package/docs/environment.md +760 -0
  320. package/docs/extending.md +43 -0
  321. package/docs/faq.md +111 -0
  322. package/docs/getting-started.md +608 -0
  323. package/docs/harness-surfaces.md +433 -0
  324. package/docs/joining-a-team.md +76 -0
  325. package/docs/release-policy.md +49 -0
  326. package/docs/safety-and-autonomy.md +419 -0
  327. package/docs/troubleshooting.md +361 -0
  328. package/docs/tutorial.md +170 -0
  329. package/docs/work-and-browser.md +254 -0
  330. package/libexec/browser-operation.cjs +186 -0
  331. package/libexec/fence-marker.cjs +101 -0
  332. package/libexec/fence-marker.d.cts +24 -0
  333. package/libexec/fenced-group-runner.cjs +77 -0
  334. package/libexec/fenced-supervisor.cjs +137 -0
  335. package/libexec/generated-filesystem.cjs +731 -0
  336. package/libexec/install-filesystem.cjs +225 -0
  337. package/libexec/rulesync-generator.NOTICE.md +1112 -0
  338. package/libexec/rulesync-generator.cjs +743 -0
  339. package/libexec/surface-generator-worker.cjs +266 -0
  340. package/libexec/surface-output-reader.cjs +99 -0
  341. package/libexec/surface-scratch-cleanup.cjs +14 -0
  342. package/libexec/validate-harness-evidence.d.mts +183 -0
  343. package/libexec/validate-harness-evidence.mjs +1312 -0
  344. package/package.json +74 -4
  345. package/surfaces/README.md +33 -0
  346. package/surfaces/agents/evaluator.agent.md +76 -0
  347. package/surfaces/guards/bash-guard.sh +48 -0
  348. package/surfaces/guards/claude.adapter.json +25 -0
  349. package/surfaces/guards/codex.adapter.json +24 -0
  350. package/surfaces/guards/opencode.adapter.json +25 -0
  351. package/surfaces/references/browser.md +63 -0
  352. package/surfaces/references/test-data-and-personas.md +84 -0
  353. package/surfaces/references/testing-tiers.md +11 -0
  354. package/surfaces/skills/cockpit-browser.skill.md +54 -0
  355. package/surfaces/skills/cockpit-explain.skill.md +32 -0
  356. package/surfaces/skills/cockpit-fix.skill.md +37 -0
  357. package/surfaces/skills/cockpit-setup.skill.md +39 -0
  358. package/surfaces/skills/cockpit-work.skill.md +34 -0
  359. package/surfaces/skills/collection.json +5 -0
  360. package/surfaces/skills/procedures/explain.md +61 -0
  361. package/surfaces/skills/procedures/fix.md +81 -0
  362. package/surfaces/skills/procedures/setup.md +379 -0
  363. package/surfaces/skills/procedures/work.md +105 -0
@@ -0,0 +1,2574 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "unconfirmed": {
6
+ "description": "Answers no person has stated yet; init writes them and doctor reports them.",
7
+ "minItems": 1,
8
+ "maxItems": 11,
9
+ "type": "array",
10
+ "items": {
11
+ "type": "string",
12
+ "enum": [
13
+ "cockpit.name",
14
+ "sibling",
15
+ "estate.runnable",
16
+ "ports.bases",
17
+ "environment.install_policies",
18
+ "environment.test_data",
19
+ "environment.compose_files",
20
+ "environment.machine",
21
+ "environment.posture",
22
+ "testing",
23
+ "guards"
24
+ ]
25
+ }
26
+ },
27
+ "cockpit": {
28
+ "type": "object",
29
+ "properties": {
30
+ "name": {
31
+ "type": "string",
32
+ "pattern": "^[a-z0-9][a-z0-9-]*$",
33
+ "description": "Name of this cockpit."
34
+ },
35
+ "siblings_root": {
36
+ "default": "..",
37
+ "description": "Directory holding the sibling checkouts, relative to the cockpit.",
38
+ "type": "string"
39
+ },
40
+ "guide_cap": {
41
+ "default": 200,
42
+ "description": "Most lines of always-loaded guidance; preflight fails above it.",
43
+ "type": "integer",
44
+ "minimum": 0,
45
+ "exclusiveMinimum": true,
46
+ "maximum": 9007199254740991
47
+ }
48
+ },
49
+ "required": [
50
+ "name"
51
+ ],
52
+ "additionalProperties": false,
53
+ "description": "Identity and layout of this cockpit."
54
+ },
55
+ "sibling": {
56
+ "minItems": 1,
57
+ "type": "array",
58
+ "items": {
59
+ "type": "object",
60
+ "properties": {
61
+ "slug": {
62
+ "type": "string",
63
+ "pattern": "^[a-z0-9][a-z0-9-]*$",
64
+ "description": "Short name of the sibling; also how the root AGENTS.md labels its copied guides."
65
+ },
66
+ "dir": {
67
+ "anyOf": [
68
+ {
69
+ "type": "string",
70
+ "enum": [
71
+ "."
72
+ ]
73
+ },
74
+ {
75
+ "type": "string",
76
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
77
+ }
78
+ ],
79
+ "description": "Checkout directory under the siblings root, or . for the siblings root itself."
80
+ },
81
+ "remote": {
82
+ "description": "Git remote to clone from; required when acquire is auto or manual and not allowed when none.",
83
+ "type": "string",
84
+ "minLength": 1
85
+ },
86
+ "branch": {
87
+ "description": "Branch to check out when cloning.",
88
+ "type": "string",
89
+ "minLength": 1
90
+ },
91
+ "mount": {
92
+ "anyOf": [
93
+ {
94
+ "type": "string",
95
+ "enum": [
96
+ "always",
97
+ "host",
98
+ "none"
99
+ ]
100
+ },
101
+ {
102
+ "type": "string",
103
+ "pattern": "^profile:[a-z0-9-]+$"
104
+ }
105
+ ],
106
+ "description": "How the stack uses the checkout: always mounted, mounted under a profile, host only, or not mounted."
107
+ },
108
+ "acquire": {
109
+ "type": "string",
110
+ "enum": [
111
+ "auto",
112
+ "manual",
113
+ "none"
114
+ ],
115
+ "description": "How the checkout reaches disk: cloned by setup, cloned by a person, or not a repository."
116
+ },
117
+ "var": {
118
+ "type": "string",
119
+ "pattern": "^(?!(?:DOCKER_|COMPOSE_|LD_|DYLD_|LIBPATH$|SHLIB_PATH$|NODE_OPTIONS$|NODE_PATH$|BASH_ENV$|ENV$|PATH$|IFS$))[A-Z][A-Z0-9_]*$",
120
+ "description": "Name of the exported *_DIR environment variable that points at the checkout."
121
+ },
122
+ "toolchain": {
123
+ "default": "none",
124
+ "description": "Toolchain that installs and tests the sibling; none for a directory of data.",
125
+ "type": "string",
126
+ "enum": [
127
+ "node",
128
+ "python",
129
+ "ruby",
130
+ "go",
131
+ "rust",
132
+ "dotnet",
133
+ "none"
134
+ ]
135
+ },
136
+ "gate": {
137
+ "description": "Set to operator for a lane that touches live data or local hardware; it never runs by default and asks first.",
138
+ "type": "string",
139
+ "enum": [
140
+ "operator"
141
+ ]
142
+ },
143
+ "host_reason": {
144
+ "description": "Why the sibling cannot join the stack; required when mount is host.",
145
+ "type": "string",
146
+ "minLength": 1
147
+ },
148
+ "guides": {
149
+ "default": [
150
+ "CLAUDE.md",
151
+ "AGENTS.md"
152
+ ],
153
+ "description": "Guide files the sibling publishes, copied into the cockpit's root AGENTS.md by sync.",
154
+ "type": "array",
155
+ "items": {
156
+ "type": "string",
157
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
158
+ }
159
+ },
160
+ "instruction_pointer": {
161
+ "default": false,
162
+ "description": "Let setup add a pointer to the cockpit guide in this sibling, when the command line also approves it.",
163
+ "type": "boolean"
164
+ },
165
+ "purpose": {
166
+ "type": "string",
167
+ "minLength": 1,
168
+ "description": "What the sibling is for; printed when its checkout is missing."
169
+ },
170
+ "environment_files": {
171
+ "description": "Template and instance environment file pairs the sibling needs.",
172
+ "type": "array",
173
+ "items": {
174
+ "type": "object",
175
+ "properties": {
176
+ "template": {
177
+ "type": "string",
178
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
179
+ "description": "Tracked template file the instance is created from."
180
+ },
181
+ "instance": {
182
+ "type": "string",
183
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
184
+ "description": "Machine-local file created from the template and left out of version control."
185
+ }
186
+ },
187
+ "required": [
188
+ "template",
189
+ "instance"
190
+ ],
191
+ "additionalProperties": false
192
+ }
193
+ },
194
+ "derives": {
195
+ "description": "Facts about the sibling that cockpit derives rows or MCP servers from.",
196
+ "type": "object",
197
+ "properties": {
198
+ "mcp_sources": {
199
+ "minItems": 1,
200
+ "maxItems": 256,
201
+ "type": "array",
202
+ "items": {
203
+ "type": "object",
204
+ "properties": {
205
+ "path": {
206
+ "type": "string",
207
+ "maxLength": 4096,
208
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
209
+ "description": "JSON file in the sibling with a top-level mcpServers object, as agent tools read from .mcp.json."
210
+ },
211
+ "provenance": {
212
+ "type": "object",
213
+ "properties": {
214
+ "source": {
215
+ "type": "string",
216
+ "maxLength": 4096,
217
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
218
+ "description": "File or place the value came from, relative to the repository."
219
+ },
220
+ "observed_on": {
221
+ "description": "Date the source was looked at; required unless kind is declared.",
222
+ "type": "string",
223
+ "format": "date",
224
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
225
+ },
226
+ "kind": {
227
+ "type": "string",
228
+ "enum": [
229
+ "declared",
230
+ "measured",
231
+ "inferred"
232
+ ],
233
+ "description": "How the value was established: declared by this file, measured, or inferred."
234
+ },
235
+ "reason": {
236
+ "type": "string",
237
+ "minLength": 1,
238
+ "maxLength": 4096,
239
+ "pattern": "\\S",
240
+ "description": "Why the value is what it is."
241
+ },
242
+ "confirmed": {
243
+ "description": "Set to true once a person has confirmed an inferred value; inferred values require it.",
244
+ "type": "boolean"
245
+ }
246
+ },
247
+ "required": [
248
+ "source",
249
+ "kind",
250
+ "reason"
251
+ ],
252
+ "additionalProperties": false,
253
+ "description": "Where this MCP source declaration came from.",
254
+ "anyOf": [
255
+ {
256
+ "properties": {
257
+ "kind": {
258
+ "enum": [
259
+ "declared"
260
+ ]
261
+ }
262
+ }
263
+ },
264
+ {
265
+ "properties": {
266
+ "kind": {
267
+ "enum": [
268
+ "measured"
269
+ ]
270
+ }
271
+ },
272
+ "required": [
273
+ "observed_on"
274
+ ]
275
+ },
276
+ {
277
+ "properties": {
278
+ "kind": {
279
+ "enum": [
280
+ "inferred"
281
+ ]
282
+ },
283
+ "confirmed": {
284
+ "enum": [
285
+ true
286
+ ]
287
+ }
288
+ },
289
+ "required": [
290
+ "confirmed",
291
+ "observed_on"
292
+ ]
293
+ }
294
+ ]
295
+ }
296
+ },
297
+ "required": [
298
+ "path",
299
+ "provenance"
300
+ ],
301
+ "additionalProperties": false
302
+ },
303
+ "description": "MCP server declaration files this sibling publishes."
304
+ }
305
+ },
306
+ "required": [
307
+ "mcp_sources"
308
+ ],
309
+ "additionalProperties": false
310
+ }
311
+ },
312
+ "required": [
313
+ "slug",
314
+ "dir",
315
+ "mount",
316
+ "acquire",
317
+ "var",
318
+ "purpose"
319
+ ],
320
+ "additionalProperties": false,
321
+ "allOf": [
322
+ {
323
+ "oneOf": [
324
+ {
325
+ "properties": {
326
+ "acquire": {
327
+ "enum": [
328
+ "none"
329
+ ]
330
+ }
331
+ },
332
+ "not": {
333
+ "required": [
334
+ "remote"
335
+ ]
336
+ }
337
+ },
338
+ {
339
+ "properties": {
340
+ "acquire": {
341
+ "enum": [
342
+ "auto",
343
+ "manual"
344
+ ]
345
+ }
346
+ },
347
+ "required": [
348
+ "remote"
349
+ ]
350
+ }
351
+ ]
352
+ },
353
+ {
354
+ "anyOf": [
355
+ {
356
+ "properties": {
357
+ "mount": {
358
+ "enum": [
359
+ "host"
360
+ ]
361
+ }
362
+ },
363
+ "required": [
364
+ "host_reason"
365
+ ]
366
+ },
367
+ {
368
+ "properties": {
369
+ "mount": {
370
+ "not": {
371
+ "enum": [
372
+ "host"
373
+ ]
374
+ }
375
+ }
376
+ }
377
+ }
378
+ ]
379
+ },
380
+ {
381
+ "anyOf": [
382
+ {
383
+ "properties": {
384
+ "gate": {
385
+ "enum": [
386
+ "operator"
387
+ ]
388
+ }
389
+ },
390
+ "required": [
391
+ "gate"
392
+ ]
393
+ },
394
+ {
395
+ "not": {
396
+ "anyOf": [
397
+ {
398
+ "properties": {
399
+ "mount": {
400
+ "enum": [
401
+ "host"
402
+ ]
403
+ }
404
+ }
405
+ },
406
+ {
407
+ "properties": {
408
+ "purpose": {
409
+ "pattern": "\\b(?:[lL][iI][vV][eE]|[pP][rR][oO][dD][uU][cC][tT][iI][oO][nN]|[hH][aA][rR][dD][wW][aA][rR][eE]|[sS][iI][mM][uU][lL][aA][tT][oO][rR])\\b"
410
+ }
411
+ }
412
+ }
413
+ ]
414
+ }
415
+ }
416
+ ]
417
+ }
418
+ ]
419
+ },
420
+ "description": "Product repositories the cockpit works across."
421
+ },
422
+ "ports": {
423
+ "type": "object",
424
+ "properties": {
425
+ "step": {
426
+ "default": 100,
427
+ "description": "Offset between consecutive stacks' published ports.",
428
+ "type": "integer",
429
+ "minimum": 0,
430
+ "exclusiveMinimum": true,
431
+ "maximum": 9007199254740991
432
+ },
433
+ "count": {
434
+ "default": 27,
435
+ "description": "Number of stacks that can run side by side.",
436
+ "type": "integer",
437
+ "minimum": 0,
438
+ "exclusiveMinimum": true,
439
+ "maximum": 9007199254740991
440
+ },
441
+ "bases": {
442
+ "type": "object",
443
+ "additionalProperties": false,
444
+ "description": "Base host port for each port variable; stack n publishes base plus n times step.",
445
+ "patternProperties": {
446
+ "^[A-Z][A-Z0-9_]*$": {
447
+ "type": "integer",
448
+ "minimum": 1,
449
+ "maximum": 65535
450
+ }
451
+ }
452
+ }
453
+ },
454
+ "required": [
455
+ "bases"
456
+ ],
457
+ "additionalProperties": false,
458
+ "description": "Port leasing for running stacks side by side."
459
+ },
460
+ "guards": {
461
+ "description": "Rules that restrict what agents may run.",
462
+ "default": {},
463
+ "type": "object",
464
+ "properties": {
465
+ "hosted_db_hosts": {
466
+ "default": [],
467
+ "description": "Hosted database host names the guards keep agents away from.",
468
+ "maxItems": 128,
469
+ "type": "array",
470
+ "items": {
471
+ "type": "string",
472
+ "pattern": "^(?:\\*\\.)?(?=[a-z0-9.-]{1,253}(?![\\s\\S]))[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*(?![\\s\\S])"
473
+ }
474
+ },
475
+ "vendor_endpoint_hosts": {
476
+ "default": [],
477
+ "description": "Real vendor endpoint host names the guards keep agents away from.",
478
+ "maxItems": 128,
479
+ "type": "array",
480
+ "items": {
481
+ "type": "string",
482
+ "pattern": "^(?:\\*\\.)?(?=[a-z0-9.-]{1,253}(?![\\s\\S]))[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*(?![\\s\\S])"
483
+ }
484
+ },
485
+ "protected_branches": {
486
+ "default": [
487
+ "main",
488
+ "master"
489
+ ],
490
+ "description": "Branches the guards keep agents from pushing to or rewriting.",
491
+ "type": "array",
492
+ "items": {
493
+ "type": "string"
494
+ }
495
+ },
496
+ "allow": {
497
+ "default": [],
498
+ "description": "Commands allowed in addition to the built-in rules.",
499
+ "maxItems": 64,
500
+ "type": "array",
501
+ "items": {
502
+ "type": "object",
503
+ "properties": {
504
+ "argv": {
505
+ "minItems": 1,
506
+ "maxItems": 32,
507
+ "type": "array",
508
+ "items": {
509
+ "type": "string",
510
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f\\uD800-\\uDFFF]{1,128}(?![\\s\\S])"
511
+ },
512
+ "description": "Command prefix, as an argument list, that is allowed."
513
+ },
514
+ "reason": {
515
+ "type": "string",
516
+ "minLength": 1,
517
+ "maxLength": 512,
518
+ "allOf": [
519
+ {
520
+ "type": "string",
521
+ "pattern": "\\S"
522
+ },
523
+ {
524
+ "type": "string",
525
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f]+$"
526
+ }
527
+ ],
528
+ "description": "Why the command is allowed."
529
+ },
530
+ "cwd": {
531
+ "description": "Allow only when run from this directory, relative to the cockpit.",
532
+ "anyOf": [
533
+ {
534
+ "type": "string",
535
+ "enum": [
536
+ "."
537
+ ]
538
+ },
539
+ {
540
+ "type": "string",
541
+ "maxLength": 4096,
542
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
543
+ }
544
+ ]
545
+ }
546
+ },
547
+ "required": [
548
+ "argv",
549
+ "reason"
550
+ ],
551
+ "additionalProperties": false
552
+ }
553
+ },
554
+ "deny": {
555
+ "default": [],
556
+ "description": "Commands refused in addition to the built-in rules.",
557
+ "maxItems": 64,
558
+ "type": "array",
559
+ "items": {
560
+ "anyOf": [
561
+ {
562
+ "type": "object",
563
+ "properties": {
564
+ "prefix": {
565
+ "minItems": 1,
566
+ "maxItems": 32,
567
+ "type": "array",
568
+ "items": {
569
+ "type": "string",
570
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f\\uD800-\\uDFFF]{1,128}(?![\\s\\S])"
571
+ },
572
+ "description": "Command prefix, as an argument list, that is refused."
573
+ },
574
+ "reason": {
575
+ "type": "string",
576
+ "minLength": 1,
577
+ "maxLength": 512,
578
+ "allOf": [
579
+ {
580
+ "type": "string",
581
+ "pattern": "\\S"
582
+ },
583
+ {
584
+ "type": "string",
585
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f]+$"
586
+ }
587
+ ],
588
+ "description": "Why the command is refused."
589
+ },
590
+ "fix": {
591
+ "description": "Safer command or step to suggest instead.",
592
+ "type": "string",
593
+ "minLength": 1,
594
+ "maxLength": 512,
595
+ "allOf": [
596
+ {
597
+ "type": "string",
598
+ "pattern": "\\S"
599
+ },
600
+ {
601
+ "type": "string",
602
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f]+$"
603
+ }
604
+ ]
605
+ }
606
+ },
607
+ "required": [
608
+ "prefix",
609
+ "reason"
610
+ ],
611
+ "additionalProperties": false
612
+ },
613
+ {
614
+ "type": "object",
615
+ "properties": {
616
+ "contains": {
617
+ "minItems": 1,
618
+ "maxItems": 32,
619
+ "type": "array",
620
+ "items": {
621
+ "type": "string",
622
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f\\uD800-\\uDFFF]{1,128}(?![\\s\\S])"
623
+ },
624
+ "description": "Argument sequence that is refused wherever it appears in a command."
625
+ },
626
+ "reason": {
627
+ "type": "string",
628
+ "minLength": 1,
629
+ "maxLength": 512,
630
+ "allOf": [
631
+ {
632
+ "type": "string",
633
+ "pattern": "\\S"
634
+ },
635
+ {
636
+ "type": "string",
637
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f]+$"
638
+ }
639
+ ],
640
+ "description": "Why the command is refused."
641
+ },
642
+ "fix": {
643
+ "description": "Safer command or step to suggest instead.",
644
+ "type": "string",
645
+ "minLength": 1,
646
+ "maxLength": 512,
647
+ "allOf": [
648
+ {
649
+ "type": "string",
650
+ "pattern": "\\S"
651
+ },
652
+ {
653
+ "type": "string",
654
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f]+$"
655
+ }
656
+ ]
657
+ }
658
+ },
659
+ "required": [
660
+ "contains",
661
+ "reason"
662
+ ],
663
+ "additionalProperties": false
664
+ }
665
+ ]
666
+ }
667
+ }
668
+ },
669
+ "additionalProperties": false
670
+ },
671
+ "mcp": {
672
+ "description": "Approval of MCP servers.",
673
+ "default": {},
674
+ "type": "object",
675
+ "properties": {
676
+ "approved": {
677
+ "default": {},
678
+ "description": "Approved MCP servers, each mapped to the sha256 of the declaration a person reviewed; others stay disabled.",
679
+ "type": "object",
680
+ "additionalProperties": false,
681
+ "patternProperties": {
682
+ "^(?=[\\s\\S]{0,128}$)(?:^[a-zA-Z0-9][a-zA-Z0-9_-]*$)": {
683
+ "type": "string",
684
+ "pattern": "^[a-f0-9]{64}$"
685
+ }
686
+ }
687
+ }
688
+ },
689
+ "additionalProperties": false
690
+ },
691
+ "work": {
692
+ "description": "How work orders are accepted, graded and closed.",
693
+ "default": {},
694
+ "type": "object",
695
+ "properties": {
696
+ "grading": {
697
+ "default": "independent",
698
+ "description": "How an order earns done: independent (an evaluator grades it), checks (cockpit ran every criterion's check and all passed) or self (the agent reports met or unmet with a note).",
699
+ "type": "string",
700
+ "enum": [
701
+ "independent",
702
+ "checks",
703
+ "self"
704
+ ]
705
+ },
706
+ "evaluators": {
707
+ "description": "Agent tools that run the independent grader for work grade and cockpit grade, tried in order: codexcli, claudecode, opencode. Defaults to the tools surfaces.tools lists that can evaluate, in that order, with the tool running the command moved last when it is detected (Claude Code or Codex), so another tool grades first. A list given here is used exactly as written.",
708
+ "minItems": 1,
709
+ "maxItems": 3,
710
+ "type": "array",
711
+ "items": {
712
+ "type": "string",
713
+ "enum": [
714
+ "codexcli",
715
+ "claudecode",
716
+ "opencode"
717
+ ]
718
+ }
719
+ },
720
+ "attempt_cap": {
721
+ "default": 2,
722
+ "description": "Failed checks or grades before an order is blocked; may be lowered but not raised.",
723
+ "type": "integer",
724
+ "minimum": 1,
725
+ "maximum": 2
726
+ },
727
+ "wip_cap": {
728
+ "default": 3,
729
+ "description": "Accepted orders that may be unfinished at once; may be lowered but not raised.",
730
+ "type": "integer",
731
+ "minimum": 1,
732
+ "maximum": 3
733
+ },
734
+ "verification_timeout_seconds": {
735
+ "default": 1800,
736
+ "description": "Seconds one criterion's check command may run before it is stopped and reported as not run.",
737
+ "type": "integer",
738
+ "minimum": 1,
739
+ "maximum": 7200
740
+ },
741
+ "evaluator_timeout_seconds": {
742
+ "default": 900,
743
+ "description": "Seconds one independent grading run may take before it is stopped.",
744
+ "type": "integer",
745
+ "minimum": 1,
746
+ "maximum": 7200
747
+ },
748
+ "gates": {
749
+ "description": "Who passes each work-order decision.",
750
+ "default": {},
751
+ "type": "object",
752
+ "properties": {
753
+ "accept": {
754
+ "description": "Who accepts a draft work order: agent, person or ci. Default agent.",
755
+ "type": "string",
756
+ "enum": [
757
+ "agent",
758
+ "person",
759
+ "ci"
760
+ ]
761
+ },
762
+ "amend": {
763
+ "description": "Who accepts a changed contract. Default agent. Removing or rewriting an accepted criterion always needs a person or ci.",
764
+ "type": "string",
765
+ "enum": [
766
+ "agent",
767
+ "person",
768
+ "ci"
769
+ ]
770
+ },
771
+ "answer": {
772
+ "description": "Who answers an open question on an order. Default agent.",
773
+ "type": "string",
774
+ "enum": [
775
+ "agent",
776
+ "person",
777
+ "ci"
778
+ ]
779
+ },
780
+ "signoff": {
781
+ "description": "Who closes a graded order. Default agent.",
782
+ "type": "string",
783
+ "enum": [
784
+ "agent",
785
+ "person",
786
+ "ci"
787
+ ]
788
+ }
789
+ },
790
+ "additionalProperties": false
791
+ }
792
+ },
793
+ "additionalProperties": false
794
+ },
795
+ "autonomy": {
796
+ "description": "Which decisions an agent may take without a person.",
797
+ "default": {},
798
+ "type": "object",
799
+ "properties": {
800
+ "sync": {
801
+ "description": "Who may run a sync that writes: agent, person or ci. Default agent.",
802
+ "type": "string",
803
+ "enum": [
804
+ "agent",
805
+ "person",
806
+ "ci"
807
+ ]
808
+ },
809
+ "stale_delete": {
810
+ "description": "Who approves sync deleting files cockpit generated before and no longer generates. Default agent.",
811
+ "type": "string",
812
+ "enum": [
813
+ "agent",
814
+ "person",
815
+ "ci"
816
+ ]
817
+ },
818
+ "reset": {
819
+ "description": "Who may apply a reset, which deletes stack data. Default person.",
820
+ "type": "string",
821
+ "enum": [
822
+ "agent",
823
+ "person",
824
+ "ci"
825
+ ]
826
+ },
827
+ "mcp_approve": {
828
+ "description": "Who approves a declared MCP server: person records each digest in [mcp.approved]; agent lets sync enable every declared server as declared, so an agent that writes a sibling MCP source starts that process outside the guard. Default person.",
829
+ "type": "string",
830
+ "enum": [
831
+ "agent",
832
+ "person"
833
+ ]
834
+ }
835
+ },
836
+ "additionalProperties": false
837
+ },
838
+ "browser": {
839
+ "description": "Browser automation for the stack.",
840
+ "type": "object",
841
+ "properties": {
842
+ "engine": {
843
+ "default": "chromium",
844
+ "description": "Browser engine to drive.",
845
+ "type": "string",
846
+ "enum": [
847
+ "chromium",
848
+ "firefox",
849
+ "webkit"
850
+ ]
851
+ },
852
+ "network_exposure": {
853
+ "default": "<loopback>",
854
+ "description": "Network rules the browser may reach beyond loopback; the default is loopback only.",
855
+ "type": "string",
856
+ "minLength": 1,
857
+ "maxLength": 512,
858
+ "pattern": "^[a-z0-9.*:<>\\[\\],-]+$"
859
+ },
860
+ "network_exposure_reason": {
861
+ "description": "Why the browser needs wider network access; required when network_exposure is wider than loopback.",
862
+ "type": "string",
863
+ "minLength": 1,
864
+ "maxLength": 512
865
+ },
866
+ "harnesses": {
867
+ "minItems": 1,
868
+ "maxItems": 3,
869
+ "type": "array",
870
+ "items": {
871
+ "type": "object",
872
+ "properties": {
873
+ "target": {
874
+ "type": "string",
875
+ "enum": [
876
+ "claudecode",
877
+ "codexcli",
878
+ "opencode"
879
+ ],
880
+ "description": "Agent tool the browser is wired to."
881
+ },
882
+ "version": {
883
+ "type": "string",
884
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
885
+ "description": "Version of the agent tool the wiring was checked against."
886
+ }
887
+ },
888
+ "required": [
889
+ "target",
890
+ "version"
891
+ ],
892
+ "additionalProperties": false
893
+ },
894
+ "description": "Agent tools, with versions, that are wired to the browser.",
895
+ "uniqueItems": true
896
+ },
897
+ "images": {
898
+ "type": "object",
899
+ "properties": {
900
+ "mcp": {
901
+ "type": "object",
902
+ "properties": {
903
+ "reference": {
904
+ "type": "string",
905
+ "pattern": "^[a-z0-9][a-z0-9./:_-]*@sha256:[a-f0-9]{64}$",
906
+ "description": "Image reference pinned by sha256 digest."
907
+ },
908
+ "driver_version": {
909
+ "type": "string",
910
+ "maxLength": 128,
911
+ "pattern": "^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*)?$",
912
+ "description": "Playwright driver version the image carries."
913
+ }
914
+ },
915
+ "required": [
916
+ "reference",
917
+ "driver_version"
918
+ ],
919
+ "additionalProperties": false,
920
+ "description": "Image that serves the browser MCP server."
921
+ }
922
+ },
923
+ "required": [
924
+ "mcp"
925
+ ],
926
+ "additionalProperties": false,
927
+ "description": "Pinned container images for the browser."
928
+ },
929
+ "project": {
930
+ "type": "object",
931
+ "properties": {
932
+ "manifest": {
933
+ "description": "package.json for the project; omit to use the one beside the lockfile.",
934
+ "type": "string",
935
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
936
+ },
937
+ "manifest_sha256": {
938
+ "description": "SHA-256 of the manifest; required when manifest is set.",
939
+ "type": "string",
940
+ "pattern": "^[a-f0-9]{64}$"
941
+ },
942
+ "lockfile": {
943
+ "type": "string",
944
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
945
+ "description": "Lockfile that pins the Playwright driver the browser commands load."
946
+ },
947
+ "sha256": {
948
+ "type": "string",
949
+ "pattern": "^[a-f0-9]{64}$",
950
+ "description": "SHA-256 of the lockfile."
951
+ },
952
+ "driver_version": {
953
+ "type": "string",
954
+ "maxLength": 128,
955
+ "pattern": "^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*)?$",
956
+ "description": "Playwright driver version the lockfile pins."
957
+ }
958
+ },
959
+ "required": [
960
+ "lockfile",
961
+ "sha256",
962
+ "driver_version"
963
+ ],
964
+ "additionalProperties": false,
965
+ "description": "Node project the browser commands load their Playwright driver from."
966
+ },
967
+ "endpoint": {
968
+ "description": "WebSocket address of the browser server, using an allowed loopback host.",
969
+ "type": "string",
970
+ "format": "uri"
971
+ },
972
+ "max_clients": {
973
+ "type": "integer",
974
+ "minimum": 1,
975
+ "maximum": 64,
976
+ "description": "Most browser clients that may connect at once."
977
+ },
978
+ "proxy": {
979
+ "type": "object",
980
+ "properties": {
981
+ "host_variable": {
982
+ "description": "Port variable in [ports.bases] that leases the proxy port.",
983
+ "type": "string",
984
+ "maxLength": 128,
985
+ "pattern": "^[A-Z][A-Z0-9_]*$"
986
+ },
987
+ "server_port": {
988
+ "type": "integer",
989
+ "minimum": 1,
990
+ "maximum": 65535,
991
+ "description": "Port the browser server listens on."
992
+ },
993
+ "proxy_port": {
994
+ "type": "integer",
995
+ "minimum": 1,
996
+ "maximum": 65535,
997
+ "description": "Port the proxy listens on; differs from server_port."
998
+ },
999
+ "allowed_hosts": {
1000
+ "minItems": 1,
1001
+ "maxItems": 64,
1002
+ "type": "array",
1003
+ "items": {
1004
+ "type": "string",
1005
+ "minLength": 1,
1006
+ "maxLength": 260
1007
+ },
1008
+ "description": "Host and port pairs the proxy allows.",
1009
+ "uniqueItems": true
1010
+ },
1011
+ "bind": {
1012
+ "default": "127.0.0.1",
1013
+ "description": "Loopback address the proxy binds to.",
1014
+ "type": "string",
1015
+ "enum": [
1016
+ "127.0.0.1",
1017
+ "::1"
1018
+ ]
1019
+ }
1020
+ },
1021
+ "required": [
1022
+ "server_port",
1023
+ "proxy_port",
1024
+ "allowed_hosts"
1025
+ ],
1026
+ "additionalProperties": false,
1027
+ "description": "Proxy the browser reaches the application through."
1028
+ },
1029
+ "resolver": {
1030
+ "default": [],
1031
+ "description": "Fixed host name to address mappings the browser uses.",
1032
+ "maxItems": 64,
1033
+ "type": "array",
1034
+ "items": {
1035
+ "type": "object",
1036
+ "properties": {
1037
+ "hostname": {
1038
+ "type": "string",
1039
+ "pattern": "^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z][a-z0-9-]*$",
1040
+ "description": "Host name to resolve."
1041
+ },
1042
+ "address": {
1043
+ "anyOf": [
1044
+ {
1045
+ "type": "string",
1046
+ "format": "ipv4",
1047
+ "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"
1048
+ },
1049
+ {
1050
+ "type": "string",
1051
+ "format": "ipv6",
1052
+ "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$"
1053
+ }
1054
+ ],
1055
+ "description": "Address the host name resolves to."
1056
+ }
1057
+ },
1058
+ "required": [
1059
+ "hostname",
1060
+ "address"
1061
+ ],
1062
+ "additionalProperties": false
1063
+ }
1064
+ },
1065
+ "authentication": {
1066
+ "type": "object",
1067
+ "properties": {
1068
+ "policy": {
1069
+ "type": "string",
1070
+ "enum": [
1071
+ "none",
1072
+ "serialized",
1073
+ "per-worker"
1074
+ ],
1075
+ "description": "Whether sessions share no sign-in, take turns on one, or each keep their own."
1076
+ },
1077
+ "states": {
1078
+ "default": [],
1079
+ "description": "Saved sign-in states, one per worker.",
1080
+ "maxItems": 64,
1081
+ "type": "array",
1082
+ "items": {
1083
+ "type": "object",
1084
+ "properties": {
1085
+ "worker": {
1086
+ "type": "string",
1087
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,63}$",
1088
+ "description": "Name of the worker the state belongs to."
1089
+ },
1090
+ "path": {
1091
+ "type": "string",
1092
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
1093
+ "description": "Saved sign-in state file under the auth artifact root."
1094
+ }
1095
+ },
1096
+ "required": [
1097
+ "worker",
1098
+ "path"
1099
+ ],
1100
+ "additionalProperties": false
1101
+ }
1102
+ }
1103
+ },
1104
+ "required": [
1105
+ "policy"
1106
+ ],
1107
+ "additionalProperties": false,
1108
+ "description": "How browser sessions sign in to the application."
1109
+ },
1110
+ "data": {
1111
+ "type": "object",
1112
+ "properties": {
1113
+ "mode": {
1114
+ "type": "string",
1115
+ "enum": [
1116
+ "empty",
1117
+ "seeded",
1118
+ "restored"
1119
+ ],
1120
+ "description": "What the data is: empty, seeded by the product, or restored from real data."
1121
+ },
1122
+ "isolated": {
1123
+ "type": "boolean",
1124
+ "description": "True when the data is separate from anyone else's."
1125
+ },
1126
+ "reaches_production": {
1127
+ "type": "boolean",
1128
+ "description": "True when browser actions can affect production."
1129
+ }
1130
+ },
1131
+ "required": [
1132
+ "mode",
1133
+ "isolated",
1134
+ "reaches_production"
1135
+ ],
1136
+ "additionalProperties": false,
1137
+ "description": "Statement about the data the browser touches; cockpit cannot observe it."
1138
+ },
1139
+ "request_preapproval": {
1140
+ "default": false,
1141
+ "description": "Run browser tools without prompts; allowed only on isolated, non-production, non-restored data.",
1142
+ "type": "boolean"
1143
+ },
1144
+ "artifacts": {
1145
+ "type": "object",
1146
+ "properties": {
1147
+ "mcp": {
1148
+ "type": "string",
1149
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
1150
+ "description": "Generated host path for the browser MCP server's files."
1151
+ },
1152
+ "cli": {
1153
+ "type": "string",
1154
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
1155
+ "description": "Generated host path for command-line browser output."
1156
+ },
1157
+ "auth": {
1158
+ "type": "string",
1159
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
1160
+ "description": "Generated host path for saved sign-in state."
1161
+ }
1162
+ },
1163
+ "required": [
1164
+ "mcp",
1165
+ "cli",
1166
+ "auth"
1167
+ ],
1168
+ "additionalProperties": false,
1169
+ "description": "Generated host paths for browser output."
1170
+ }
1171
+ },
1172
+ "required": [
1173
+ "harnesses",
1174
+ "images",
1175
+ "project",
1176
+ "max_clients",
1177
+ "proxy",
1178
+ "authentication",
1179
+ "data",
1180
+ "artifacts"
1181
+ ],
1182
+ "additionalProperties": false,
1183
+ "anyOf": [
1184
+ {
1185
+ "properties": {
1186
+ "request_preapproval": {
1187
+ "enum": [
1188
+ false
1189
+ ]
1190
+ }
1191
+ }
1192
+ },
1193
+ {
1194
+ "properties": {
1195
+ "data": {
1196
+ "required": [
1197
+ "mode",
1198
+ "isolated",
1199
+ "reaches_production"
1200
+ ],
1201
+ "properties": {
1202
+ "mode": {
1203
+ "enum": [
1204
+ "empty",
1205
+ "seeded"
1206
+ ]
1207
+ },
1208
+ "isolated": {
1209
+ "enum": [
1210
+ true
1211
+ ]
1212
+ },
1213
+ "reaches_production": {
1214
+ "enum": [
1215
+ false
1216
+ ]
1217
+ }
1218
+ }
1219
+ }
1220
+ }
1221
+ }
1222
+ ]
1223
+ },
1224
+ "testing": {
1225
+ "description": "Test stages and gates.",
1226
+ "type": "object",
1227
+ "properties": {
1228
+ "stages": {
1229
+ "minItems": 1,
1230
+ "maxItems": 128,
1231
+ "type": "array",
1232
+ "items": {
1233
+ "type": "object",
1234
+ "properties": {
1235
+ "id": {
1236
+ "type": "string",
1237
+ "pattern": "^[a-z][a-z0-9-]{0,63}$",
1238
+ "description": "Name of the stage."
1239
+ },
1240
+ "command": {
1241
+ "minItems": 1,
1242
+ "maxItems": 128,
1243
+ "type": "array",
1244
+ "items": {
1245
+ "type": "string",
1246
+ "minLength": 1,
1247
+ "maxLength": 4096
1248
+ },
1249
+ "description": "Command to run, as an argument list."
1250
+ },
1251
+ "requires_stack": {
1252
+ "type": "boolean",
1253
+ "description": "True when the stage needs the stack running."
1254
+ },
1255
+ "timeout_seconds": {
1256
+ "default": 1800,
1257
+ "description": "Seconds the stage may run before it is stopped and the gate reports DEGRADED.",
1258
+ "type": "integer",
1259
+ "minimum": 1,
1260
+ "maximum": 7200
1261
+ },
1262
+ "select": {
1263
+ "description": "Arguments appended to the command when test-run --select names that kind; {value} becomes the selected value.",
1264
+ "type": "object",
1265
+ "properties": {
1266
+ "spec": {
1267
+ "description": "Arguments that select tests by spec; {value} becomes the selection.",
1268
+ "minItems": 1,
1269
+ "maxItems": 32,
1270
+ "type": "array",
1271
+ "items": {
1272
+ "type": "string",
1273
+ "minLength": 1,
1274
+ "maxLength": 4096
1275
+ }
1276
+ },
1277
+ "file": {
1278
+ "description": "Arguments that select tests by file; {value} becomes the selection.",
1279
+ "minItems": 1,
1280
+ "maxItems": 32,
1281
+ "type": "array",
1282
+ "items": {
1283
+ "type": "string",
1284
+ "minLength": 1,
1285
+ "maxLength": 4096
1286
+ }
1287
+ },
1288
+ "test": {
1289
+ "description": "Arguments that select tests by test name; {value} becomes the selection.",
1290
+ "minItems": 1,
1291
+ "maxItems": 32,
1292
+ "type": "array",
1293
+ "items": {
1294
+ "type": "string",
1295
+ "minLength": 1,
1296
+ "maxLength": 4096
1297
+ }
1298
+ },
1299
+ "route": {
1300
+ "description": "Arguments that select tests by route; {value} becomes the selection.",
1301
+ "minItems": 1,
1302
+ "maxItems": 32,
1303
+ "type": "array",
1304
+ "items": {
1305
+ "type": "string",
1306
+ "minLength": 1,
1307
+ "maxLength": 4096
1308
+ }
1309
+ }
1310
+ },
1311
+ "additionalProperties": false
1312
+ }
1313
+ },
1314
+ "required": [
1315
+ "id",
1316
+ "command",
1317
+ "requires_stack"
1318
+ ],
1319
+ "additionalProperties": false
1320
+ },
1321
+ "description": "Commands that make up the test gates."
1322
+ },
1323
+ "gates": {
1324
+ "minItems": 1,
1325
+ "maxItems": 128,
1326
+ "type": "array",
1327
+ "items": {
1328
+ "type": "object",
1329
+ "properties": {
1330
+ "id": {
1331
+ "type": "string",
1332
+ "pattern": "^[a-z][a-z0-9-]{0,63}$",
1333
+ "description": "Name of the gate."
1334
+ },
1335
+ "tier": {
1336
+ "type": "string",
1337
+ "enum": [
1338
+ "targeted",
1339
+ "full"
1340
+ ],
1341
+ "description": "Whether the gate covers targeted changes or the full suite."
1342
+ },
1343
+ "stages": {
1344
+ "minItems": 1,
1345
+ "maxItems": 128,
1346
+ "type": "array",
1347
+ "items": {
1348
+ "type": "string",
1349
+ "pattern": "^[a-z][a-z0-9-]{0,63}$"
1350
+ },
1351
+ "description": "Stages the gate runs, by id."
1352
+ },
1353
+ "changes": {
1354
+ "type": "string",
1355
+ "minLength": 1,
1356
+ "maxLength": 4096,
1357
+ "description": "Kind of change that calls for this gate."
1358
+ }
1359
+ },
1360
+ "required": [
1361
+ "id",
1362
+ "tier",
1363
+ "stages",
1364
+ "changes"
1365
+ ],
1366
+ "additionalProperties": false
1367
+ },
1368
+ "description": "Named gates that run stages before handing back changes."
1369
+ },
1370
+ "native_hooks": {
1371
+ "default": {
1372
+ "install": "inspect"
1373
+ },
1374
+ "description": "How the repository's own git hooks are handled.",
1375
+ "type": "object",
1376
+ "properties": {
1377
+ "install": {
1378
+ "default": "inspect",
1379
+ "description": "Inspect the repository's hooks, or install them as the policy file declares.",
1380
+ "type": "string",
1381
+ "enum": [
1382
+ "inspect",
1383
+ "explicit-native"
1384
+ ]
1385
+ }
1386
+ },
1387
+ "additionalProperties": false
1388
+ },
1389
+ "native_hook_policy": {
1390
+ "description": "Policy file for installing the repository's hooks; required for explicit-native.",
1391
+ "type": "object",
1392
+ "properties": {
1393
+ "path": {
1394
+ "type": "string",
1395
+ "maxLength": 4096,
1396
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
1397
+ "description": "Policy file, relative to the cockpit."
1398
+ },
1399
+ "sha256": {
1400
+ "type": "string",
1401
+ "pattern": "^[a-f0-9]{64}$",
1402
+ "description": "SHA-256 of the policy file."
1403
+ }
1404
+ },
1405
+ "required": [
1406
+ "path",
1407
+ "sha256"
1408
+ ],
1409
+ "additionalProperties": false
1410
+ }
1411
+ },
1412
+ "required": [
1413
+ "stages",
1414
+ "gates"
1415
+ ],
1416
+ "additionalProperties": false,
1417
+ "oneOf": [
1418
+ {
1419
+ "properties": {
1420
+ "native_hooks": {
1421
+ "properties": {
1422
+ "install": {
1423
+ "enum": [
1424
+ "inspect"
1425
+ ]
1426
+ }
1427
+ }
1428
+ }
1429
+ },
1430
+ "not": {
1431
+ "required": [
1432
+ "native_hook_policy"
1433
+ ]
1434
+ }
1435
+ },
1436
+ {
1437
+ "properties": {
1438
+ "native_hooks": {
1439
+ "properties": {
1440
+ "install": {
1441
+ "enum": [
1442
+ "explicit-native"
1443
+ ]
1444
+ }
1445
+ },
1446
+ "required": [
1447
+ "install"
1448
+ ]
1449
+ }
1450
+ },
1451
+ "required": [
1452
+ "native_hooks",
1453
+ "native_hook_policy"
1454
+ ]
1455
+ }
1456
+ ]
1457
+ },
1458
+ "environment": {
1459
+ "description": "How the stack is reached, signed in to, built and kept.",
1460
+ "default": {},
1461
+ "type": "object",
1462
+ "properties": {
1463
+ "addressing": {
1464
+ "description": "How the product is reached locally: by host name or by leased port.",
1465
+ "type": "string",
1466
+ "enum": [
1467
+ "hostname",
1468
+ "port"
1469
+ ]
1470
+ },
1471
+ "authentication": {
1472
+ "description": "How the product signs in locally: real sign-in, bypassed, or none.",
1473
+ "type": "string",
1474
+ "enum": [
1475
+ "real",
1476
+ "bypassed",
1477
+ "none"
1478
+ ]
1479
+ },
1480
+ "posture_requirements": {
1481
+ "description": "Posture facts the product relies on, each tagged with the posture it depends on.",
1482
+ "minItems": 1,
1483
+ "maxItems": 128,
1484
+ "type": "array",
1485
+ "items": {
1486
+ "type": "object",
1487
+ "properties": {
1488
+ "requirement": {
1489
+ "type": "string",
1490
+ "minLength": 1,
1491
+ "maxLength": 64,
1492
+ "pattern": "^[a-z][a-z0-9-]*$",
1493
+ "description": "Name of the posture requirement the product relies on."
1494
+ },
1495
+ "addressing": {
1496
+ "description": "Addressing posture this requirement depends on; set at least one of addressing and authentication.",
1497
+ "type": "string",
1498
+ "enum": [
1499
+ "hostname",
1500
+ "port"
1501
+ ]
1502
+ },
1503
+ "authentication": {
1504
+ "description": "Authentication posture this requirement depends on; set at least one of addressing and authentication.",
1505
+ "type": "string",
1506
+ "enum": [
1507
+ "real",
1508
+ "bypassed",
1509
+ "none"
1510
+ ]
1511
+ }
1512
+ },
1513
+ "required": [
1514
+ "requirement"
1515
+ ],
1516
+ "additionalProperties": false,
1517
+ "anyOf": [
1518
+ {
1519
+ "required": [
1520
+ "addressing"
1521
+ ]
1522
+ },
1523
+ {
1524
+ "required": [
1525
+ "authentication"
1526
+ ]
1527
+ }
1528
+ ]
1529
+ }
1530
+ },
1531
+ "machine": {
1532
+ "description": "Least the container runtime must offer before the stack starts.",
1533
+ "type": "object",
1534
+ "properties": {
1535
+ "runtime_memory_mb": {
1536
+ "type": "integer",
1537
+ "minimum": 0,
1538
+ "exclusiveMinimum": true,
1539
+ "maximum": 9007199254740991,
1540
+ "description": "Least memory in megabytes the container runtime must offer before the stack starts."
1541
+ },
1542
+ "runtime_cpus": {
1543
+ "type": "number",
1544
+ "minimum": 0,
1545
+ "exclusiveMinimum": true,
1546
+ "description": "Least number of CPUs the container runtime must offer before the stack starts."
1547
+ },
1548
+ "free_disk_mb": {
1549
+ "type": "integer",
1550
+ "minimum": 0,
1551
+ "exclusiveMinimum": true,
1552
+ "maximum": 9007199254740991,
1553
+ "description": "Least free disk space in megabytes the stack needs before it starts."
1554
+ },
1555
+ "cold_start_seconds": {
1556
+ "type": "integer",
1557
+ "minimum": 0,
1558
+ "exclusiveMinimum": true,
1559
+ "maximum": 3600,
1560
+ "description": "Seconds a first start may take; start fails and reports unhealthy beyond it. At most one hour."
1561
+ }
1562
+ },
1563
+ "required": [
1564
+ "runtime_memory_mb",
1565
+ "runtime_cpus",
1566
+ "free_disk_mb",
1567
+ "cold_start_seconds"
1568
+ ],
1569
+ "additionalProperties": false
1570
+ },
1571
+ "resettable_volumes": {
1572
+ "default": [],
1573
+ "description": "Compose volumes that reset may delete and recreate, named by their Compose key.",
1574
+ "type": "array",
1575
+ "items": {
1576
+ "type": "string",
1577
+ "pattern": "^[a-z0-9][a-z0-9_.-]*$"
1578
+ },
1579
+ "uniqueItems": true
1580
+ },
1581
+ "generated_host_paths": {
1582
+ "default": [],
1583
+ "description": "Host paths cockpit generates and owns, relative to the cockpit.",
1584
+ "type": "array",
1585
+ "items": {
1586
+ "type": "string",
1587
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
1588
+ },
1589
+ "uniqueItems": true
1590
+ },
1591
+ "compose_files": {
1592
+ "default": [],
1593
+ "description": "Compose files, relative to the cockpit, that make up the stack; cockpit runs them as written.",
1594
+ "type": "array",
1595
+ "items": {
1596
+ "type": "string",
1597
+ "allOf": [
1598
+ {
1599
+ "type": "string",
1600
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
1601
+ },
1602
+ {
1603
+ "type": "string",
1604
+ "pattern": "^[^:]+$"
1605
+ }
1606
+ ]
1607
+ },
1608
+ "uniqueItems": true
1609
+ },
1610
+ "entrypoint_derivatives": {
1611
+ "default": [],
1612
+ "description": "Addresses derived from leased ports, such as application origins and callback URLs.",
1613
+ "type": "array",
1614
+ "items": {
1615
+ "type": "object",
1616
+ "properties": {
1617
+ "name": {
1618
+ "type": "string",
1619
+ "pattern": "^[a-z0-9][a-z0-9-]*$",
1620
+ "description": "Name that identifies this entrypoint in command output."
1621
+ },
1622
+ "kind": {
1623
+ "type": "string",
1624
+ "enum": [
1625
+ "entrypoint",
1626
+ "origin",
1627
+ "callback_url",
1628
+ "advertised_listener",
1629
+ "cors_origin",
1630
+ "public_base_url"
1631
+ ],
1632
+ "description": "What the address is used for, such as an application origin or a callback URL."
1633
+ },
1634
+ "port": {
1635
+ "type": "string",
1636
+ "pattern": "^[A-Z][A-Z0-9_]*$",
1637
+ "description": "Port-base variable from [ports.bases] whose leased port this address uses."
1638
+ },
1639
+ "path": {
1640
+ "type": "string",
1641
+ "pattern": "^\\/(?!\\/)(?!\\.{1,2}(?:\\/|$))(?!.*\\/\\.{1,2}(?:\\/|$))(?!.*[%\\\\?#\\x00-\\x20\\x7f]).*$",
1642
+ "description": "Absolute URL path appended to the origin."
1643
+ },
1644
+ "hostname": {
1645
+ "description": "Named local URL host, a subdomain of .localhost; omit to use 127.0.0.1.",
1646
+ "type": "string",
1647
+ "maxLength": 253,
1648
+ "pattern": "^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+localhost(?![\\s\\S])"
1649
+ },
1650
+ "scheme": {
1651
+ "description": "URL scheme, http or https; omit to use http.",
1652
+ "type": "string",
1653
+ "enum": [
1654
+ "http",
1655
+ "https"
1656
+ ]
1657
+ }
1658
+ },
1659
+ "required": [
1660
+ "name",
1661
+ "kind",
1662
+ "port",
1663
+ "path"
1664
+ ],
1665
+ "additionalProperties": false
1666
+ }
1667
+ },
1668
+ "install_policies": {
1669
+ "default": [],
1670
+ "description": "The build and test commands the guard admits for each toolchain and lockfile.",
1671
+ "type": "array",
1672
+ "items": {
1673
+ "type": "object",
1674
+ "properties": {
1675
+ "toolchain": {
1676
+ "type": "string",
1677
+ "enum": [
1678
+ "node",
1679
+ "python",
1680
+ "ruby",
1681
+ "go",
1682
+ "rust",
1683
+ "dotnet"
1684
+ ],
1685
+ "description": "Toolchain of the siblings this policy applies to."
1686
+ },
1687
+ "lockfile": {
1688
+ "type": "string",
1689
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
1690
+ "description": "Lockfile, relative to the sibling, that selects this policy."
1691
+ },
1692
+ "build": {
1693
+ "description": "Build command, as an argument list, when the product owns one.",
1694
+ "minItems": 1,
1695
+ "maxItems": 32,
1696
+ "type": "array",
1697
+ "items": {
1698
+ "type": "string",
1699
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f\\uD800-\\uDFFF]{1,128}(?![\\s\\S])"
1700
+ }
1701
+ },
1702
+ "test": {
1703
+ "description": "Test command, as an argument list, when the product owns one.",
1704
+ "minItems": 1,
1705
+ "maxItems": 32,
1706
+ "type": "array",
1707
+ "items": {
1708
+ "type": "string",
1709
+ "pattern": "^[^\\x00-\\x1f\\x7f-\\x9f\\uD800-\\uDFFF]{1,128}(?![\\s\\S])"
1710
+ }
1711
+ }
1712
+ },
1713
+ "required": [
1714
+ "toolchain",
1715
+ "lockfile"
1716
+ ],
1717
+ "additionalProperties": false
1718
+ }
1719
+ },
1720
+ "seed": {
1721
+ "description": "Command up runs once the stack is healthy, whenever a resettable volume was created since the last successful seed.",
1722
+ "type": "object",
1723
+ "properties": {
1724
+ "argv": {
1725
+ "minItems": 1,
1726
+ "maxItems": 256,
1727
+ "type": "array",
1728
+ "items": {
1729
+ "type": "string",
1730
+ "minLength": 1
1731
+ },
1732
+ "description": "Command, as an argument list, that fills the resettable volumes; it runs on the host in the cockpit directory with the leased ports in its environment."
1733
+ },
1734
+ "timeout_seconds": {
1735
+ "type": "integer",
1736
+ "minimum": 1,
1737
+ "maximum": 3600,
1738
+ "description": "Seconds the seed may run before it is stopped."
1739
+ }
1740
+ },
1741
+ "required": [
1742
+ "argv",
1743
+ "timeout_seconds"
1744
+ ],
1745
+ "additionalProperties": false
1746
+ }
1747
+ },
1748
+ "additionalProperties": false
1749
+ },
1750
+ "surfaces": {
1751
+ "description": "Instructions, skills and settings generated for agent tools.",
1752
+ "default": {},
1753
+ "type": "object",
1754
+ "properties": {
1755
+ "tools": {
1756
+ "default": [
1757
+ "claudecode",
1758
+ "codexcli",
1759
+ "opencode"
1760
+ ],
1761
+ "description": "Agent tools whose instructions, skills and settings sync writes and check compares. Defaults to the tools whose guard is measured (claudecode, codexcli, opencode); the other shipped targets are written only when listed.",
1762
+ "minItems": 1,
1763
+ "maxItems": 5,
1764
+ "type": "array",
1765
+ "items": {
1766
+ "type": "string",
1767
+ "enum": [
1768
+ "claudecode",
1769
+ "codexcli",
1770
+ "opencode",
1771
+ "cursor",
1772
+ "grokcli"
1773
+ ]
1774
+ }
1775
+ },
1776
+ "overlays": {
1777
+ "default": [],
1778
+ "description": "Team-owned rules, subagents, skills and hooks added to the generated surfaces.",
1779
+ "maxItems": 256,
1780
+ "type": "array",
1781
+ "items": {
1782
+ "type": "object",
1783
+ "properties": {
1784
+ "name": {
1785
+ "type": "string",
1786
+ "maxLength": 128,
1787
+ "pattern": "^[a-z0-9][a-z0-9-]*$",
1788
+ "description": "Name of the declaration; an overlay that reuses a core name replaces it."
1789
+ },
1790
+ "feature": {
1791
+ "type": "string",
1792
+ "enum": [
1793
+ "rules",
1794
+ "subagents",
1795
+ "skills",
1796
+ "hooks"
1797
+ ],
1798
+ "description": "Kind of surface the overlay provides."
1799
+ },
1800
+ "sources": {
1801
+ "minItems": 1,
1802
+ "maxItems": 256,
1803
+ "type": "array",
1804
+ "items": {
1805
+ "type": "object",
1806
+ "properties": {
1807
+ "path": {
1808
+ "allOf": [
1809
+ {
1810
+ "type": "string",
1811
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
1812
+ },
1813
+ {
1814
+ "type": "string",
1815
+ "maxLength": 4096,
1816
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
1817
+ }
1818
+ ],
1819
+ "description": "Path of the source file."
1820
+ },
1821
+ "bytes": {
1822
+ "type": "string",
1823
+ "maxLength": 65536,
1824
+ "description": "Full text of the source."
1825
+ }
1826
+ },
1827
+ "required": [
1828
+ "path",
1829
+ "bytes"
1830
+ ],
1831
+ "additionalProperties": false
1832
+ },
1833
+ "description": "Files that make up the declaration."
1834
+ },
1835
+ "source": {
1836
+ "allOf": [
1837
+ {
1838
+ "type": "string",
1839
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
1840
+ },
1841
+ {
1842
+ "type": "string",
1843
+ "maxLength": 4096,
1844
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
1845
+ }
1846
+ ],
1847
+ "description": "Where the declaration was read from."
1848
+ },
1849
+ "replaces": {
1850
+ "description": "Core declaration this overlay replaces; required when the name matches a core one.",
1851
+ "type": "object",
1852
+ "properties": {
1853
+ "name": {
1854
+ "type": "string",
1855
+ "maxLength": 128,
1856
+ "pattern": "^[a-z0-9][a-z0-9-]*$",
1857
+ "description": "Name of the core declaration being replaced."
1858
+ },
1859
+ "sha256": {
1860
+ "type": "string",
1861
+ "pattern": "^[a-f0-9]{64}$",
1862
+ "description": "SHA-256 of the original core declaration, recorded so a later change to it is reported."
1863
+ }
1864
+ },
1865
+ "required": [
1866
+ "name",
1867
+ "sha256"
1868
+ ],
1869
+ "additionalProperties": false
1870
+ }
1871
+ },
1872
+ "required": [
1873
+ "name",
1874
+ "feature",
1875
+ "sources",
1876
+ "source"
1877
+ ],
1878
+ "additionalProperties": false
1879
+ }
1880
+ },
1881
+ "harnesses": {
1882
+ "default": [],
1883
+ "description": "Agent tools beyond the shipped ones, with measured capabilities.",
1884
+ "maxItems": 64,
1885
+ "type": "array",
1886
+ "items": {
1887
+ "type": "object",
1888
+ "properties": {
1889
+ "name": {
1890
+ "type": "string",
1891
+ "maxLength": 128,
1892
+ "allOf": [
1893
+ {
1894
+ "type": "string",
1895
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
1896
+ },
1897
+ {
1898
+ "type": "string",
1899
+ "pattern": "^(?!(?:claudecode|codexcli|opencode|cursor|grokcli)$)"
1900
+ }
1901
+ ],
1902
+ "description": "Name of the custom harness; cannot reuse a shipped one."
1903
+ },
1904
+ "capabilities": {
1905
+ "minItems": 6,
1906
+ "maxItems": 6,
1907
+ "type": "array",
1908
+ "items": {
1909
+ "oneOf": [
1910
+ {
1911
+ "type": "object",
1912
+ "properties": {
1913
+ "feature": {
1914
+ "type": "string",
1915
+ "enum": [
1916
+ "rules",
1917
+ "mcp",
1918
+ "subagents",
1919
+ "skills",
1920
+ "hooks",
1921
+ "permissions"
1922
+ ],
1923
+ "description": "Surface feature this row describes."
1924
+ },
1925
+ "measured_on": {
1926
+ "type": "string",
1927
+ "format": "date",
1928
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
1929
+ "description": "Date the capability was measured."
1930
+ },
1931
+ "spelling": {
1932
+ "allOf": [
1933
+ {
1934
+ "type": "string",
1935
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
1936
+ },
1937
+ {
1938
+ "type": "string",
1939
+ "maxLength": 4096,
1940
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
1941
+ }
1942
+ ],
1943
+ "description": "File the harness reads for this feature."
1944
+ },
1945
+ "control": {
1946
+ "allOf": [
1947
+ {
1948
+ "type": "string",
1949
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
1950
+ },
1951
+ {
1952
+ "type": "string",
1953
+ "maxLength": 4096,
1954
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
1955
+ }
1956
+ ],
1957
+ "description": "Path of the deliberately broken control file the capability was measured against."
1958
+ },
1959
+ "mechanism": {
1960
+ "type": "object",
1961
+ "properties": {
1962
+ "module": {
1963
+ "allOf": [
1964
+ {
1965
+ "type": "string",
1966
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
1967
+ },
1968
+ {
1969
+ "type": "string",
1970
+ "maxLength": 4096,
1971
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
1972
+ }
1973
+ ],
1974
+ "description": "Module that implements the capability."
1975
+ },
1976
+ "export": {
1977
+ "type": "string",
1978
+ "maxLength": 128,
1979
+ "pattern": "^[A-Za-z_$][A-Za-z0-9_$]*$",
1980
+ "description": "Export of the module that implements the capability."
1981
+ }
1982
+ },
1983
+ "required": [
1984
+ "module",
1985
+ "export"
1986
+ ],
1987
+ "additionalProperties": false,
1988
+ "description": "Code that emits the surface."
1989
+ },
1990
+ "state": {
1991
+ "type": "string",
1992
+ "enum": [
1993
+ "enforced"
1994
+ ],
1995
+ "description": "Whether the harness enforces, only instructs, or lacks this capability."
1996
+ },
1997
+ "evidence": {
1998
+ "type": "object",
1999
+ "properties": {
2000
+ "reference": {
2001
+ "allOf": [
2002
+ {
2003
+ "type": "string",
2004
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
2005
+ },
2006
+ {
2007
+ "type": "string",
2008
+ "maxLength": 4096,
2009
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
2010
+ }
2011
+ ],
2012
+ "description": "Probe record or file, relative to the cockpit."
2013
+ },
2014
+ "sha256": {
2015
+ "type": "string",
2016
+ "pattern": "^[a-f0-9]{64}$",
2017
+ "description": "SHA-256 of the evidence."
2018
+ }
2019
+ },
2020
+ "required": [
2021
+ "reference",
2022
+ "sha256"
2023
+ ],
2024
+ "additionalProperties": false,
2025
+ "description": "Evidence that the harness enforces the capability."
2026
+ }
2027
+ },
2028
+ "required": [
2029
+ "feature",
2030
+ "measured_on",
2031
+ "spelling",
2032
+ "control",
2033
+ "mechanism",
2034
+ "state",
2035
+ "evidence"
2036
+ ],
2037
+ "additionalProperties": false
2038
+ },
2039
+ {
2040
+ "type": "object",
2041
+ "properties": {
2042
+ "feature": {
2043
+ "type": "string",
2044
+ "enum": [
2045
+ "rules",
2046
+ "mcp",
2047
+ "subagents",
2048
+ "skills",
2049
+ "hooks",
2050
+ "permissions"
2051
+ ],
2052
+ "description": "Surface feature this row describes."
2053
+ },
2054
+ "measured_on": {
2055
+ "type": "string",
2056
+ "format": "date",
2057
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
2058
+ "description": "Date the capability was measured."
2059
+ },
2060
+ "spelling": {
2061
+ "allOf": [
2062
+ {
2063
+ "type": "string",
2064
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
2065
+ },
2066
+ {
2067
+ "type": "string",
2068
+ "maxLength": 4096,
2069
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
2070
+ }
2071
+ ],
2072
+ "description": "File the harness reads for this feature."
2073
+ },
2074
+ "control": {
2075
+ "allOf": [
2076
+ {
2077
+ "type": "string",
2078
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
2079
+ },
2080
+ {
2081
+ "type": "string",
2082
+ "maxLength": 4096,
2083
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
2084
+ }
2085
+ ],
2086
+ "description": "Path of the deliberately broken control file the capability was measured against."
2087
+ },
2088
+ "mechanism": {
2089
+ "type": "object",
2090
+ "properties": {
2091
+ "module": {
2092
+ "allOf": [
2093
+ {
2094
+ "type": "string",
2095
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
2096
+ },
2097
+ {
2098
+ "type": "string",
2099
+ "maxLength": 4096,
2100
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
2101
+ }
2102
+ ],
2103
+ "description": "Module that implements the capability."
2104
+ },
2105
+ "export": {
2106
+ "type": "string",
2107
+ "maxLength": 128,
2108
+ "pattern": "^[A-Za-z_$][A-Za-z0-9_$]*$",
2109
+ "description": "Export of the module that implements the capability."
2110
+ }
2111
+ },
2112
+ "required": [
2113
+ "module",
2114
+ "export"
2115
+ ],
2116
+ "additionalProperties": false,
2117
+ "description": "Code that emits the surface."
2118
+ },
2119
+ "state": {
2120
+ "type": "string",
2121
+ "enum": [
2122
+ "instructed"
2123
+ ],
2124
+ "description": "Whether the harness enforces, only instructs, or lacks this capability."
2125
+ }
2126
+ },
2127
+ "required": [
2128
+ "feature",
2129
+ "measured_on",
2130
+ "spelling",
2131
+ "control",
2132
+ "mechanism",
2133
+ "state"
2134
+ ],
2135
+ "additionalProperties": false
2136
+ },
2137
+ {
2138
+ "type": "object",
2139
+ "properties": {
2140
+ "feature": {
2141
+ "type": "string",
2142
+ "enum": [
2143
+ "rules",
2144
+ "mcp",
2145
+ "subagents",
2146
+ "skills",
2147
+ "hooks",
2148
+ "permissions"
2149
+ ],
2150
+ "description": "Surface feature this row describes."
2151
+ },
2152
+ "measured_on": {
2153
+ "type": "string",
2154
+ "format": "date",
2155
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
2156
+ "description": "Date the capability was measured."
2157
+ },
2158
+ "state": {
2159
+ "type": "string",
2160
+ "enum": [
2161
+ "unavailable"
2162
+ ],
2163
+ "description": "Whether the harness enforces, only instructs, or lacks this capability."
2164
+ },
2165
+ "reason": {
2166
+ "type": "string",
2167
+ "minLength": 1,
2168
+ "maxLength": 4096,
2169
+ "pattern": "\\S",
2170
+ "description": "Why the capability is unavailable."
2171
+ }
2172
+ },
2173
+ "required": [
2174
+ "feature",
2175
+ "measured_on",
2176
+ "state",
2177
+ "reason"
2178
+ ],
2179
+ "additionalProperties": false
2180
+ }
2181
+ ]
2182
+ },
2183
+ "description": "One row per surface feature saying what the harness supports."
2184
+ }
2185
+ },
2186
+ "required": [
2187
+ "name",
2188
+ "capabilities"
2189
+ ],
2190
+ "additionalProperties": false
2191
+ }
2192
+ },
2193
+ "bundles": {
2194
+ "default": [],
2195
+ "description": "Bundle formats to publish, such as a Claude plugin bundle.",
2196
+ "maxItems": 1,
2197
+ "type": "array",
2198
+ "items": {
2199
+ "type": "string",
2200
+ "enum": [
2201
+ "claudecode-plugin"
2202
+ ]
2203
+ }
2204
+ },
2205
+ "adopted": {
2206
+ "default": [],
2207
+ "description": "Harness settings files cockpit merges with its own output.",
2208
+ "maxItems": 3,
2209
+ "type": "array",
2210
+ "items": {
2211
+ "type": "object",
2212
+ "properties": {
2213
+ "path": {
2214
+ "type": "string",
2215
+ "enum": [
2216
+ ".claude/settings.json",
2217
+ ".codex/config.toml",
2218
+ ".codex/hooks.json"
2219
+ ],
2220
+ "description": "Harness settings file that was adopted."
2221
+ },
2222
+ "source": {
2223
+ "allOf": [
2224
+ {
2225
+ "type": "string",
2226
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$"
2227
+ },
2228
+ {
2229
+ "type": "string",
2230
+ "maxLength": 4096,
2231
+ "pattern": "^(?!.*(?:^|\\/)(?:\\.git|internal|node_modules)(?:\\/|$)).+$"
2232
+ }
2233
+ ],
2234
+ "description": "Where the adopted copy now lives, under cockpit/adopted/."
2235
+ },
2236
+ "sha256": {
2237
+ "type": "string",
2238
+ "pattern": "^[a-f0-9]{64}$",
2239
+ "description": "SHA-256 of the bytes that were moved, as a record for review."
2240
+ },
2241
+ "adopted_on": {
2242
+ "type": "string",
2243
+ "format": "date",
2244
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
2245
+ "description": "Date the file was adopted."
2246
+ },
2247
+ "provenance": {
2248
+ "type": "object",
2249
+ "properties": {
2250
+ "source": {
2251
+ "type": "string",
2252
+ "maxLength": 4096,
2253
+ "pattern": "^(?!\\/)(?![A-Za-z][A-Za-z0-9+.-]*:)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*\\\\)(?:[^/\\x00-\\x1f\\x7f]+\\/)*[^/\\x00-\\x1f\\x7f]+$",
2254
+ "description": "File or place the value came from, relative to the repository."
2255
+ },
2256
+ "observed_on": {
2257
+ "description": "Date the source was looked at; required unless kind is declared.",
2258
+ "type": "string",
2259
+ "format": "date",
2260
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
2261
+ },
2262
+ "kind": {
2263
+ "type": "string",
2264
+ "enum": [
2265
+ "declared",
2266
+ "measured",
2267
+ "inferred"
2268
+ ],
2269
+ "description": "How the value was established: declared by this file, measured, or inferred."
2270
+ },
2271
+ "reason": {
2272
+ "type": "string",
2273
+ "minLength": 1,
2274
+ "maxLength": 4096,
2275
+ "pattern": "\\S",
2276
+ "description": "Why the value is what it is."
2277
+ },
2278
+ "confirmed": {
2279
+ "description": "Set to true once a person has confirmed an inferred value; inferred values require it.",
2280
+ "type": "boolean"
2281
+ }
2282
+ },
2283
+ "required": [
2284
+ "source",
2285
+ "kind",
2286
+ "reason"
2287
+ ],
2288
+ "additionalProperties": false,
2289
+ "description": "Where the adoption came from; its kind must be declared.",
2290
+ "anyOf": [
2291
+ {
2292
+ "properties": {
2293
+ "kind": {
2294
+ "enum": [
2295
+ "declared"
2296
+ ]
2297
+ }
2298
+ }
2299
+ },
2300
+ {
2301
+ "properties": {
2302
+ "kind": {
2303
+ "enum": [
2304
+ "measured"
2305
+ ]
2306
+ }
2307
+ },
2308
+ "required": [
2309
+ "observed_on"
2310
+ ]
2311
+ },
2312
+ {
2313
+ "properties": {
2314
+ "kind": {
2315
+ "enum": [
2316
+ "inferred"
2317
+ ]
2318
+ },
2319
+ "confirmed": {
2320
+ "enum": [
2321
+ true
2322
+ ]
2323
+ }
2324
+ },
2325
+ "required": [
2326
+ "confirmed",
2327
+ "observed_on"
2328
+ ]
2329
+ }
2330
+ ]
2331
+ }
2332
+ },
2333
+ "required": [
2334
+ "path",
2335
+ "source",
2336
+ "sha256",
2337
+ "adopted_on",
2338
+ "provenance"
2339
+ ],
2340
+ "additionalProperties": false
2341
+ }
2342
+ }
2343
+ },
2344
+ "additionalProperties": false
2345
+ }
2346
+ },
2347
+ "required": [
2348
+ "cockpit",
2349
+ "sibling",
2350
+ "ports"
2351
+ ],
2352
+ "additionalProperties": false,
2353
+ "x-cockpit-runtime-checks": [
2354
+ {
2355
+ "path": "sibling[].slug",
2356
+ "rule": "unique"
2357
+ },
2358
+ {
2359
+ "path": "sibling[].dir",
2360
+ "rule": "unique"
2361
+ },
2362
+ {
2363
+ "path": "sibling[].var",
2364
+ "rule": "unique"
2365
+ },
2366
+ {
2367
+ "path": "sibling[].environment_files[].instance",
2368
+ "rule": "unique"
2369
+ },
2370
+ {
2371
+ "path": "environment.resettable_volumes[]",
2372
+ "rule": "unique"
2373
+ },
2374
+ {
2375
+ "path": "environment.resettable_volumes[]",
2376
+ "rule": "declared_compose_volume_key"
2377
+ },
2378
+ {
2379
+ "path": "environment.generated_host_paths[]",
2380
+ "rule": "unique"
2381
+ },
2382
+ {
2383
+ "path": "environment.compose_files[]",
2384
+ "rule": "unique"
2385
+ },
2386
+ {
2387
+ "path": "environment.entrypoint_derivatives[].name",
2388
+ "rule": "unique"
2389
+ },
2390
+ {
2391
+ "path": "environment.install_policies[].toolchain+lockfile",
2392
+ "rule": "unique"
2393
+ },
2394
+ {
2395
+ "path": "environment.posture_requirements[].requirement",
2396
+ "rule": "unique"
2397
+ },
2398
+ {
2399
+ "path": "environment.entrypoint_derivatives[].port",
2400
+ "rule": "declared_in_ports.bases"
2401
+ },
2402
+ {
2403
+ "path": "browser.artifacts",
2404
+ "rule": "exact_environment.generated_host_paths_coverage"
2405
+ },
2406
+ {
2407
+ "path": "browser",
2408
+ "rule": "matches_environment_addressing_authentication_and_client_cap"
2409
+ },
2410
+ {
2411
+ "path": "browser.images",
2412
+ "rule": "mcp_driver_shares_major_minor_with_project_driver"
2413
+ },
2414
+ {
2415
+ "path": "testing.gates[].stages[]",
2416
+ "rule": "references_declared_testing_stage"
2417
+ },
2418
+ {
2419
+ "path": "sibling[].environment_files[]",
2420
+ "rule": "template_and_instance_differ"
2421
+ },
2422
+ {
2423
+ "path": "sibling[].derives.mcp_sources[].path",
2424
+ "rule": "unique_within_sibling"
2425
+ },
2426
+ {
2427
+ "path": "environment.seed",
2428
+ "rule": "requires_resettable_volumes"
2429
+ },
2430
+ {
2431
+ "path": "ports",
2432
+ "rule": "count_times_base_count_within_shared_input_budget",
2433
+ "limit": 4096
2434
+ },
2435
+ {
2436
+ "path": "surfaces.overlays[].name",
2437
+ "rule": "unique"
2438
+ },
2439
+ {
2440
+ "path": "surfaces.overlays[].sources[].path",
2441
+ "rule": "unique"
2442
+ },
2443
+ {
2444
+ "path": "surfaces.overlays[].sources",
2445
+ "rule": "feature_namespace_and_complete_skill_definitions"
2446
+ },
2447
+ {
2448
+ "path": "surfaces.overlays[].sources[].bytes",
2449
+ "rule": "utf8_byte_length_at_most_65536"
2450
+ },
2451
+ {
2452
+ "path": "surfaces.overlays[].replaces.name",
2453
+ "rule": "matches_declaration_name"
2454
+ },
2455
+ {
2456
+ "path": "surfaces.harnesses[].name",
2457
+ "rule": "unique"
2458
+ },
2459
+ {
2460
+ "path": "surfaces.harnesses[].capabilities",
2461
+ "rule": "one_row_per_surface_feature"
2462
+ },
2463
+ {
2464
+ "path": "surfaces.harnesses[].capabilities[].spelling",
2465
+ "rule": "unique_when_emitted"
2466
+ },
2467
+ {
2468
+ "path": "surfaces.adopted[].path",
2469
+ "rule": "unique"
2470
+ },
2471
+ {
2472
+ "path": "surfaces.adopted[].source",
2473
+ "rule": "equals_cockpit/adopted/<path>"
2474
+ },
2475
+ {
2476
+ "path": "surfaces.adopted[].provenance.kind",
2477
+ "rule": "declared"
2478
+ }
2479
+ ],
2480
+ "x-cockpit-editor-limitations": [
2481
+ {
2482
+ "path": "sibling[].environment_files[].instance",
2483
+ "rule": "unique"
2484
+ },
2485
+ {
2486
+ "path": "sibling[].environment_files[]",
2487
+ "rule": "template_and_instance_differ"
2488
+ },
2489
+ {
2490
+ "path": "sibling[].derives.mcp_sources[].path",
2491
+ "rule": "unique_within_sibling"
2492
+ },
2493
+ {
2494
+ "path": "environment.seed",
2495
+ "rule": "requires_resettable_volumes"
2496
+ },
2497
+ {
2498
+ "path": "environment.entrypoint_derivatives[].name",
2499
+ "rule": "unique"
2500
+ },
2501
+ {
2502
+ "path": "environment.entrypoint_derivatives[].port",
2503
+ "rule": "declared_in_ports.bases"
2504
+ },
2505
+ {
2506
+ "path": "environment.install_policies[].toolchain+lockfile",
2507
+ "rule": "unique"
2508
+ },
2509
+ {
2510
+ "path": "environment.posture_requirements[].requirement",
2511
+ "rule": "unique"
2512
+ },
2513
+ {
2514
+ "path": "browser.artifacts",
2515
+ "rule": "exact_environment.generated_host_paths_coverage"
2516
+ },
2517
+ {
2518
+ "path": "browser",
2519
+ "rule": "matches_environment_addressing_authentication_and_client_cap"
2520
+ },
2521
+ {
2522
+ "path": "browser.images",
2523
+ "rule": "mcp_driver_shares_major_minor_with_project_driver"
2524
+ },
2525
+ {
2526
+ "path": "testing.gates[].stages[]",
2527
+ "rule": "references_declared_testing_stage"
2528
+ },
2529
+ {
2530
+ "path": "surfaces.overlays[].name",
2531
+ "rule": "unique"
2532
+ },
2533
+ {
2534
+ "path": "surfaces.overlays[].sources[].path",
2535
+ "rule": "unique"
2536
+ },
2537
+ {
2538
+ "path": "surfaces.overlays[].sources",
2539
+ "rule": "feature_namespace_and_complete_skill_definitions"
2540
+ },
2541
+ {
2542
+ "path": "surfaces.overlays[].sources[].bytes",
2543
+ "rule": "utf8_byte_length_at_most_65536"
2544
+ },
2545
+ {
2546
+ "path": "surfaces.overlays[].replaces.name",
2547
+ "rule": "matches_declaration_name"
2548
+ },
2549
+ {
2550
+ "path": "surfaces.harnesses[].name",
2551
+ "rule": "unique"
2552
+ },
2553
+ {
2554
+ "path": "surfaces.harnesses[].capabilities",
2555
+ "rule": "one_row_per_surface_feature"
2556
+ },
2557
+ {
2558
+ "path": "surfaces.harnesses[].capabilities[].spelling",
2559
+ "rule": "unique_when_emitted"
2560
+ },
2561
+ {
2562
+ "path": "surfaces.adopted[].path",
2563
+ "rule": "unique"
2564
+ },
2565
+ {
2566
+ "path": "surfaces.adopted[].source",
2567
+ "rule": "equals_cockpit/adopted/<path>"
2568
+ },
2569
+ {
2570
+ "path": "surfaces.adopted[].provenance.kind",
2571
+ "rule": "declared"
2572
+ }
2573
+ ]
2574
+ }