@b00dea/cockpit 0.1.0 → 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 (196) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/README.md +3 -0
  3. package/cockpit.schema.json +73 -3
  4. package/dist/autonomy.d.ts +3 -2
  5. package/dist/autonomy.js +30 -13
  6. package/dist/browser/commands.d.ts +57 -2
  7. package/dist/browser/commands.js +114 -10
  8. package/dist/browser/runtime.d.ts +1 -0
  9. package/dist/browser/runtime.js +4 -1
  10. package/dist/browser/surfaces.d.ts +7 -7
  11. package/dist/browser/surfaces.js +5 -0
  12. package/dist/canonical-json.d.ts +2 -0
  13. package/dist/canonical-json.js +5 -0
  14. package/dist/cli-main.d.ts +40 -3
  15. package/dist/cli-main.js +241 -62
  16. package/dist/command-table.d.ts +19 -11
  17. package/dist/command-table.js +190 -38
  18. package/dist/config/load.d.ts +16 -4
  19. package/dist/config/load.js +25 -3
  20. package/dist/config/unconfirmed-toml.d.ts +9 -0
  21. package/dist/config/unconfirmed-toml.js +29 -0
  22. package/dist/diagnostics.js +10 -1
  23. package/dist/docs/check.d.ts +16 -0
  24. package/dist/docs/check.js +197 -0
  25. package/dist/docs/decision-record.d.ts +34 -0
  26. package/dist/docs/decision-record.js +135 -0
  27. package/dist/docs/decisions.d.ts +16 -0
  28. package/dist/docs/decisions.js +103 -0
  29. package/dist/docs/markdown.d.ts +36 -0
  30. package/dist/docs/markdown.js +88 -0
  31. package/dist/docs/references.d.ts +32 -0
  32. package/dist/docs/references.js +148 -0
  33. package/dist/environment/application/confirm.d.ts +35 -0
  34. package/dist/environment/application/confirm.js +122 -0
  35. package/dist/environment/application/destructive.js +6 -2
  36. package/dist/environment/application/doctor.d.ts +12 -7
  37. package/dist/environment/application/doctor.js +20 -8
  38. package/dist/environment/application/guard.d.ts +12 -6
  39. package/dist/environment/application/guard.js +87 -32
  40. package/dist/environment/application/health.d.ts +14 -5
  41. package/dist/environment/application/health.js +8 -2
  42. package/dist/environment/application/lifecycle-context.d.ts +10 -3
  43. package/dist/environment/application/lifecycle-state.js +4 -3
  44. package/dist/environment/application/lifecycle.d.ts +2 -1
  45. package/dist/environment/application/lifecycle.js +11 -3
  46. package/dist/environment/application/services.d.ts +60 -0
  47. package/dist/environment/application/services.js +89 -0
  48. package/dist/environment/application/siblings.d.ts +43 -0
  49. package/dist/environment/application/siblings.js +269 -0
  50. package/dist/environment/claims.d.ts +10 -10
  51. package/dist/environment/claims.js +3 -11
  52. package/dist/environment/compose-topology.d.ts +15 -7
  53. package/dist/environment/compose-topology.js +100 -23
  54. package/dist/environment/contract.d.ts +42 -9
  55. package/dist/environment/contract.js +33 -0
  56. package/dist/environment/executable.d.ts +12 -0
  57. package/dist/environment/executable.js +46 -23
  58. package/dist/environment/generated-application/check.js +2 -0
  59. package/dist/environment/generated-application/prepare.js +2 -0
  60. package/dist/environment/generated-application/shared.d.ts +10 -2
  61. package/dist/environment/generated-application/shared.js +6 -1
  62. package/dist/environment/generated-application/surface-outputs.js +23 -12
  63. package/dist/environment/generated-application/surfaces.js +16 -11
  64. package/dist/environment/generated-application/sync.js +19 -4
  65. package/dist/environment/git-observation.d.ts +25 -6
  66. package/dist/environment/git-observation.js +37 -28
  67. package/dist/environment/health-composition.d.ts +3 -2
  68. package/dist/environment/health-composition.js +19 -2
  69. package/dist/environment/init-application.d.ts +39 -14
  70. package/dist/environment/init-application.js +39 -10
  71. package/dist/environment/lifecycle-composition.d.ts +4 -2
  72. package/dist/environment/lifecycle-composition.js +84 -17
  73. package/dist/environment/lifecycle-stage.d.ts +8 -3
  74. package/dist/environment/lifecycle-stage.js +11 -1
  75. package/dist/environment/logs.d.ts +1 -1
  76. package/dist/environment/map-limit.d.ts +2 -0
  77. package/dist/environment/map-limit.js +13 -0
  78. package/dist/environment/mcp-observation.d.ts +9 -0
  79. package/dist/environment/mcp-observation.js +46 -0
  80. package/dist/environment/observations.d.ts +1 -1
  81. package/dist/environment/observations.js +2 -0
  82. package/dist/environment/operator-application.d.ts +35 -6
  83. package/dist/environment/operator-application.js +42 -0
  84. package/dist/environment/presence.d.ts +4 -0
  85. package/dist/environment/presence.js +26 -0
  86. package/dist/environment/read-composition.d.ts +8 -3
  87. package/dist/environment/read-composition.js +53 -8
  88. package/dist/environment/readiness-composition.d.ts +20 -1
  89. package/dist/environment/readiness-composition.js +23 -2
  90. package/dist/environment/reclaim.d.ts +56 -19
  91. package/dist/environment/reclaim.js +147 -42
  92. package/dist/environment/runtime.d.ts +64 -18
  93. package/dist/environment/runtime.js +73 -3
  94. package/dist/environment/served-checkout-grants.d.ts +53 -0
  95. package/dist/environment/served-checkout-grants.js +182 -0
  96. package/dist/environment/sibling-checkouts.d.ts +119 -0
  97. package/dist/environment/sibling-checkouts.js +254 -0
  98. package/dist/environment/sibling-observation.d.ts +27 -0
  99. package/dist/environment/sibling-observation.js +45 -0
  100. package/dist/environment/sibling-pull.d.ts +23 -0
  101. package/dist/environment/sibling-pull.js +95 -0
  102. package/dist/environment/stack-inputs.d.ts +18 -0
  103. package/dist/environment/stack-inputs.js +210 -0
  104. package/dist/environment/stack-inventory-prune.d.ts +31 -0
  105. package/dist/environment/stack-inventory-prune.js +129 -0
  106. package/dist/environment/stack-inventory-report.d.ts +44 -0
  107. package/dist/environment/stack-inventory-report.js +78 -0
  108. package/dist/environment/stack-inventory.d.ts +94 -0
  109. package/dist/environment/stack-inventory.js +418 -0
  110. package/dist/environment/state.d.ts +48 -9
  111. package/dist/environment/state.js +142 -2
  112. package/dist/environment/tool-registration.js +3 -7
  113. package/dist/environment-exec/execute.d.ts +6 -3
  114. package/dist/environment-exec/execute.js +4 -0
  115. package/dist/fix-catalogue.d.ts +1 -1
  116. package/dist/generated-environment/adopt.js +4 -8
  117. package/dist/guards/answer-confirmation.d.ts +41 -0
  118. package/dist/guards/answer-confirmation.js +109 -0
  119. package/dist/guards/evaluator.d.ts +20 -3
  120. package/dist/guards/evaluator.js +39 -7
  121. package/dist/guards/local-identity.d.ts +6 -2
  122. package/dist/guards/local-identity.js +10 -4
  123. package/dist/guards/policy-change.d.ts +43 -0
  124. package/dist/guards/policy-change.js +159 -0
  125. package/dist/guards/policy-pin.d.ts +1 -1
  126. package/dist/guards/policy-pin.js +14 -12
  127. package/dist/init/command.d.ts +4 -3
  128. package/dist/init/command.js +36 -16
  129. package/dist/init/derive.d.ts +8 -6
  130. package/dist/init/derive.js +140 -36
  131. package/dist/init/draft.d.ts +13 -11
  132. package/dist/init/draft.js +54 -31
  133. package/dist/init/render.d.ts +18 -6
  134. package/dist/init/render.js +31 -9
  135. package/dist/repository-path.d.ts +9 -0
  136. package/dist/repository-path.js +16 -0
  137. package/dist/schema.d.ts +42 -75
  138. package/dist/schema.js +62 -11
  139. package/dist/surfaces/harness-registry.d.ts +80 -0
  140. package/dist/surfaces/harness-registry.js +29 -0
  141. package/dist/surfaces/mcp.d.ts +67 -17
  142. package/dist/surfaces/mcp.js +194 -31
  143. package/dist/surfaces/projection.d.ts +7 -7
  144. package/dist/surfaces/projection.js +41 -6
  145. package/dist/surfaces/render.d.ts +5 -44
  146. package/dist/surfaces/render.js +5 -2
  147. package/dist/team-metadata.js +2 -1
  148. package/dist/testing/test-protection.d.ts +34 -0
  149. package/dist/testing/test-protection.js +137 -0
  150. package/dist/testing/weakening.d.ts +15 -0
  151. package/dist/testing/weakening.js +30 -0
  152. package/dist/work-orders/application-closure.d.ts +7 -0
  153. package/dist/work-orders/application-closure.js +76 -0
  154. package/dist/work-orders/application-context.d.ts +162 -0
  155. package/dist/work-orders/application-context.js +137 -0
  156. package/dist/work-orders/application-decisions.d.ts +27 -0
  157. package/dist/work-orders/application-decisions.js +121 -0
  158. package/dist/work-orders/application-grading.d.ts +11 -0
  159. package/dist/work-orders/application-grading.js +212 -0
  160. package/dist/work-orders/application.d.ts +4 -97
  161. package/dist/work-orders/application.js +94 -254
  162. package/dist/work-orders/composition.d.ts +35 -58
  163. package/dist/work-orders/composition.js +216 -24
  164. package/dist/work-orders/contract.d.ts +22 -6
  165. package/dist/work-orders/contract.js +34 -16
  166. package/dist/work-orders/decisions.d.ts +23 -0
  167. package/dist/work-orders/decisions.js +55 -0
  168. package/dist/work-orders/store.d.ts +54 -5
  169. package/dist/work-orders/store.js +118 -24
  170. package/docs/README.md +6 -3
  171. package/docs/capability-matrix.md +17 -9
  172. package/docs/cli-reference.md +209 -1
  173. package/docs/command-list.md +12 -1
  174. package/docs/concepts.md +6 -4
  175. package/docs/configuration-essentials.md +7 -2
  176. package/docs/configuration-reference.md +18 -3
  177. package/docs/docs-check.md +76 -0
  178. package/docs/environment.md +194 -6
  179. package/docs/faq.md +5 -3
  180. package/docs/getting-started.md +109 -25
  181. package/docs/harness-surfaces.md +69 -2
  182. package/docs/safety-and-autonomy.md +56 -12
  183. package/docs/troubleshooting.md +29 -8
  184. package/docs/tutorial.md +3 -2
  185. package/docs/work-and-browser.md +180 -14
  186. package/libexec/browser-operation.cjs +86 -2
  187. package/package.json +2 -2
  188. package/surfaces/skills/cockpit-browser.skill.md +7 -2
  189. package/surfaces/skills/cockpit-explain.skill.md +1 -1
  190. package/surfaces/skills/cockpit-fix.skill.md +1 -1
  191. package/surfaces/skills/cockpit-setup.skill.md +3 -3
  192. package/surfaces/skills/cockpit-work.skill.md +1 -1
  193. package/surfaces/skills/procedures/explain.md +9 -4
  194. package/surfaces/skills/procedures/fix.md +25 -11
  195. package/surfaces/skills/procedures/setup.md +113 -40
  196. package/surfaces/skills/procedures/work.md +45 -16
@@ -8,8 +8,11 @@ This generated index is for users choosing the command that owns their next oper
8
8
 
9
9
  - `cockpit init`: Preview, then accept, a first cockpit setup for one or more agent tools.
10
10
  - `cockpit setup`: Clone or locate the declared sibling repositories and link them.
11
+ - `cockpit use`: Serve a sibling from another of its checkouts, such as a worktree.
12
+ - `cockpit pull`: Fast-forward the cockpit and its siblings to their upstreams.
11
13
  - `cockpit sibling`: Add or remove a repository in cockpit.toml (sibling add, sibling remove).
12
14
  - `cockpit tool`: Add or remove an agent tool in cockpit.toml (tool add, tool remove).
15
+ - `cockpit confirm`: Confirm an init answer no person stated by running the observation that verifies it.
13
16
  - `cockpit registry-resolve`: Turn a validated shell registry into data shell scripts can source.
14
17
  - `cockpit upgrade`: Move the exact cockpit pin to a newer version and re-run sync.
15
18
 
@@ -26,9 +29,14 @@ This generated index is for users choosing the command that owns their next oper
26
29
  - `cockpit preflight`: Check that the environment is healthy and ready for work.
27
30
  - `cockpit session`: Keep the environment available for one command, then release it.
28
31
  - `cockpit logs`: Show recent logs for one declared service.
32
+ - `cockpit ps`: Show the state and health of each service in this checkout's stack.
33
+ - `cockpit restart`: Restart one service of this checkout's stack and wait until it is healthy.
34
+ - `cockpit rebuild`: Rebuild one service's image, replace its container and wait until it is healthy.
35
+ - `cockpit exec`: Run a command inside one service's container of this checkout's stack.
29
36
  - `cockpit sleep`: Release this checkout and stop the stack if no other holder remains.
30
37
  - `cockpit down`: Stop and remove the stack (on the active local Docker context).
31
38
  - `cockpit reset`: Preview a reset, then approve it interactively or apply it as [autonomy] reset allows (on the active local Docker context).
39
+ - `cockpit stacks`: List every stack on this machine, or preview and remove those whose checkout is gone (stacks prune).
32
40
 
33
41
  ## Diagnose
34
42
 
@@ -40,8 +48,10 @@ This generated index is for users choosing the command that owns their next oper
40
48
  - `cockpit work status`: Report each work order, its state and how it closed.
41
49
  - `cockpit work accept`: Accept a work order, or a change to an accepted one, as [work.gates] allows.
42
50
  - `cockpit work check`: Run every criterion's check and the order's gates.
43
- - `cockpit work note`: Record a note on an order, or with --ask an open question that blocks it.
51
+ - `cockpit work note`: Record a note on an order, an open question with --ask, or a decision with --decision.
52
+ - `cockpit work decide`: Resolve a recorded decision: write or cite its decision record, or say it is not lasting.
44
53
  - `cockpit work answer`: Answer an open question on an order, as [work.gates] allows.
54
+ - `cockpit work acknowledge`: Acknowledge that an order weakened tests, as [work.gates] allows.
45
55
  - `cockpit work grade`: Grade an accepted order the way [work] grading says.
46
56
  - `cockpit work signoff`: Close a graded order as done, or any open one as partial or abandoned.
47
57
  - `cockpit work recover`: Inspect or remove a crashed command's work-order lock.
@@ -49,3 +59,4 @@ This generated index is for users choosing the command that owns their next oper
49
59
  - `cockpit grade`: Independently grade uncommitted work against a criteria file, with no work order.
50
60
  - `cockpit browser drive`: Drive the declared application browser surfaces.
51
61
  - `cockpit browser screenshot`: Capture the declared application surfaces.
62
+ - `cockpit docs check`: Report removed paths and make targets living docs still cite, and broken decision records.
package/docs/concepts.md CHANGED
@@ -68,10 +68,12 @@ holds its schema and limits.
68
68
  ### Evaluator
69
69
 
70
70
  The grader for a finished work order under the default `independent` grading. It grades each
71
- acceptance criterion against the checks cockpit ran and the change since the order was accepted, in a
72
- fresh read-only run that never sees the session that did the work, in another listed agent tool when
73
- one is available, otherwise the same tool in a new run. It never edits code. A cockpit can instead let the
74
- checks alone decide, or let the agent report its own verdict; the record says which.
71
+ acceptance criterion, and the standing criteria cockpit adds (changes outside scope, flagged test
72
+ changes, the agent's amendments), against the checks cockpit ran and the change since the order was
73
+ accepted, in a fresh read-only run that never sees the session that did the work, in another listed
74
+ agent tool when one is available, otherwise the same tool in a new run. It never edits code. A cockpit
75
+ can instead let the checks alone decide, or let the agent report its own verdict; the record says
76
+ which.
75
77
 
76
78
  ### Enforced, instructed, generated and unavailable
77
79
 
@@ -22,7 +22,8 @@ siblings_root = ".."
22
22
  ## `[[sibling]]`
23
23
 
24
24
  One table per product repository. `mount` says how the stack uses the checkout: `always`
25
- bind-mounts it, `profile:<name>` mounts it only under that Compose profile, `none` leaves it read
25
+ bind-mounts it, `profile:<name>` mounts it only while that Compose profile is active
26
+ ([Compose profiles](environment.md#compose-profiles)), `none` leaves it read
26
27
  but never mounted, and `host` runs it outside the stack for the reason given in `host_reason`.
27
28
  `acquire` says how it reaches disk: `auto` clones `remote` during `setup`, `manual` expects a
28
29
  person to clone it, and `none` never clones it, so it must already be there. The two are
@@ -90,12 +91,15 @@ as written ([Compose-first stacks](environment.md#compose-first-stacks)). A smal
90
91
  Compose file gets a starting one from `cockpit init --scaffold-compose`
91
92
  ([Scaffold a Compose file](environment.md#scaffold-a-compose-file)). `resettable_volumes` names the
92
93
  Compose volumes `reset` may delete, and `seed` the command `up` runs to fill them
93
- ([Demo data, test users and roles](environment.md#demo-data-test-users-and-roles)). Full entry:
94
+ ([Demo data, test users and roles](environment.md#demo-data-test-users-and-roles)). `profiles`
95
+ names the Compose profiles every `up` activates; `up --profile <name>` adds one for a run
96
+ ([Compose profiles](environment.md#compose-profiles)). Full entry:
94
97
  [`[environment]`](configuration-reference.md#environment).
95
98
 
96
99
  ```toml
97
100
  [environment]
98
101
  compose_files = ["compose.yml"]
102
+ profiles = ["workers"]
99
103
  resettable_volumes = ["postgres-data"]
100
104
  seed = { argv = ["npm", "run", "db:seed"], timeout_seconds = 300 }
101
105
  ```
@@ -170,3 +174,4 @@ reference also lists the [defaults](configuration-reference.md#defaults) and the
170
174
  | MCP approvals | [`[mcp]`](configuration-reference.md#mcp) | [MCP servers and restrictions](harness-surfaces.md#mcp-servers-and-restrictions) |
171
175
  | Surface overlays | [`[[surfaces.overlays]]`](configuration-reference.md#surfacesoverlays) | [Ownership and extension](harness-surfaces.md#ownership-and-extension) |
172
176
  | Custom harnesses | [`[[surfaces.harnesses]]`](configuration-reference.md#surfacesharnesses) | [Custom harnesses](harness-surfaces.md#custom-harnesses) |
177
+ | Living documents and decision records | [`[docs]`](configuration-reference.md#docs) | [Check living documents and decision records](docs-check.md) |
@@ -54,6 +54,7 @@ The values cockpit uses for a key the configuration leaves out.
54
54
  "resettable_volumes": [],
55
55
  "generated_host_paths": [],
56
56
  "compose_files": [],
57
+ "profiles": [],
57
58
  "entrypoint_derivatives": [],
58
59
  "install_policies": []
59
60
  },
@@ -91,6 +92,7 @@ Each section is one TOML table: `[name]` holds one, `[[name]]` repeats. A table
91
92
  | `testing` | Test stages and gates. | table: [`[testing]`](#testing) | | |
92
93
  | `environment` | How the stack is reached, signed in to, built and kept. | table: [`[environment]`](#environment) | `{}` | |
93
94
  | `surfaces` | Instructions, skills and settings generated for agent tools. | table: [`[surfaces]`](#surfaces) | `{}` | |
95
+ | `docs` | Living documents and decision records: docs check keeps them true, and work orders record their decisions there. | table: [`[docs]`](#docs) | | |
94
96
 
95
97
  ### `[cockpit]`
96
98
 
@@ -118,6 +120,7 @@ Each section is one TOML table: `[name]` holds one, `[[name]]` repeats. A table
118
120
  | `instruction_pointer` | Let setup add a pointer to the cockpit guide in this sibling, when the command line also approves it. | boolean | `false` | |
119
121
  | `purpose` | What the sibling is for; printed when its checkout is missing. | string | | required; at least 1 character |
120
122
  | `environment_files` | Template and instance environment file pairs the sibling needs. | array of table: [`[[sibling.environment_files]]`](#siblingenvironment_files) | | |
123
+ | `rebuild_inputs` | Files or directories in the sibling, beyond its lockfiles, whose change leaves a running stack stale, such as a migrations directory. | array of string | | at most 64 items; each item: pattern [P1](#patterns) |
121
124
  | `derives` | Facts about the sibling that cockpit derives rows or MCP servers from. | table: [`[sibling.derives]`](#siblingderives) | | |
122
125
 
123
126
  - Must match `{"oneOf":[{"properties":{"acquire":{"enum":["none"]}},"not":{"required":["remote"]}},{"properties":{"acquire":{"enum":["auto","manual"]}},"required":["remote"]}]}`.
@@ -209,9 +212,10 @@ Each section is one TOML table: `[name]` holds one, `[[name]]` repeats. A table
209
212
  | Key | Meaning | Type | Default | Constraints |
210
213
  | --- | --- | --- | --- | --- |
211
214
  | `accept` | Who accepts a draft work order: agent, person or ci. Default agent. | string | | one of `"agent"`, `"person"`, `"ci"` |
212
- | `amend` | Who accepts a changed contract. Default agent. Removing or rewriting an accepted criterion always needs a person or ci. | string | | one of `"agent"`, `"person"`, `"ci"` |
215
+ | `amend` | Who accepts a changed contract. Default agent. Removing an accepted criterion or gate always needs a person or ci; an agent's rewrite of a criterion, scope, non-goal or objective is judged at the next grade, and needs a person under checks grading. | string | | one of `"agent"`, `"person"`, `"ci"` |
213
216
  | `answer` | Who answers an open question on an order. Default agent. | string | | one of `"agent"`, `"person"`, `"ci"` |
214
217
  | `signoff` | Who closes a graded order. Default agent. | string | | one of `"agent"`, `"person"`, `"ci"` |
218
+ | `acknowledge` | Who acknowledges that an order weakened tests, which checks grading otherwise fails; under independent and self grading the acknowledgement is context for the verdict. Default agent. | string | | one of `"agent"`, `"person"`, `"ci"` |
215
219
 
216
220
  ### `[autonomy]`
217
221
 
@@ -238,7 +242,7 @@ Each section is one TOML table: `[name]` holds one, `[[name]]` repeats. A table
238
242
  | `resolver` | Fixed host name to address mappings the browser uses. | array of table: [`[[browser.resolver]]`](#browserresolver) | `[]` | at most 64 items |
239
243
  | `authentication` | How browser sessions sign in to the application. | table: [`[browser.authentication]`](#browserauthentication) | | required |
240
244
  | `data` | Statement about the data the browser touches; cockpit cannot observe it. | table: [`[browser.data]`](#browserdata) | | required |
241
- | `request_preapproval` | Run browser tools without prompts; allowed only on isolated, non-production, non-restored data. | boolean | `false` | |
245
+ | `request_preapproval` | Run browser tools without prompts; allowed only on isolated, non-production, non-restored data. Defaults to true when data qualifies and false otherwise. | boolean | | |
242
246
  | `artifacts` | Generated host paths for browser output. | table: [`[browser.artifacts]`](#browserartifacts) | | required |
243
247
 
244
248
  - Must match at least one of `[{"properties":{"request_preapproval":{"enum":[false]}}},{"properties":{"data":{"required":["mode","isolated","reaches_production"],"properties":{"mode":{"enum":["empty","seeded"]},"isolated":{"enum":[true]},"reaches_production":{"enum":[false]}}}}}]`.
@@ -324,6 +328,7 @@ Each section is one TOML table: `[name]` holds one, `[[name]]` repeats. A table
324
328
 
325
329
  | Key | Meaning | Type | Default | Constraints |
326
330
  | --- | --- | --- | --- | --- |
331
+ | `test_files` | Paths and globs, relative to each checkout, that hold tests. Grading fails an order that deletes, skips or loosens what they match. Defaults to common layouts. | array of string | | 1–64 items; each item: pattern `^(?!\/)(?!.*(?:^\|\/)\.\.(?:\/\|$))[A-Za-z0-9._@+\-/*?]+$`, 1–512 characters |
327
332
  | `stages` | Commands that make up the test gates. | array of table: [`[[testing.stages]]`](#testingstages) | | required; 1–128 items |
328
333
  | `gates` | Named gates that run stages before handing back changes. | array of table: [`[[testing.gates]]`](#testinggates) | | required; 1–128 items |
329
334
  | `native_hooks` | How the repository's own git hooks are handled. | table: [`[testing.native_hooks]`](#testingnative_hooks) | `{"install":"inspect"}` | |
@@ -383,6 +388,7 @@ Each section is one TOML table: `[name]` holds one, `[[name]]` repeats. A table
383
388
  | `resettable_volumes` | Compose volumes that reset may delete and recreate, named by their Compose key. | array of string | `[]` | unique items; each item: pattern `^[a-z0-9][a-z0-9_.-]*$` |
384
389
  | `generated_host_paths` | Host paths cockpit generates and owns, relative to the cockpit. | array of string | `[]` | unique items; each item: pattern [P1](#patterns) |
385
390
  | `compose_files` | Compose files, relative to the cockpit, that make up the stack; cockpit runs them as written. | array of string | `[]` | unique items; each item: pattern [P1](#patterns), pattern `^[^:]+$` |
391
+ | `profiles` | Compose profiles every up and session activates; up --profile adds more for one run. | array of string | `[]` | at most 64 items; each item: pattern `^[a-z0-9][a-z0-9_.-]*$`, at most 64 characters |
386
392
  | `entrypoint_derivatives` | Addresses derived from leased ports, such as application origins and callback URLs. | array of table: [`[[environment.entrypoint_derivatives]]`](#environmententrypoint_derivatives) | `[]` | |
387
393
  | `install_policies` | The build and test commands the guard admits for each toolchain and lockfile. | array of table: [`[[environment.install_policies]]`](#environmentinstall_policies) | `[]` | |
388
394
  | `seed` | Command up runs once the stack is healthy, whenever a resettable volume was created since the last successful seed. | table: [`[environment.seed]`](#environmentseed) | | |
@@ -523,6 +529,14 @@ Each section is one TOML table: `[name]` holds one, `[[name]]` repeats. A table
523
529
  | `adopted_on` | Date the file was adopted. | string | | required; format `date`; pattern [P2](#patterns) |
524
530
  | `provenance` | Where the adoption came from; its kind must be declared. | table: [`provenance` shape](#provenance-shape) | | required |
525
531
 
532
+ ### `[docs]`
533
+
534
+ | Key | Meaning | Type | Default | Constraints |
535
+ | --- | --- | --- | --- | --- |
536
+ | `living` | Globs of the Markdown documents that must stay true; docs check reports the paths and make targets they cite that the repository has since removed. | array of string | `[]` | at most 64 items; each item: pattern `^(?!(?:[a-z0-9][a-z0-9-]{0,63}:)?(?:.*\/)?\.\.(?:\/\|$))(?:[a-z0-9][a-z0-9-]{0,63}:)?(?![/])[A-Za-z0-9._@+\-/*?]+$`, at most 1024 characters |
537
+ | `decisions` | Directory of decision records, such as docs/adr. Work orders record their lasting decisions there, and docs check reports duplicate numbers, missing statuses and broken supersedes links. | string | | pattern [P7](#patterns); at most 1024 characters |
538
+ | `decisions_index` | Index file that links every decision record; a record cockpit writes is appended to it, and docs check reports records it omits and links to records that do not exist. | string | | pattern [P7](#patterns); at most 1024 characters |
539
+
526
540
  ## Shapes
527
541
 
528
542
  These tables recur in several places; each place links here instead of repeating the keys.
@@ -558,6 +572,7 @@ Long patterns that several keys share, cited by name in the tables.
558
572
  | P4 | `^[^\x00-\x1f\x7f-\x9f\uD800-\uDFFF]{1,128}(?![\s\S])` |
559
573
  | P5 | `^(?: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-]*))*)?$` |
560
574
  | P6 | `^(?!.*(?:^\|\/)(?:\.git\|internal\|node_modules)(?:\/\|$)).+$` |
575
+ | P7 | `^(?!(?:[a-z0-9][a-z0-9-]{0,63}:)?(?:.*\/)?\.\.?(?:\/\|$))(?:[a-z0-9][a-z0-9-]{0,63}:)?(?![/])[A-Za-z0-9._@+\-/]*[A-Za-z0-9._@+-]$` |
561
576
 
562
577
  ## Checks beyond the schema
563
578
 
@@ -616,6 +631,6 @@ Agent tools load every skill's frontmatter into each session and its entry point
616
631
  | `packages/cockpit/surfaces/skills/cockpit-fix.skill.md` | lines | 12 | `packages/cockpit/surfaces/skills/procedures/fix.md` |
617
632
  | `packages/cockpit/surfaces/skills/cockpit-work.skill.md` | lines | 9 | `packages/cockpit/surfaces/skills/procedures/work.md` |
618
633
 
619
- Each procedure is read on demand and has no size limit: `packages/cockpit/surfaces/skills/procedures/setup.md` (SHA-256 `0ef32e4d7d2304d5f9b150a59e90edbd825159386d89ee0ea19fe5142c06e366`), `packages/cockpit/surfaces/skills/procedures/explain.md` (SHA-256 `dce839b290d2a584fc5592c895c20425414e9201a4c35c2460ff0539d545f2bb`), `packages/cockpit/surfaces/skills/procedures/fix.md` (SHA-256 `a91365d5a79404d506e95a7d7a64fa50460dfc842265d1040402185767f527af`) and `packages/cockpit/surfaces/skills/procedures/work.md` (SHA-256 `b3e6b8de3a249e73e65f84624c991416933086308073ff979f10632aae988791`).
634
+ Each procedure is read on demand and has no size limit: `packages/cockpit/surfaces/skills/procedures/setup.md` (SHA-256 `f8aa06a781db377ce38e34517f64a523f631e9c6122a13073e38cba46f1d7a0e`), `packages/cockpit/surfaces/skills/procedures/explain.md` (SHA-256 `3055cd5929e13266151a1f5657e6ed6a0d9f2a43545770bda5a0dbe6b9a2c0f9`), `packages/cockpit/surfaces/skills/procedures/fix.md` (SHA-256 `ccb7c2e0c568d0a218c1c4bd8cdb31e5fad67e65df5018b73fe71207b0b555aa`) and `packages/cockpit/surfaces/skills/procedures/work.md` (SHA-256 `037ac35ad0c49202a19a6ee7a65104a9ed052917ac4fb3e15d4f49127103ba20`).
620
635
 
621
636
  <!-- cockpit:ref schema=cockpit.guide_cap --> `cockpit.guide_cap` limits always-loaded guidance to 200 lines by default. The measured cost depends on each configuration's sibling guides, so it is not listed here.
@@ -0,0 +1,76 @@
1
+ # Check living documents and decision records
2
+
3
+ `cockpit docs check` reports documents that have drifted from the repositories they describe: a
4
+ living document that still cites a path or `make` target the repository has removed, and a
5
+ decision-record set whose numbers, index, statuses or supersedes links no longer agree. It reads
6
+ files and runs read-only Git; it changes nothing.
7
+
8
+ ## Declare what to check
9
+
10
+ <!-- cockpit:ref schema=docs.living --> List the documents that must stay true under `[docs]` in
11
+ `cockpit.toml`. Each entry is a glob in the cockpit's own repository, or `<sibling slug>:<glob>` in
12
+ a sibling, spelt as a work order's scope is. `decisions` and `decisions_index` are optional and
13
+ name a directory of decision records and the file that links them. Full entry:
14
+ [`[docs]`](configuration-reference.md#docs).
15
+
16
+ ```toml
17
+ [docs]
18
+ living = ["README.md", "AGENTS.md", "docs/**/*.md", "api:README.md"]
19
+ decisions = "docs/adr"
20
+ decisions_index = "docs/adr/README.md"
21
+ ```
22
+
23
+ Leave append-only logs and backlogs out of `living`: they are full of proposals and history, and
24
+ are true as records of their time. Without `[docs]` the command refuses with `DOCS_NOT_DECLARED`
25
+ rather than passing on nothing, and an entry that matches no file is reported as
26
+ `DOCS_DECLARATION_UNMATCHED`.
27
+
28
+ ## Run it
29
+
30
+ ```sh
31
+ npx --no cockpit docs check --config cockpit.toml
32
+ npx --no cockpit docs check --config cockpit.toml --json
33
+ ```
34
+
35
+ It exits 2 when it reports anything, so a CI job runs it the way it runs `work verify`. The guard
36
+ admits it for agents without asking, because it writes nothing. `doctor` names it when `[docs]` is
37
+ declared but does not run it, and `check` does not run it either: both report on the environment
38
+ and its generated files, while this reads every repository's history and judges prose, which is a
39
+ different verdict and a slower one.
40
+
41
+ ## Stale references
42
+
43
+ A path counts when it is an inline code span or a relative link target; spans resolve from the
44
+ repository root, links from the document. A `make` target counts when an inline code span or a
45
+ shell fence runs it. Either is reported only when it existed in the repository's history and does
46
+ not exist now:
47
+
48
+ - `DOCS_REFERENCE_REMOVED`: the path was deleted, or renamed, in which case the message names
49
+ where it went.
50
+ - `DOCS_TARGET_REMOVED`: a Makefile once defined the target and none does now.
51
+
52
+ Keying on history keeps proposals quiet: "add `make park`" names a target that never existed, so
53
+ it is not reported, and no allowlist is needed. A link that never resolved is a link checker's
54
+ job, not this one. npm and pnpm scripts are not checked.
55
+
56
+ ## Decision records
57
+
58
+ The records are the Markdown files directly inside `decisions`, except the index, a `README.md`
59
+ and any file named as a template.
60
+
61
+ | Code | Reported when |
62
+ |---|---|
63
+ | `DECISION_NUMBER_REUSED` | two records share a numeric prefix; dated names such as `2026-09-cache.md` are not numbered |
64
+ | `DECISION_UNINDEXED` | `decisions_index` does not link a record |
65
+ | `DECISION_INDEX_ENTRY_MISSING` | `decisions_index` links a record file that does not exist |
66
+ | `DECISION_STATUS_MISSING` | the status is absent or does not start with proposed, accepted, superseded, deprecated or rejected |
67
+ | `DECISION_LINK_UNRESOLVED` | a "Supersedes" or "Superseded by" names no record |
68
+ | `DECISION_SUPERSEDED_STALE` | an accepted record supersedes another in full, and that one still says accepted |
69
+
70
+ The status is read from `status:` in YAML front matter, a `Status:` line (bold or not), or the
71
+ first line under a `## Status` heading. A supersedes reference is a link, a file name, `ADR-12`,
72
+ `#12`, or a number right after the keyword. "Supersedes 0012" replaces the whole record;
73
+ "supersedes the retry clause of 0012" replaces part of it, so 0012 only has to exist.
74
+
75
+ What this cannot see is a decision that was made and never written down; nothing here makes an
76
+ agent record one.
@@ -34,7 +34,7 @@ input passed validation.
34
34
  | `environment.compose_files` | compose first | the surfaces, plus `check` reads the Compose topology | run the declared Compose files |
35
35
 
36
36
  The runtime commands are `up`, `sleep`, `session`, `down`,
37
- `reset`, `preflight`, `logs` and `runtime measure`. Every mode writes the harness
37
+ `reset`, `preflight`, `logs`, `ps`, `restart`, `rebuild`, `exec` and `runtime measure`. Every mode writes the harness
38
38
  [surfaces](concepts.md#surface) (instructions, skills, guards, permissions, evaluator and work
39
39
  orders) and checks them for [drift](concepts.md#drift). A cockpit that declares only
40
40
  `[environment.machine]` still gets the machine-capacity checks in `preflight`, so it is not refused
@@ -66,12 +66,21 @@ with `COMPOSE_TOPOLOGY_UNAVAILABLE` if Docker cannot produce it. It also checks:
66
66
  `COMPOSE_PORT_ALL_INTERFACES`, because Docker then binds every interface and the service is
67
67
  reachable from the network; write `"127.0.0.1:${API_HOST_PORT}:3000"`, or name `0.0.0.0` when you
68
68
  mean the wider exposure;
69
+ - a service that sets `container_name` fails with `COMPOSE_CONTAINER_NAME_FIXED`, because Docker allows
70
+ one container of a name and the second checkout's stack would fail to start; remove it and address
71
+ the service by its Compose service name, or with `docker compose exec <service>`;
72
+ - a service with `build` and a fixed `image` fails with `COMPOSE_IMAGE_TAG_SHARED`, because every
73
+ checkout builds to the same tag and one checkout's build replaces the image another's stack runs;
74
+ remove `image`, so Compose names the build after the stack's own project;
75
+ - a profile in `environment.profiles` or a `profile:<name>` mount that no service declares fails
76
+ with `COMPOSE_PROFILE_UNDEFINED`, because Compose accepts an unknown profile and starts nothing
77
+ for it;
69
78
  - a service with no Compose healthcheck warns with `COMPOSE_HEALTHCHECK_MISSING`, because running
70
79
  is then treated as ready;
71
80
  - an image referenced by tag rather than digest warns with `COMPOSE_IMAGE_UNPINNED`.
72
81
 
73
82
  `doctor` reports a refusal from this check as itself, with its fix, not as the surface evidence it makes
74
- unavailable. `init` shows the port and healthcheck findings beside the drafted `cockpit.toml`, as
83
+ unavailable. `init` shows the port, container name, shared image tag and healthcheck findings beside the drafted `cockpit.toml`, as
75
84
  warnings carrying the same fix; it never edits a Compose file, so apply the edit before or right after
76
85
  accepting.
77
86
 
@@ -128,6 +137,25 @@ each image by digest when you can. The file is yours from then
128
137
  on: cockpit runs it as written and never rewrites it, and the scaffold refuses with
129
138
  `INIT_SCAFFOLD_COMPOSE_EXISTS` when the cockpit root already holds any Compose file.
130
139
 
140
+ ### Compose profiles
141
+
142
+ A service with `profiles: [workers]` in the Compose file runs only while that profile is active.
143
+ `environment.profiles` lists the profiles every `up` and `session` activates, and
144
+ `up --profile <name>` or `session --profile <name>`, repeated for several, adds more for that run.
145
+ A sibling declared `mount = "profile:<name>"` is mounted, and checked as mounted, exactly while its
146
+ profile is active; the generated agent files follow `environment.profiles`. A profile no service
147
+ declares is refused with `COMPOSE_PROFILE_UNDEFINED`, by `check` for the declared ones and by `up`
148
+ for the requested ones.
149
+
150
+ The stack records the profiles it started with, and every later command on it, `down`, `sleep`,
151
+ `logs`, `preflight`, `ps` and the service verbs included, activates the same set, so `down` removes
152
+ the profile services too. A plain `up` or `session` joins the running stack with its recorded set.
153
+ Adding a profile changes what the stack runs, so `up` refuses it on a running stack with
154
+ `LIFECYCLE_PROGRESS_INVALID`, as it refuses any change to what the stack was started from: run
155
+ `down`, then `up --profile <name>`. `check` judges each service's bind mounts under the default
156
+ set and under the default set plus each other profile, so a bind that only one profile set would
157
+ refuse still fails `check`.
158
+
131
159
  ## Local URLs and port families
132
160
 
133
161
  Write each published port with an explicit loopback binding in your Compose file, as in
@@ -222,6 +250,63 @@ stale key names. Restore the named checkout or bring its instance keys in line w
222
250
  then rerun `cockpit doctor --config cockpit.toml`. When no sibling declares an environment file,
223
251
  the instance-presence and key-freshness checks pass: there is nothing to seed or compare.
224
252
 
253
+ ## Serve a sibling from a worktree
254
+
255
+ The stack mounts each sibling's declared checkout. When you work on a branch in another checkout of
256
+ that repository, usually a linked worktree, point the sibling at it for this cockpit checkout:
257
+
258
+ ```sh
259
+ npx --no cockpit use api /path/to/api/.worktrees/feature --config cockpit.toml
260
+ npx --no cockpit use api --clear --config cockpit.toml
261
+ ```
262
+
263
+ `use` accepts the root of a checkout that shares the declared checkout's object store, or whose
264
+ `origin` names the same repository as the declared checkout or its `remote`; anything else is
265
+ refused with `SIBLING_CHECKOUT_FOREIGN`. Name the checkout's own directory: a path that reaches it
266
+ through a symbolic link is refused. The choice is recorded in `.cockpit/local/sibling-checkouts`,
267
+ never in `cockpit.toml`, so it applies to this checkout of the cockpit alone. `up`, `logs`, the guard's
268
+ allowed roots and protected instance files, `doctor` and `preflight`, work orders (checks, grades,
269
+ test gates and test-weakening detection) and `docs check` all use the recorded checkout, and each
270
+ refuses with `SIBLING_CHECKOUT_UNAVAILABLE` once that checkout is gone. `doctor` and `preflight`
271
+ name each one (`SIBLING_CHECKOUT_OVERRIDDEN`) and warn with
272
+ `SIBLING_ENVIRONMENT_FILE_MISSING` for every declared environment file the worktree lacks: a fresh
273
+ worktree has none of the ignored ones, and cockpit never copies them from another checkout.
274
+
275
+ A running stack keeps the checkout it mounted: run `down` and `up` after `use`. An agent may run
276
+ `use` for a checkout inside a directory it may already write; any other path is a person's call. The
277
+ directory grants `sync` writes for each agent tool are committed and name the declared checkout, so a
278
+ worktree kept inside it stays reachable without a prompt. For a checkout outside it, `use` grants
279
+ the tools that read a machine-local setting, and `use --clear` takes that grant back:
280
+
281
+ - **Claude Code**: `use` adds the checkout to `permissions.additionalDirectories` in
282
+ `.claude/settings.local.json`, keeping everything else in the file, and removes only the entry it
283
+ added. It refuses a file it cannot parse rather than rewrite it, because Claude Code ignores such
284
+ a file entirely.
285
+ - **OpenCode**: `use` writes the checkout to the machine-local grant file `sync` writes for the
286
+ sibling, and `sync` keeps it there.
287
+ - **Codex** has no machine-local setting for extra writable roots, so its sandbox still reaches only
288
+ the declared checkout: start Codex with `--add-dir <checkout>`.
289
+ - **Cursor** and **Grok Build** have no measured machine-local grant, so `use` writes nothing for
290
+ them and they may ask before editing the checkout.
291
+
292
+ `use` lists in its output which tools got the grant, and `--json` reports them as `agentGrants`.
293
+ Restart an agent session that is already running so it reads the new grant.
294
+ [Harness surfaces](harness-surfaces.md#sibling-projection-and-standing-cost) records what was measured.
295
+
296
+ ## Bring checkouts up to date
297
+
298
+ `cockpit pull --config cockpit.toml` fetches and fast-forwards the cockpit and every sibling
299
+ checkout, including one `use` recorded, to the upstream of the branch each has checked out. It
300
+ never merges, rebases, stashes or switches branch, and it runs no Git hooks. A checkout with
301
+ modified tracked files, a branch that has diverged from its upstream, an upstream that is gone or a
302
+ failed fetch is left exactly as it was and reported with `PULL_SKIPPED` and the command that
303
+ resolves it; a detached HEAD or a branch that tracks nothing is listed and skipped without a
304
+ warning. Like `setup`, its Git reads only each repository's own configuration, so a credential
305
+ helper set only in your global Git configuration is not used, and a repository whose attributes name
306
+ a filter defined only there, such as Git LFS, is skipped rather than checked out as placeholder
307
+ files; run `git pull --ff-only` in it yourself. Because it can only fast-forward, an
308
+ agent may run it without asking.
309
+
225
310
  ## Lifecycle and ownership
226
311
 
227
312
  `setup` gets the declared sibling checkouts onto disk and wires them up. `mount` controls how the
@@ -375,6 +460,65 @@ identity, control socket or stop confirmation did not match; cockpit then keeps
375
460
  refuses any overlapping cleanup. Do not remove its state or runtime resources by hand: that
376
461
  destroys the records cockpit needs to repair it safely.
377
462
 
463
+ ### List and prune stacks across the machine
464
+
465
+ Each checkout gets its own stack, port lease and state, so deleting a worktree leaves its containers,
466
+ network, volumes and lease behind with no checkout left to run `down` from. `stacks` lists every
467
+ stack this machine knows about, whichever cockpit and checkout started it, and changes nothing:
468
+
469
+ ```sh
470
+ npx --no cockpit stacks --config cockpit.toml --json
471
+ ```
472
+
473
+ It reads cockpit's state root and the containers, networks and volumes on the local Docker daemon
474
+ that carry cockpit's ownership labels, and attributes a resource to a stack only when all of them
475
+ are present and well formed; nothing is attributed by its name. Each row gives the cockpit, the stack,
476
+ its Compose project, its checkout, the state record and whether this version can read it, running
477
+ and stopped containers, networks, volumes, the port lease it still holds, its last recorded
478
+ activity, and a verdict with the reason.
479
+
480
+ A stack's checkout is proven, never guessed. Compose labels each container with the directory it
481
+ ran from, and the ancestor whose checkout identity derives the stack's own identity is its
482
+ checkout; or the cockpit's main checkout is known and none of the checkouts Git records for it
483
+ derives the stack. `checkout.source` says which. The checkout is `present`, `missing`, `replaced`
484
+ (the path exists but is no longer a checkout of that cockpit) or `unknown`. A worktree whose path
485
+ does not exist while Git still registers it, or marks it locked, is `unknown`, not `missing`: a
486
+ drive or share that is not mounted, or a checkout moved without `git worktree repair`, looks exactly
487
+ like that. Once such a checkout is really gone, `git worktree prune` in its main checkout (after
488
+ `git worktree unlock` for a locked one) lets `stacks prune` remove its stack.
489
+
490
+ A stack is `orphaned` only when its checkout is proven `missing`. Every other stack is kept: one
491
+ whose checkout exists or cannot be found, one that a `down` or `reset` is still draining, the
492
+ current checkout's own, and one whose state this cockpit version cannot read, because a newer
493
+ version may still use it for a checkout that exists. A state folder this version cannot read is
494
+ listed with the stacks; one in the colon spelling an earlier build used is orphaned once none of its
495
+ stacks is kept, and one named as current versions name their state is kept for a version that reads
496
+ it.
497
+
498
+ `stacks prune` shows exactly what it would remove and a digest of it, and removes nothing:
499
+
500
+ ```sh
501
+ npx --no cockpit stacks prune --config cockpit.toml
502
+ npx --no cockpit stacks prune --config cockpit.toml --apply
503
+ ```
504
+
505
+ `--apply` observes the machine again and removes only while the plan still has the previewed digest:
506
+ each orphan's containers, then its networks and labelled volumes, then the state records that hold
507
+ its port lease, then the orphaned state folders. State is removed only while every file still holds
508
+ the bytes the preview read, under the lock `up` takes to lease ports. A step that fails stops the
509
+ prune with `STACKS_PRUNE_INCOMPLETE`; what it had not removed stays listed, and running `--apply`
510
+ again resumes. The result is reported only once a fresh inventory no longer lists what was removed.
511
+
512
+ Removing an orphan is housekeeping, so `--apply` runs for an agent. A prune that deletes volumes
513
+ deletes data, and follows the reset gate: it runs only where `[autonomy] reset` lets the caller
514
+ reset, and otherwise a person runs `stacks prune --interactive` in a terminal and types the
515
+ preview's digest. That gate is the running cockpit's own policy and says nothing for another
516
+ cockpit's, so `--apply` removes only this cockpit's orphans and the state folders an earlier build
517
+ left. The preview still lists every orphan, marks each with `thisCockpit`, and warns with
518
+ `STACKS_PRUNE_UNCONFIRMED` that another cockpit's are removed only by a person's
519
+ `stacks prune --interactive`, which covers the whole machine. `doctor` warns with `STACKS_ORPHANED` when a stack of this cockpit has lost its
520
+ checkout or a state record cannot be read, without asking Docker; `stacks` gives the full picture.
521
+
378
522
  ### Change a running stack
379
523
 
380
524
  A stack's identity, carried in its ownership labels and saved progress, is a digest of the Compose
@@ -390,9 +534,12 @@ receive, gives the stack a new identity, and `up` refuses with `LIFECYCLE_PROGRE
390
534
  running stack in place. To apply such a change, for example a `[ports.bases]` edit:
391
535
 
392
536
  1. Edit `cockpit.toml`. This can happen while the stack runs.
393
- 2. Have a person run `cockpit sync --config cockpit.toml` in a terminal. Until then, the agent
394
- guard holds every tool call, because the configuration no longer matches what it was generated
395
- for, and `sleep` and `down` refuse because they read the Compose files `sync` publishes.
537
+ 2. Run `cockpit sync --config cockpit.toml`. Until then, the agent guard holds every tool call
538
+ except that sync, because the configuration no longer matches what it was generated for, and
539
+ `sleep` and `down` refuse because they read the Compose files `sync` publishes. An agent may run
540
+ it where `[autonomy] sync = "agent"` and the edit does not
541
+ [widen what agents may do](safety-and-autonomy.md#edits-the-guard-has-not-applied), as a
542
+ `[ports.bases]` edit does not; otherwise a person runs it in a terminal.
396
543
  3. Run `cockpit down --config cockpit.toml`. It finds the stack and its port lease by the stack,
397
544
  not by the edited declaration, and removes the containers still running the old declaration.
398
545
  While another holder, such as a running `cockpit session`, still holds the stack, it refuses
@@ -403,15 +550,32 @@ Restoring `cockpit.toml` to the exact bytes `sync` last saw, for example with
403
550
  `git restore cockpit.toml`, clears the guard's hold without a `sync`: the guard compares the file's
404
551
  content, not which file holds it.
405
552
 
553
+ ### When a sibling changes under a running stack
554
+
555
+ A bind mount follows a sibling's files at once, but installed dependencies usually live in an image
556
+ or volume built earlier and the database keeps the schema it was migrated to. When `up` starts a
557
+ stack it records a digest of each mounted sibling's lockfiles and of its `rebuild_inputs`, such as
558
+ a migrations directory. Lockfiles come from the `environment.install_policies` rows for the
559
+ sibling's toolchain, or, without one, from the common lockfile names present in the checkout; each
560
+ finding names which source it came from. `doctor` and `preflight` warn with `STACK_INPUTS_CHANGED`
561
+ when any of them, or the checkout serving the sibling, changed since, and `pull` warns after
562
+ moving one. Run `down` and then `up` so every service starts on the current files; rebuild an image
563
+ that installs the dependencies before `up`. A resumed `up` keeps the record, because resuming
564
+ restarts nothing; `down`, or a `sleep` that stops the stack, drops it.
565
+
566
+ It is a warning, not a refusal: whether a changed lockfile matters is the product's call, and
567
+ `test-run` does not block on it.
568
+
406
569
  ## Choose the Docker daemon
407
570
 
408
571
  Every command uses the daemon Docker itself would select: a `DOCKER_HOST` when set, otherwise the
409
- context `DOCKER_CONTEXT` names, otherwise the active context `docker context show` reports. Three
572
+ context `DOCKER_CONTEXT` names, otherwise the active context `docker context show` reports. Four
410
573
  commands fix that daemon once, before their first step, and address only it:
411
574
 
412
575
  | Command | Why it fixes the daemon |
413
576
  |---|---|
414
577
  | `down`, `reset` | they delete; reading the context per step could list one daemon and delete from another if `docker context use` ran mid-command |
578
+ | `stacks` | `stacks prune` deletes, for the same reason |
415
579
  | `runtime measure` | the measurement must describe the daemon `up` will use, not one selected while the probe ran |
416
580
 
417
581
  None of them needs a prefix, so they run as printed:
@@ -753,6 +917,30 @@ that, `logs` keeps the newest whole records that fit, sets `truncated` to `true`
753
917
  and warns with `LOGS_TRUNCATED`; lower `--tail` to stay under it. Output is returned after
754
918
  collection, including structured records in JSON mode, rather than streamed.
755
919
 
920
+ ### Work on one service
921
+
922
+ `ps`, `restart`, `rebuild` and `exec` act on one service of this checkout's own running stack, with
923
+ its Compose project, files and profiles, so neither a person nor an agent names the derived project.
924
+ The stack must have been started by `up` from this checkout; after `down` they refuse and name `up`.
925
+
926
+ - `ps` lists every service of the stack with its container state, health and status; a service
927
+ with no container is `absent`.
928
+ - `restart --service <name>` restarts the container in place, without its dependents, then waits
929
+ for it as `up` does and reports its last log lines when it does not become healthy.
930
+ - `rebuild --service <name>` builds the service's image, replaces its container and waits the same
931
+ way; use it when a change is baked into the image. It also works on a stack whose start stopped at
932
+ that service, and it records the new container so `preflight` and `logs` follow it.
933
+ - `exec --service <name> -- <command> [args...]` runs the command inside the service's container
934
+ and exits with the command's own status, as `session` does. It gets a terminal only when cockpit
935
+ runs in one.
936
+
937
+ The guard admits these verbs as it admits `up`. The command after `exec --` runs in the container,
938
+ whose files the guard cannot see, so it is never proven read-only: the name-based denials still apply
939
+ (`exec --service web -- cat .env` is refused like `cat .env`), and it runs without asking only when a
940
+ `[guards] allow` rule or a declared build or test command admits it
941
+ ([Cockpit and project commands](safety-and-autonomy.md#cockpit-and-project-commands)). `reset` stays
942
+ gated by `[autonomy]`.
943
+
756
944
  ## Where the decisions live
757
945
 
758
946
  Contributors looking for the source module behind each step should start at
package/docs/faq.md CHANGED
@@ -67,9 +67,11 @@ its declared remote. It never rewrites Git remotes or edits undeclared files.
67
67
 
68
68
  ## Can two agents use the same machine at once?
69
69
 
70
- Yes. Each checkout leases its own port family, and each running `up` or `session` is a holder of
71
- the stack. `sleep` stops the stack only when no holder remains, so one agent cannot stop
72
- another's environment. See [Environment](environment.md#lifecycle-and-ownership).
70
+ Yes. Each checkout, a linked worktree included, leases its own port family and runs its own stack,
71
+ and each running `up` or `session` is a holder of it. `sleep` stops the stack only when no holder
72
+ remains, so one agent cannot stop another's environment. `cockpit use` points a sibling at a worktree
73
+ for one cockpit checkout, and `cockpit stacks prune` removes the stack a deleted worktree left behind.
74
+ See [Environment](environment.md#lifecycle-and-ownership).
73
75
 
74
76
  ## What happens to my secrets?
75
77