@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
@@ -20,9 +20,11 @@ budget: uncapped
20
20
  other user-guide pages cited here sit beside it.
21
21
  - When the guard asks before a command, the person decides in Claude Code; Codex and OpenCode deny
22
22
  instead, so hand the person the exact command to run in a terminal. A refusal that holds every
23
- tool call (a guard message saying so, or `GUARD_AUTHORITY_UNAVAILABLE`) follows any
24
- edit to `cockpit.toml` or reinstall of cockpit or Node, and clears only when a person runs
25
- `./node_modules/.bin/cockpit sync --config cockpit.toml` in a terminal. A refused command is the
23
+ tool call (a guard message saying so, `GUARD_AUTHORITY_UNAVAILABLE` or `GUARD_CONFIG_UNSYNCED`)
24
+ follows any edit to `cockpit.toml` or reinstall of cockpit or Node. `GUARD_CONFIG_UNSYNCED` means
25
+ the edit does not widen what agents may do, so run
26
+ `./node_modules/.bin/cockpit sync --config cockpit.toml` yourself where `[autonomy] sync =
27
+ "agent"`; any other hold clears only when a person runs it in a terminal. A refused command is the
26
28
  person's to run: never reword, wrap or re-spell it to get past the guard.
27
29
  - In Codex's sandbox only `check`, `sync --dry-run` and `--help` work. Every other cockpit command
28
30
  there cannot read cockpit's state or the Docker socket, so a failure it reports is not evidence:
@@ -54,11 +56,13 @@ started it, even where it lives outside this root.
54
56
  2. **Preview.** Run `./node_modules/.bin/cockpit init . --target <tool> --json`, adding
55
57
  `--registry` only when adopting an existing registry. The preview writes nothing. Read
56
58
  `result.stage`, `result.question` and `result.interview.outstanding`: every field the interview
57
- will ask, each with its inferred values and the file each came from. Done when you hold
59
+ will ask, each with its `proposals` (each with `provenance.kind` `derived`, `measured` or
60
+ `inferred`, and the file it came from) and `confirmedBy`. Done when you hold
58
61
  `result.previewSha256` and the outstanding fields.
59
62
  3. **Explore, then ask in one small round.** Read the repositories for each outstanding field
60
- before asking, ask only for what the files and CLI output cannot answer, and present each
61
- inferred value with its source for confirmation. Always settle these with the person:
63
+ before asking, ask only for what the files and CLI output cannot answer. A field with
64
+ `confirmedBy = "agent"` is yours to accept as read (step 4); present every other proposal with
65
+ its source for confirmation. Always settle these with the person:
62
66
  - **The name.** `init` proposes the cockpit root's directory name for `cockpit.name`. It scopes
63
67
  the cockpit's Compose projects, state and generated files, so changing it after the first sync
64
68
  means following the *Rename a cockpit* section of
@@ -73,11 +77,16 @@ started it, even where it lives outside this root.
73
77
  except for a directory name that is not a valid sibling slug, which refuses with
74
78
  `INIT_COCKPIT_ROOT_REQUIRED`.
75
79
  - **The test gates.** For a runnable product, `init` proposes `testing` stages and gates from the
76
- test entry points it finds. Confirm which commands prove a change: the targeted gate agents
77
- iterate with, and the full gate they run before handing back. A new product with no tests needs
78
- the person to choose its test runner first; adding a test framework to a product repository
79
- waits for their explicit yes. Answer `testing = "none"` only when they decide there are no
80
- tests yet; `doctor` then reports `TESTING_GATE_UNDECLARED`.
80
+ test entry points it finds. Whether each proves anything is your judgement, made on evidence:
81
+ name the behaviours its tests exercise, break one of them on purpose, run the proposed command
82
+ and see it go red, then restore the file so the checkout is as you found it. That edit needs no
83
+ yes, because it is undone within the step. Write the behaviours into the gate's `changes` text
84
+ and keep the red run's output for your report; a gate that stays green on the break proves
85
+ nothing about that behaviour, so say so. The person confirms which gate agents iterate with and
86
+ which they run before handing back. A new product with no tests needs the person to choose its
87
+ test runner first; adopting a test framework in a product repository waits for their explicit
88
+ yes. Answer `testing = "none"` only when they decide there are no tests yet; `doctor` then
89
+ reports `TESTING_GATE_UNDECLARED`.
81
90
  - **The non-local hosts** for `guards`: the database and live vendor API hosts of every
82
91
  production, staging or shared environment. Env templates give variable names only; each host
83
92
  comes from the person.
@@ -87,12 +96,15 @@ started it, even where it lives outside this root.
87
96
  "proceed without asking" covers interview answers only. Mark every answer you chose yourself in
88
97
  the file's `[provenance]` table, for example `"environment.machine" = "agent-default"`: init then
89
98
  writes the field under `unconfirmed` in `cockpit.toml` with a comment saying the setup agent
90
- chose it, and `doctor` reports `DECLARATION_UNCONFIRMED` until a person confirms it. An unmarked
91
- answer is recorded as the person's. Done when the file holds every answer and marks each one you
99
+ chose it, and `doctor` reports `DECLARATION_UNCONFIRMED` until it is confirmed (step 7). Mark a
100
+ field with `confirmedBy = "agent"` as `"derived"` instead, with no value needed: init answers it
101
+ with what it read, refuses one that differs (`DOCUMENT_CONFIGURATION_ANSWER_NOT_DERIVED`), and
102
+ records the file it came from. An unmarked answer is recorded as the person's. Done when the file holds every answer and marks each one you
92
103
  chose.
93
104
  5. **Accept.** Show the person the answers file and the preview digest, then rerun with
94
105
  `--accept-preview <previewSha256> --answers <file>`. The run stops at `configuration.defaults`:
95
- once the person has read the draft in `result.question.document`, rerun adding
106
+ once the person has read the values the draft in `result.question.document` lists under
107
+ "A person confirms these" (the digest covers only those), rerun adding
96
108
  `--accept-defaults` with `result.question.expectedSha256`. Each digest binds consent to the bytes
97
109
  the person saw, so take it only from the latest pending run; any other is refused
98
110
  (`INIT_PREVIEW_NOT_ACCEPTED`, `INIT_DEFAULTS_NOT_ACCEPTED`). A different value for an answer
@@ -120,11 +132,12 @@ started it, even where it lives outside this root.
120
132
  refused by the command that needs it), `needs` (why cockpit needs it) and `findings` (the
121
133
  diagnostic, its message and its fix); `noFinding` lists the ones no check reported, which is not
122
134
  proof, because a check that could not run reports nothing. Take the gaps one at a time, required
123
- first: say what is missing, why cockpit needs it, and the exact change you propose. Ask before
124
- touching any product repository; committing, installing cockpit, recording a remote, untracking
125
- a file or adding a test changes it for everyone who works on it. Where a gap needs judgement
126
- (which test runner to adopt, whether the existing tests prove anything, where characterization
127
- tests for untested code should live), propose with what you read and let the person decide.
135
+ first: say what is missing, why cockpit needs it, and the exact change you propose. A change to a
136
+ product repository follows step 8: committing, installing cockpit, recording a remote, untracking
137
+ a file or adding a test changes it for everyone who works on it. Whether the existing tests prove
138
+ anything is yours to judge, as step 3 describes; where a gap needs the person's judgement (which
139
+ test runner to adopt, where characterization tests for untested code should live), propose with
140
+ what you read and let them decide.
128
141
  - The `cockpit-installed` gap clears first: `init` ran from a temporary copy, so run
129
142
  `npm install` in the cockpit root, then ask the person to run
130
143
  `./node_modules/.bin/cockpit sync --config cockpit.toml` in a terminal so the guard hook runs
@@ -135,11 +148,25 @@ started it, even where it lives outside this root.
135
148
  person to run `codex -C <cockpit root>` in a terminal (not `codex exec`), trust the folder if
136
149
  asked, and choose **Trust all and continue** when Codex shows **Hooks need review**. `doctor`
137
150
  reports `CODEX_HOOK_UNTRUSTED` until it is done.
151
+ - `DECLARATION_UNCONFIRMED` lists the answers no person stated. Confirm `ports.bases` (with the
152
+ stack up), `environment.compose_files` and `environment.machine` by observation, one at a time:
153
+ `./node_modules/.bin/cockpit confirm ports.bases --config cockpit.toml --json` runs the
154
+ observation that verifies the answer and, when it passes, removes the entry and records what
155
+ ran. Then run `./node_modules/.bin/cockpit sync --config cockpit.toml` where `[autonomy] sync =
156
+ "agent"`, or hand it to the person, before confirming the next one. A refusal
157
+ (`CONFIRM_OBSERVATION_FAILED`) names what the observation saw: fix that, or the value, and
158
+ confirm again. Never delete an `unconfirmed` entry by hand: `CONFIRM_PERSON_REQUIRED` marks the
159
+ answers only a person confirms (the trust decisions, `cockpit.name`, `estate.runnable`,
160
+ `environment.test_data`), so list them in your report with their values.
138
161
  Done when `doctor` reports no required gap and every other gap is cleared or reported.
139
- 8. **Offer the product changes, one yes each.** "Use sensible defaults" never extends to writing
140
- inside a product repository: an **AGENTS.md** pointer, a Compose file, a `package.json`, a
141
- Dockerfile or a `.env.schema` in a sibling checkout each needs the person's explicit yes to that
142
- exact change, because it changes the product for everyone who works on it.
162
+ 8. **Put product changes where the person reviews them.** A Dockerfile, Compose file or
163
+ `.env.schema` the product needs goes on a new branch in that sibling's checkout: start the branch
164
+ only when `git -C <sibling> status --short` prints nothing, write the files there, and put their
165
+ diff against the starting branch in your report. Nothing is pushed, so the person reviews it
166
+ before it reaches anyone else. Creating a hosted repository or a remote waits for their yes. Every
167
+ other product change (an **AGENTS.md** pointer, a `package.json`, a new test framework) needs the
168
+ person's explicit yes to that exact change, because it changes the product for everyone who works
169
+ on it; "use sensible defaults" never extends to it.
143
170
  - For a dedicated cockpit, offer an instruction pointer for each product repository. If the
144
171
  product has no **AGENTS.md**, show the exact proposed file as a draft; if it has one, show the
145
172
  marked block that would be appended without changing the team's text. After approval, set
@@ -152,10 +179,12 @@ started it, even where it lives outside this root.
152
179
  identities or create browser state.
153
180
  - For environment or secret adoption, follow **Secret handling** after sync has established its
154
181
  owned ignore boundary.
155
- Done when each offer is applied or declined.
182
+ Done when each product file is on its branch with its diff in your report, and each other offer
183
+ is applied or declined.
156
184
 
157
- Report the actual result, every gap still named, and every default you chose, with its field and
158
- value, so the person can confirm or replace each.
185
+ Report the actual result; every gap still named; every default you chose, with its field and
186
+ value, so the person can confirm or replace each; your judgement of each test gate, with its red run;
187
+ and the diff of every product branch.
159
188
 
160
189
  ## Create a local setup
161
190
 
@@ -183,13 +212,16 @@ guesses. So derive each value from what the repository shows, record it as infer
183
212
  answer is retained as a not-declared decision. A true answer is only a requirement: it remains unresolved
184
213
  until product-owned seed operations or browser authentication states are declared, and never proves that
185
214
  data or a login exists.
186
- 5. Decide where the runnable pieces live. A Dockerfile or Compose file written into a product
187
- repository is a product change, so ask the human first and show the exact path and contents.
188
- Without that permission, declare an environment cockpit renders itself and leave the product
189
- untouched. Done when either the human approved that specific file or no product file was written.
215
+ 5. Decide where the runnable pieces live. A Dockerfile or Compose file in the product is a product
216
+ change: write it on a branch in that repository's checkout, as step 8 of **Bootstrap** describes.
217
+ A `compose.yml` at the cockpit root that reaches the checkout through its sibling variable leaves
218
+ the product untouched. Done when each product file is on its branch with its diff in your report,
219
+ or no product file was written.
190
220
  6. Finish the configuration with the init flow in **Bootstrap**. On an existing cockpit, an edit to
191
- `cockpit.toml` makes the guard hold every tool call, so a person runs
192
- `./node_modules/.bin/cockpit sync --config cockpit.toml` in a terminal; then run
221
+ `cockpit.toml` makes the guard hold every tool call until it is synced. When the hold says the
222
+ edit does not widen what agents may do, run
223
+ `./node_modules/.bin/cockpit sync --config cockpit.toml` yourself where `[autonomy] sync =
224
+ "agent"`; when it names fields that widen, a person runs it in a terminal. Then run
193
225
  `./node_modules/.bin/cockpit check --config cockpit.toml --json`. Done when the check exits 0.
194
226
  7. Where a runtime is declared, measure it with
195
227
  `./node_modules/.bin/cockpit runtime measure --config cockpit.toml --image <local-image>`, using an
@@ -235,14 +267,17 @@ report secure agent secret use as unavailable unless a sandbox that has been tes
235
267
  ## Add or remove an agent tool
236
268
 
237
269
  When the team starts or stops using an agent tool, the `tool` command edits only `[surfaces]
238
- tools` in `cockpit.toml`. The guard asks before every `tool` command, the preview included, and
239
- after the edit it holds every tool call until a person syncs.
270
+ tools` in `cockpit.toml`, and after the edit the guard holds every tool call until it is synced.
271
+ Adding a tool does not widen what agents may do, so you may run `tool add`; removing one deletes
272
+ that tool's guard, so the guard asks before `tool remove`, and the hold then names `surfaces.tools`
273
+ and waits for a person.
240
274
 
241
275
  1. Preview with `./node_modules/.bin/cockpit tool add <tool> --config cockpit.toml --dry-run` (or
242
276
  `tool remove`) and show the person the list it prints. Done when they agree to that list.
243
277
  2. Run it without `--dry-run`. Tell the person first that every tool call is held after it. Done
244
278
  when the command exits 0.
245
- 3. The person runs `./node_modules/.bin/cockpit sync --config cockpit.toml` in a terminal: an added
279
+ 3. Sync: after `tool add`, run `./node_modules/.bin/cockpit sync --config cockpit.toml` yourself
280
+ where `[autonomy] sync = "agent"`; after `tool remove`, the person runs it in a terminal. An added
246
281
  tool's files are written from the same sources as the others, and a removed tool's files are
247
282
  deleted as `[autonomy] stale_delete` allows. When sync refuses with
248
283
  `GENERATED_STALE_APPROVAL_REQUIRED`, they rerun it with `--interactive` and type the
@@ -254,7 +289,7 @@ after the edit it holds every tool call until a person syncs.
254
289
  Use this on an installed cockpit when a product gains or drops a repository. The `sibling`
255
290
  command edits `cockpit.toml` so the repository is declared once, with its purpose, instead of
256
291
  reached by path. The guard asks before every `sibling` command, and because the command writes
257
- `cockpit.toml` immediately, the guard then holds every tool call until a person syncs.
292
+ `cockpit.toml` immediately, the guard then holds every tool call until it is synced.
258
293
 
259
294
  1. **Propose the declaration.** Read the repository and ask the person for its purpose when no
260
295
  source states it. Show the human the proposed sibling declaration before invoking the command:
@@ -271,9 +306,10 @@ reached by path. The guard asks before every `sibling` command, and because the
271
306
  which refuses and lists every reference while anything still uses the repository, and never
272
307
  deletes the checkout. The command writes cockpit.toml immediately; `--json` changes only its
273
308
  output format, so it is neither a preview nor an acceptance gate. While the stack is up, a
274
- repository the stack uses is refused until a person runs
309
+ repository the stack uses is refused until the stack is stopped; you may stop it with
275
310
  `./node_modules/.bin/cockpit down --config cockpit.toml`. Done when the command exits 0.
276
- 3. **Sync.** The changed declaration affects the guard, so a human runs
311
+ 3. **Sync.** Adding or removing a repository widens what agents may do (a new repository is a new
312
+ directory they may write), so the hold names the sibling and a person runs
277
313
  `./node_modules/.bin/cockpit sync --config cockpit.toml` in a terminal. Then run
278
314
  `./node_modules/.bin/cockpit check --config cockpit.toml --json`. Done when the check exits 0.
279
315
  4. **Instruction pointer, only on request.** When the person wants the repository's **AGENTS.md**
@@ -347,6 +383,42 @@ never applied silently. Installing a new cockpit also makes the guard hold every
347
383
  5. **Commit together.** Ask the person to commit the lockfile and the regenerated files together.
348
384
  Done when `./node_modules/.bin/cockpit check --config cockpit.toml --json` exits 0.
349
385
 
386
+ ## Keep checkouts and stacks current
387
+
388
+ Each checkout of the cockpit, a linked worktree included, runs its own stack from the sibling
389
+ checkouts it mounts. These commands keep both current; run them yourself, except where a step
390
+ gives one to the person.
391
+
392
+ 1. **Update the checkouts** with `./node_modules/.bin/cockpit pull --config cockpit.toml --json`. It
393
+ only fetches and fast-forwards the cockpit and every sibling. A checkout it skips (`PULL_SKIPPED`:
394
+ modified files, a diverged branch, a failed fetch) stays as it was; report it with the command
395
+ the finding names. Done when every checkout is current or reported.
396
+ 2. **Serve a sibling from a worktree** with
397
+ `./node_modules/.bin/cockpit use sibling-slug /absolute/path/to/worktree --config cockpit.toml`,
398
+ and go back with `use sibling-slug --clear`. The choice holds for this cockpit checkout only, and
399
+ a checkout outside the directories you may already write is the person's to choose. A running
400
+ stack keeps the checkout it mounted, so run `down` and `up` after it. A worktree lacks the
401
+ ignored environment files (`SIBLING_ENVIRONMENT_FILE_MISSING`), and cockpit never copies them:
402
+ ask the person. Done when `doctor` names the checkout under `SIBLING_CHECKOUT_OVERRIDDEN`.
403
+ 3. **A stale stack.** `STACK_INPUTS_CHANGED` from `doctor`, `preflight` or `pull` means a mounted
404
+ sibling's lockfile or declared `rebuild_inputs` changed under the running stack. While the stack
405
+ still runs, rebuild each service whose image installs those dependencies with
406
+ `./node_modules/.bin/cockpit rebuild --config cockpit.toml --service service-id`, then run
407
+ `./node_modules/.bin/cockpit down --config cockpit.toml` and
408
+ `./node_modules/.bin/cockpit up --config cockpit.toml`. When `down` refuses because another
409
+ holder still uses the stack (`CLAIM_CO_TENANT`), leave it and report who holds it. Done when
410
+ `doctor` no longer warns, or the holder is reported.
411
+ 4. **Orphaned stacks.** `STACKS_ORPHANED` from `doctor` means a stack lost its checkout, usually a
412
+ deleted worktree. `./node_modules/.bin/cockpit stacks --config cockpit.toml --json` lists every
413
+ stack with its checkout and verdict; `./node_modules/.bin/cockpit stacks prune --config cockpit.toml`
414
+ previews what would go, and
415
+ `./node_modules/.bin/cockpit stacks prune --config cockpit.toml --apply` removes this cockpit's
416
+ orphans only. A prune that deletes volumes runs only where `[autonomy] reset = "agent"`, and
417
+ another cockpit's orphans need a person: for either, hand the person
418
+ `stacks prune --interactive` for a terminal. A stack whose worktree Git still registers, or marks
419
+ locked, is kept until `git worktree prune` (after `git worktree unlock` for a locked one) runs in
420
+ its main checkout. Done when `stacks` lists no orphaned stack, or the person has the command.
421
+
350
422
  ## Diagnose
351
423
 
352
424
  1. Run `./node_modules/.bin/cockpit doctor --config cockpit.toml --json` first: it reports health,
@@ -355,8 +427,9 @@ never applied silently. Installing a new cockpit also makes the guard hold every
355
427
  pass the blocking gate.
356
428
  2. Follow the fix each diagnostic names, required gaps first. When the fix is a person's step
357
429
  (trusting a Codex hook, signing in to a provider, approving a digest), hand them the exact
358
- command it names. Done when `doctor` reports each gap cleared, or you have reported the ones
359
- only a person can clear.
430
+ command it names. A stale or orphaned stack is cleared by **Keep checkouts and stacks
431
+ current**. Done when `doctor` reports each gap cleared, or you have reported the ones only a
432
+ person can clear.
360
433
 
361
434
  For an account of the result without changing anything, use the cockpit-explain skill.
362
435
 
@@ -20,9 +20,11 @@ budget: uncapped
20
20
  other user-guide pages cited here sit beside it.
21
21
  - When the guard asks before a command, the person decides in Claude Code; Codex and OpenCode deny
22
22
  instead, so hand the person the exact command to run in a terminal. A refusal that holds every
23
- tool call (a guard message saying so, or `GUARD_AUTHORITY_UNAVAILABLE`) follows any
24
- edit to `cockpit.toml` or reinstall of cockpit or Node, and clears only when a person runs
25
- `./node_modules/.bin/cockpit sync --config cockpit.toml` in a terminal. A refused command is the
23
+ tool call (a guard message saying so, `GUARD_AUTHORITY_UNAVAILABLE` or `GUARD_CONFIG_UNSYNCED`)
24
+ follows any edit to `cockpit.toml` or reinstall of cockpit or Node. `GUARD_CONFIG_UNSYNCED` means
25
+ the edit does not widen what agents may do, so run
26
+ `./node_modules/.bin/cockpit sync --config cockpit.toml` yourself where `[autonomy] sync =
27
+ "agent"`; any other hold clears only when a person runs it in a terminal. A refused command is the
26
28
  person's to run: never reword, wrap or re-spell it to get past the guard.
27
29
  - In Codex's sandbox only `check`, `sync --dry-run` and `--help` work. Every other cockpit command
28
30
  there cannot read cockpit's state or the Docker socket, so a failure it reports is not evidence:
@@ -62,12 +64,24 @@ not the thinking: reuse the planning skills the harness already has.
62
64
  run the same command with `--interactive` in a terminal. Never type the digest yourself. Past
63
65
  `work.wip_cap` it refuses until an open order closes. Done when `work status` reports it accepted.
64
66
  3. **Work test-first inside scope.** Write the failing test for a criterion, then the code, changing
65
- only what `scope` names. If the work needs more, edit the order and run `work accept` again to
66
- accept the amendment; dropping or rewriting an accepted criterion always needs a person. When you
67
+ only what `scope` names; a file outside it that the change needs (a lockfile, a regenerated
68
+ reference, a changeset) is judged at grading, so change nothing else. If the work needs more, edit
69
+ the order and run `work accept` again to accept the amendment: dropping a criterion or gate always
70
+ needs a person, a rewritten criterion or widened scope needs one under `checks` grading, and
71
+ otherwise the next grade judges whether your amendment lowered the bar. When you
67
72
  need a person's input, run
68
73
  `./node_modules/.bin/cockpit work note --config cockpit.toml --work-order WO-001 --ask --text "<question>"`
69
74
  and stop: the order is blocked until it is answered with `work answer`, which under `answer =
70
- "person"` only a person can run. Done when every criterion has code and a test that passes.
75
+ "person"` only a person can run. When `work accept` or `work status` lists `relatedDecisions`,
76
+ read those decision records before changing the code they name. When the work makes a lasting
77
+ decision (a format, a boundary, a dependency, an option rejected), record it with
78
+ `./node_modules/.bin/cockpit work note --config cockpit.toml --work-order WO-001 --decision --text "<title>"`
79
+ and resolve it with `work decide --decision <n> --record` (adding `--supersedes <number>` when it
80
+ replaces an older record), then replace every placeholder in the record it writes;
81
+ `--record-file <path>` cites a record that already exists, and `--none --reason "<why>"` resolves
82
+ one that turned out not to last. Update the documentation that describes behaviour you change.
83
+ This needs `[docs] decisions` in `cockpit.toml`, and nothing enforces it under
84
+ `[work] grading = "checks"`. Done when every criterion has code and a test that passes.
71
85
  4. **Check** with `./node_modules/.bin/cockpit work check --config cockpit.toml --work-order WO-001 --json`.
72
86
  It runs every criterion's check and the order's gates; a failure (`WORK_CHECK_FAILED`) returns
73
87
  each result's outcome and the end of its output under `result.results`. Fix and rerun. While
@@ -76,8 +90,11 @@ not the thinking: reuse the planning skills the harness already has.
76
90
  faster feedback. Done when `work check` exits 0.
77
91
  5. **Before grading, review.** Run the harness's installed simplification and code-review skills,
78
92
  with security emphasis when the change touches authentication, secrets, guards or reach to
79
- non-local hosts. Fix their blocking findings and rerun `work check`. Done when no blocking
80
- finding is open and `work check` still exits 0.
93
+ non-local hosts. Fix their blocking findings and rerun `work check`. Where `cockpit.toml` declares
94
+ `[docs]`, also run `./node_modules/.bin/cockpit docs check --config cockpit.toml --json` and fix
95
+ each finding your change caused: a living document citing a path or `make` target you removed, or
96
+ a decision record out of step with its index. Done when no blocking finding is open, `work check`
97
+ still exits 0 and `docs check` reports nothing your change caused.
81
98
  6. **Grade** with `./node_modules/.bin/cockpit work grade --config cockpit.toml --work-order WO-001 --json`.
82
99
  Under the default `independent` grading a fresh read-only evaluator grades each criterion, in
83
100
  another listed agent tool when there is one; never grade your own work. When no evaluator can run
@@ -85,21 +102,33 @@ not the thinking: reuse the planning skills the harness already has.
85
102
  rate-limited or timed out), the refusal names each tool's cause and the command that fixes it:
86
103
  report that to the person instead of retrying. A warning
87
104
  `EVALUATOR_FELL_BACK_TO_RUNNING_TOOL` means the tool doing the work graded it; pass it on. Under
88
- `checks`, the checks decide. Under `self`, pass `--verdict met` or `unmet` and a `--note` saying
89
- what you checked; the checks still run and a failed one fails the grade. Anything short of
90
- passing (`WORK_GRADE_UNSATISFIED`) lists each criterion's verdict and note under
91
- `result.criteria`, failed checks under `result.checks` and changes outside scope under
92
- `result.outOfScope`: go back to step 3 for each. When the person names a grader ("use Codex to
105
+ `checks`, the checks decide, and any change outside scope fails. Under `self`, pass
106
+ `--verdict met` or `unmet` and a `--note` saying what you checked, naming each path in
107
+ `result.outOfScope` and each flagged test file with why its change is needed; the checks still run
108
+ and a failed one fails the grade. Cockpit adds standing criteria for changes outside scope
109
+ (`scope-changes-necessary`), flagged test changes (`test-changes-justified`) and your amendments
110
+ (`amendments-hold-bar`), and with `[docs]` declared for recorded decisions
111
+ (`decisions-recorded`) and updated documentation (`docs-updated`). Anything short of passing
112
+ (`WORK_GRADE_UNSATISFIED`) lists each criterion's verdict and note under `result.criteria` and
113
+ failed checks under `result.checks`: go back to step 3 for each, reverting a change outside scope
114
+ or a test change the grade calls unneeded. `WORK_TEST_WEAKENED` means a test change was not accepted: restore the test, or under
115
+ `checks` grading acknowledge a legitimate change with `work acknowledge --note <why>`. When
116
+ `amendments-hold-bar` is unmet, the next amendment is a person's: report it. When the person names a grader ("use Codex to
93
117
  grade", "use Claude for everything"), pass `--evaluator <tool>` (`codexcli`, `claudecode` or
94
118
  `opencode`) on every grade for the rest of the session; only that tool runs, with no fallback.
95
119
  Done when the grade passes.
96
120
  7. **Attempt cap.** Each failed check or grade counts an attempt; at `work.attempt_cap` the order is
97
- blocked (the refusal names the cap). Record the root cause with `work note`, then report to the
98
- person, who amends the contract or closes the order. Done when the person has the cause and the order's state.
121
+ blocked. Record the root cause with `work note`, then do what the refusal names: close it with
122
+ `work signoff --partial` or `--abandon`, or amend the contract, yourself where `[work.gates]` gives
123
+ that step to the agent, and otherwise hand the person the command. Done when the order is closed or
124
+ amended, or the person has the cause and the command.
99
125
  8. **Close** with `./node_modules/.bin/cockpit work signoff --config cockpit.toml --work-order WO-001`
100
126
  once graded; under `signoff = "person"` it answers `WORK_PERSON_REQUIRED` as step 2 describes.
127
+ It refuses while a recorded decision is unresolved or its record still holds placeholders.
101
128
  An order that cannot be finished closes with `--partial --note <what is left>` or
102
- `--abandon --note <why>`. Done when `work status` names how it closed.
129
+ `--abandon --note <why>`. A command refused because another holds the order's lock: when that
130
+ command crashed, run `work recover --work-order WO-001 --apply`, which removes the lock only once it
131
+ has shown the holder gone and otherwise names what it could not check. Done when `work status` names how it closed.
103
132
 
104
133
  Report each criterion's verdict and note, how the order closed (`work status` names it), and any
105
134
  step you could not run.