@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.
- package/CHANGELOG.md +99 -0
- package/README.md +3 -0
- package/cockpit.schema.json +73 -3
- package/dist/autonomy.d.ts +3 -2
- package/dist/autonomy.js +30 -13
- package/dist/browser/commands.d.ts +57 -2
- package/dist/browser/commands.js +114 -10
- package/dist/browser/runtime.d.ts +1 -0
- package/dist/browser/runtime.js +4 -1
- package/dist/browser/surfaces.d.ts +7 -7
- package/dist/browser/surfaces.js +5 -0
- package/dist/canonical-json.d.ts +2 -0
- package/dist/canonical-json.js +5 -0
- package/dist/cli-main.d.ts +40 -3
- package/dist/cli-main.js +241 -62
- package/dist/command-table.d.ts +19 -11
- package/dist/command-table.js +190 -38
- package/dist/config/load.d.ts +16 -4
- package/dist/config/load.js +25 -3
- package/dist/config/unconfirmed-toml.d.ts +9 -0
- package/dist/config/unconfirmed-toml.js +29 -0
- package/dist/diagnostics.js +10 -1
- package/dist/docs/check.d.ts +16 -0
- package/dist/docs/check.js +197 -0
- package/dist/docs/decision-record.d.ts +34 -0
- package/dist/docs/decision-record.js +135 -0
- package/dist/docs/decisions.d.ts +16 -0
- package/dist/docs/decisions.js +103 -0
- package/dist/docs/markdown.d.ts +36 -0
- package/dist/docs/markdown.js +88 -0
- package/dist/docs/references.d.ts +32 -0
- package/dist/docs/references.js +148 -0
- package/dist/environment/application/confirm.d.ts +35 -0
- package/dist/environment/application/confirm.js +122 -0
- package/dist/environment/application/destructive.js +6 -2
- package/dist/environment/application/doctor.d.ts +12 -7
- package/dist/environment/application/doctor.js +20 -8
- package/dist/environment/application/guard.d.ts +12 -6
- package/dist/environment/application/guard.js +87 -32
- package/dist/environment/application/health.d.ts +14 -5
- package/dist/environment/application/health.js +8 -2
- package/dist/environment/application/lifecycle-context.d.ts +10 -3
- package/dist/environment/application/lifecycle-state.js +4 -3
- package/dist/environment/application/lifecycle.d.ts +2 -1
- package/dist/environment/application/lifecycle.js +11 -3
- package/dist/environment/application/services.d.ts +60 -0
- package/dist/environment/application/services.js +89 -0
- package/dist/environment/application/siblings.d.ts +43 -0
- package/dist/environment/application/siblings.js +269 -0
- package/dist/environment/claims.d.ts +10 -10
- package/dist/environment/claims.js +3 -11
- package/dist/environment/compose-topology.d.ts +15 -7
- package/dist/environment/compose-topology.js +100 -23
- package/dist/environment/contract.d.ts +42 -9
- package/dist/environment/contract.js +33 -0
- package/dist/environment/executable.d.ts +12 -0
- package/dist/environment/executable.js +46 -23
- package/dist/environment/generated-application/check.js +2 -0
- package/dist/environment/generated-application/prepare.js +2 -0
- package/dist/environment/generated-application/shared.d.ts +10 -2
- package/dist/environment/generated-application/shared.js +6 -1
- package/dist/environment/generated-application/surface-outputs.js +23 -12
- package/dist/environment/generated-application/surfaces.js +16 -11
- package/dist/environment/generated-application/sync.js +19 -4
- package/dist/environment/git-observation.d.ts +25 -6
- package/dist/environment/git-observation.js +37 -28
- package/dist/environment/health-composition.d.ts +3 -2
- package/dist/environment/health-composition.js +19 -2
- package/dist/environment/init-application.d.ts +39 -14
- package/dist/environment/init-application.js +39 -10
- package/dist/environment/lifecycle-composition.d.ts +4 -2
- package/dist/environment/lifecycle-composition.js +84 -17
- package/dist/environment/lifecycle-stage.d.ts +8 -3
- package/dist/environment/lifecycle-stage.js +11 -1
- package/dist/environment/logs.d.ts +1 -1
- package/dist/environment/map-limit.d.ts +2 -0
- package/dist/environment/map-limit.js +13 -0
- package/dist/environment/mcp-observation.d.ts +9 -0
- package/dist/environment/mcp-observation.js +46 -0
- package/dist/environment/observations.d.ts +1 -1
- package/dist/environment/observations.js +2 -0
- package/dist/environment/operator-application.d.ts +35 -6
- package/dist/environment/operator-application.js +42 -0
- package/dist/environment/presence.d.ts +4 -0
- package/dist/environment/presence.js +26 -0
- package/dist/environment/read-composition.d.ts +8 -3
- package/dist/environment/read-composition.js +53 -8
- package/dist/environment/readiness-composition.d.ts +20 -1
- package/dist/environment/readiness-composition.js +23 -2
- package/dist/environment/reclaim.d.ts +56 -19
- package/dist/environment/reclaim.js +147 -42
- package/dist/environment/runtime.d.ts +64 -18
- package/dist/environment/runtime.js +73 -3
- package/dist/environment/served-checkout-grants.d.ts +53 -0
- package/dist/environment/served-checkout-grants.js +182 -0
- package/dist/environment/sibling-checkouts.d.ts +119 -0
- package/dist/environment/sibling-checkouts.js +254 -0
- package/dist/environment/sibling-observation.d.ts +27 -0
- package/dist/environment/sibling-observation.js +45 -0
- package/dist/environment/sibling-pull.d.ts +23 -0
- package/dist/environment/sibling-pull.js +95 -0
- package/dist/environment/stack-inputs.d.ts +18 -0
- package/dist/environment/stack-inputs.js +210 -0
- package/dist/environment/stack-inventory-prune.d.ts +31 -0
- package/dist/environment/stack-inventory-prune.js +129 -0
- package/dist/environment/stack-inventory-report.d.ts +44 -0
- package/dist/environment/stack-inventory-report.js +78 -0
- package/dist/environment/stack-inventory.d.ts +94 -0
- package/dist/environment/stack-inventory.js +418 -0
- package/dist/environment/state.d.ts +48 -9
- package/dist/environment/state.js +142 -2
- package/dist/environment/tool-registration.js +3 -7
- package/dist/environment-exec/execute.d.ts +6 -3
- package/dist/environment-exec/execute.js +4 -0
- package/dist/fix-catalogue.d.ts +1 -1
- package/dist/generated-environment/adopt.js +4 -8
- package/dist/guards/answer-confirmation.d.ts +41 -0
- package/dist/guards/answer-confirmation.js +109 -0
- package/dist/guards/evaluator.d.ts +20 -3
- package/dist/guards/evaluator.js +39 -7
- package/dist/guards/local-identity.d.ts +6 -2
- package/dist/guards/local-identity.js +10 -4
- package/dist/guards/policy-change.d.ts +43 -0
- package/dist/guards/policy-change.js +159 -0
- package/dist/guards/policy-pin.d.ts +1 -1
- package/dist/guards/policy-pin.js +14 -12
- package/dist/init/command.d.ts +4 -3
- package/dist/init/command.js +36 -16
- package/dist/init/derive.d.ts +8 -6
- package/dist/init/derive.js +140 -36
- package/dist/init/draft.d.ts +13 -11
- package/dist/init/draft.js +54 -31
- package/dist/init/render.d.ts +18 -6
- package/dist/init/render.js +31 -9
- package/dist/repository-path.d.ts +9 -0
- package/dist/repository-path.js +16 -0
- package/dist/schema.d.ts +42 -75
- package/dist/schema.js +62 -11
- package/dist/surfaces/harness-registry.d.ts +80 -0
- package/dist/surfaces/harness-registry.js +29 -0
- package/dist/surfaces/mcp.d.ts +67 -17
- package/dist/surfaces/mcp.js +194 -31
- package/dist/surfaces/projection.d.ts +7 -7
- package/dist/surfaces/projection.js +41 -6
- package/dist/surfaces/render.d.ts +5 -44
- package/dist/surfaces/render.js +5 -2
- package/dist/team-metadata.js +2 -1
- package/dist/testing/test-protection.d.ts +34 -0
- package/dist/testing/test-protection.js +137 -0
- package/dist/testing/weakening.d.ts +15 -0
- package/dist/testing/weakening.js +30 -0
- package/dist/work-orders/application-closure.d.ts +7 -0
- package/dist/work-orders/application-closure.js +76 -0
- package/dist/work-orders/application-context.d.ts +162 -0
- package/dist/work-orders/application-context.js +137 -0
- package/dist/work-orders/application-decisions.d.ts +27 -0
- package/dist/work-orders/application-decisions.js +121 -0
- package/dist/work-orders/application-grading.d.ts +11 -0
- package/dist/work-orders/application-grading.js +212 -0
- package/dist/work-orders/application.d.ts +4 -97
- package/dist/work-orders/application.js +94 -254
- package/dist/work-orders/composition.d.ts +35 -58
- package/dist/work-orders/composition.js +216 -24
- package/dist/work-orders/contract.d.ts +22 -6
- package/dist/work-orders/contract.js +34 -16
- package/dist/work-orders/decisions.d.ts +23 -0
- package/dist/work-orders/decisions.js +55 -0
- package/dist/work-orders/store.d.ts +54 -5
- package/dist/work-orders/store.js +118 -24
- package/docs/README.md +6 -3
- package/docs/capability-matrix.md +17 -9
- package/docs/cli-reference.md +209 -1
- package/docs/command-list.md +12 -1
- package/docs/concepts.md +6 -4
- package/docs/configuration-essentials.md +7 -2
- package/docs/configuration-reference.md +18 -3
- package/docs/docs-check.md +76 -0
- package/docs/environment.md +194 -6
- package/docs/faq.md +5 -3
- package/docs/getting-started.md +109 -25
- package/docs/harness-surfaces.md +69 -2
- package/docs/safety-and-autonomy.md +56 -12
- package/docs/troubleshooting.md +29 -8
- package/docs/tutorial.md +3 -2
- package/docs/work-and-browser.md +180 -14
- package/libexec/browser-operation.cjs +86 -2
- package/package.json +2 -2
- package/surfaces/skills/cockpit-browser.skill.md +7 -2
- package/surfaces/skills/cockpit-explain.skill.md +1 -1
- package/surfaces/skills/cockpit-fix.skill.md +1 -1
- package/surfaces/skills/cockpit-setup.skill.md +3 -3
- package/surfaces/skills/cockpit-work.skill.md +1 -1
- package/surfaces/skills/procedures/explain.md +9 -4
- package/surfaces/skills/procedures/fix.md +25 -11
- package/surfaces/skills/procedures/setup.md +113 -40
- package/surfaces/skills/procedures/work.md +45 -16
package/docs/getting-started.md
CHANGED
|
@@ -32,6 +32,10 @@ npm install --save-dev --save-exact @b00dea/cockpit
|
|
|
32
32
|
npx --no cockpit init . --target claudecode
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
With pnpm or yarn, install with `pnpm add -D -E @b00dea/cockpit` or `yarn add -D -E @b00dea/cockpit`
|
|
36
|
+
and run `pnpm exec cockpit` or `yarn cockpit` wherever this guide runs cockpit through `npx --no`. `init`
|
|
37
|
+
detects `pnpm-lock.yaml` or `yarn.lock` and writes the matching commands into what it proposes.
|
|
38
|
+
|
|
35
39
|
Replace `claudecode` with `codexcli` or `opencode` for those tools, or list several, yours first
|
|
36
40
|
(`--target claudecode,opencode`). `init` records them as `[surfaces] tools` and installs the
|
|
37
41
|
`cockpit-setup` skill for each listed tool. The default tools are `claudecode`, `codexcli` and
|
|
@@ -90,25 +94,40 @@ same procedure.
|
|
|
90
94
|
A clean-looking configuration with invented values in it is the failure cockpit exists to prevent.
|
|
91
95
|
The agent follows these rules for the whole setup:
|
|
92
96
|
|
|
93
|
-
1. **Ask the human first, and wait for a yes,** before
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
approves or runs staging and the commit of the cockpit: the agent hands them the command.
|
|
97
|
+
1. **Ask the human first, and wait for a yes,** before creating a Git remote or hosted repository,
|
|
98
|
+
running a destructive command (`reset`, `sync --interactive` removals, deleting files), running
|
|
99
|
+
`cockpit sync --adopt`, accepting an `init` digest, or changing a product repository in any other
|
|
100
|
+
way than the next sentences allow (adopting a test framework or a dependency, for example). A
|
|
101
|
+
person approves or runs staging and the commit of the cockpit: the agent hands them the command.
|
|
102
|
+
A Dockerfile, Compose file or `.env.schema` the product needs goes on a new branch in that
|
|
103
|
+
sibling's checkout, started with no uncommitted changes, and the hand-back shows its diff against
|
|
104
|
+
the branch it started from. Nothing is pushed, so the person reviews it before it reaches anyone
|
|
105
|
+
else.
|
|
98
106
|
2. **Show the exact preview before asking:** the `sync --dry-run` listing, the `init` preview with its
|
|
99
107
|
`previewSha256`, the answers file or the defaults digest. Consent binds to those bytes, and a
|
|
100
108
|
digest from anything but the latest pending run is refused.
|
|
101
109
|
3. **Never invent a configuration value.** A port, image, command, health check, purpose or name
|
|
102
110
|
comes from a file the agent read or from the human; otherwise it leaves a named gap and asks.
|
|
103
|
-
4. **
|
|
104
|
-
|
|
111
|
+
4. **Only what init read exactly is the agent's to accept.** `init` labels each proposal with
|
|
112
|
+
`provenance.kind`: `derived` (the complete answer, read from the named file and line),
|
|
113
|
+
`measured` (observed on this machine) or `inferred` (a hint or guess). A field whose
|
|
114
|
+
`confirmedBy` is `"agent"` may be answered with `"derived"` (below); `init` checks the value
|
|
115
|
+
against what it read, and bring-up proves it. Every other field, and every security boundary
|
|
116
|
+
(the `guards` hosts, protected branches, guard and MCP allow-lists), becomes an answer only on the
|
|
117
|
+
human's word.
|
|
105
118
|
5. **Ask for every non-local host.** The `guards` answer lists the database and live vendor API hosts
|
|
106
119
|
of production, staging and shared environments. Variable names come from env templates, never
|
|
107
120
|
values; each host comes from the human.
|
|
108
121
|
6. **Defaults never reach into a product repository.** "Use sensible defaults" covers `init` answers
|
|
109
|
-
only. A pointer in a sibling's **AGENTS.md
|
|
110
|
-
explicit yes to that exact change
|
|
111
|
-
(below), and its report ends with each
|
|
122
|
+
only. A pointer in a sibling's **AGENTS.md** or a change to its `package.json` still needs an
|
|
123
|
+
explicit yes to that exact change, and a product file goes on a branch as rule 1 says. Every
|
|
124
|
+
answer the agent chose itself is marked `"agent-default"` (below), and its report ends with each
|
|
125
|
+
default, its field and its value.
|
|
126
|
+
7. **Confirm a default only by observing it.** The agent clears an `unconfirmed` entry only with
|
|
127
|
+
`cockpit confirm`, which runs the observation that verifies that answer on this machine and
|
|
128
|
+
records it. The trust decisions (`guards`, `testing`, `environment.install_policies`, `sibling`,
|
|
129
|
+
`environment.posture`) and the answers no observation settles (`cockpit.name`, `estate.runnable`,
|
|
130
|
+
`environment.test_data`) stay a person's (below).
|
|
112
131
|
|
|
113
132
|
These rules are instructions, not enforcement. The guard cockpit installs later blocks some commands;
|
|
114
133
|
see [Safety and autonomy](safety-and-autonomy.md).
|
|
@@ -135,9 +154,48 @@ guards = "agent-default"
|
|
|
135
154
|
```
|
|
136
155
|
|
|
137
156
|
Each such field is written under `unconfirmed` at the top of `cockpit.toml`, listed in
|
|
138
|
-
`result.unconfirmed`, and reported by `doctor` as `DECLARATION_UNCONFIRMED` until
|
|
139
|
-
the
|
|
140
|
-
|
|
157
|
+
`result.unconfirmed`, and reported by `doctor` as `DECLARATION_UNCONFIRMED` until it is confirmed. An
|
|
158
|
+
`environment.machine` floor the file does not attribute is recorded as unattributed, because no file
|
|
159
|
+
records its free disk or cold start time.
|
|
160
|
+
|
|
161
|
+
Three answers are facts about this machine and the running product, so an agent confirms them by
|
|
162
|
+
observation, one at a time:
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
./node_modules/.bin/cockpit confirm ports.bases --config cockpit.toml --json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
| Answer | The observation that confirms it |
|
|
169
|
+
|---|---|
|
|
170
|
+
| `ports.bases` | `preflight` passes with the stack up and its port family leased on the declared bases |
|
|
171
|
+
| `environment.compose_files` | `check` passes, which parses the Compose files and resolves the stack's topology |
|
|
172
|
+
| `environment.machine` | the runtime measured on this machine meets the declared memory, CPU and free-disk floor |
|
|
173
|
+
|
|
174
|
+
When the observation passes, `confirm` removes that one entry from `unconfirmed` (comments and every
|
|
175
|
+
other byte stay) and records what ran, when, its result and an evidence digest in
|
|
176
|
+
`.cockpit/local/answer-confirmations`. That file is machine-local and ignored, because the evidence is
|
|
177
|
+
about this machine, and the guard denies agent writes to it. The guard treats the removed entry as
|
|
178
|
+
non-widening only while that record matches the configuration on disk, so the agent's own sync
|
|
179
|
+
applies it where `[autonomy] sync = "agent"`; any other edit, or a clone without the record, leaves
|
|
180
|
+
it to a person. A failed observation is refused with `CONFIRM_OBSERVATION_FAILED` beside the
|
|
181
|
+
diagnostics that explain it.
|
|
182
|
+
|
|
183
|
+
Every other answer is refused with `CONFIRM_PERSON_REQUIRED`: the trust decisions, and
|
|
184
|
+
`cockpit.name`, `estate.runnable` and `environment.test_data`, which state what the owner wants rather
|
|
185
|
+
than anything a machine can show. A person confirms the value with whoever owns the product, corrects
|
|
186
|
+
it if it is wrong, deletes its `unconfirmed` entry and runs `cockpit sync` in a terminal.
|
|
187
|
+
|
|
188
|
+
A field whose `interview.outstanding` entry says `confirmedBy = "agent"` can instead be marked
|
|
189
|
+
`"derived"`, with or without a value: `init` answers it with the value it read, refuses
|
|
190
|
+
(`DOCUMENT_CONFIGURATION_ANSWER_NOT_DERIVED`) a value that differs or a field it read no complete value
|
|
191
|
+
for, and writes a `# Derived:` comment naming the source instead of an `unconfirmed` entry:
|
|
192
|
+
|
|
193
|
+
```toml
|
|
194
|
+
[provenance]
|
|
195
|
+
"cockpit.name" = "derived"
|
|
196
|
+
"ports.bases" = "derived"
|
|
197
|
+
"environment.compose_files" = "derived"
|
|
198
|
+
```
|
|
141
199
|
|
|
142
200
|
### Walk through readiness
|
|
143
201
|
|
|
@@ -147,9 +205,18 @@ has an `id`, a `level` (a `required` gap is refused by the command that needs it
|
|
|
147
205
|
warns), `needs` (why cockpit needs it) and `findings` (each diagnostic with its message and fix).
|
|
148
206
|
`noFinding` lists the prerequisites no check reported; a check that could not run reports nothing, so
|
|
149
207
|
it is not proof. Take the gaps one at a time, required first: what is missing, why, and the exact change
|
|
150
|
-
you propose.
|
|
151
|
-
|
|
152
|
-
|
|
208
|
+
you propose.
|
|
209
|
+
|
|
210
|
+
Whether the existing tests prove anything is the agent's judgement, made on evidence. For each
|
|
211
|
+
proposed gate, name the behaviours its tests exercise, then break one of them on purpose, run the
|
|
212
|
+
gate, watch it go red, and restore the file so the checkout is as it was found; that edit needs no
|
|
213
|
+
yes, because it is undone before the step ends. Write the behaviours into the gate's `changes` text
|
|
214
|
+
and report the judgement, with the red run's output, in the hand-back. A gate that stays green on the
|
|
215
|
+
break proves nothing about that behaviour, and the report says so. Adopting a new test framework in a
|
|
216
|
+
product repository stays the human's call.
|
|
217
|
+
|
|
218
|
+
The cockpit directory must be a Git working tree, committed and clean, before `preflight` passes; a
|
|
219
|
+
new one reports `GIT_STATE_UNHEALTHY` until a person stages and commits it.
|
|
153
220
|
|
|
154
221
|
## The init interview
|
|
155
222
|
|
|
@@ -178,14 +245,22 @@ depends on what it finds:
|
|
|
178
245
|
`mount = "none"`).
|
|
179
246
|
- **A declared runtime** adds questions about the machine floor and posture the product needs.
|
|
180
247
|
|
|
181
|
-
|
|
248
|
+
Each outstanding field lists its `proposals`, and `confirmedBy` says who settles it: `"agent"` when a
|
|
249
|
+
`derived` proposal answers the whole field (today `cockpit.name`, `ports.bases` and
|
|
250
|
+
`environment.compose_files`, when the files leave no gap), `"person"` otherwise. A source `init`
|
|
251
|
+
could not read, or two that disagree, such as a host port with no default or a memory limit set twice
|
|
252
|
+
with different values, leaves the field to the person. Proposals come only from exact sources: a Dockerfile's `EXPOSE`, `CMD` and `ENTRYPOINT`, a
|
|
182
253
|
`package.json` `start`, `serve` or `dev` script, the `node` toolchain a lockfile names, each
|
|
183
254
|
repository's `origin` remote (a URL carrying credentials is skipped, never shown), variable names
|
|
184
255
|
(never values) in env templates such as `.env.example`, an existing Compose file, the `services:` of
|
|
185
256
|
GitHub workflows, and test entry points such as a Makefile `test` target, a `package.json` test script
|
|
186
257
|
or `go.mod`. A name that suggests a database or vendor endpoint, such as `DATABASE_URL`, becomes a
|
|
187
|
-
`guards` question about its host.
|
|
188
|
-
`
|
|
258
|
+
`guards` question about its host. For the machine floor, `init` sums the memory and CPU limits of the
|
|
259
|
+
services the Compose file starts by default (`deploy.resources.limits` or `mem_limit` and `cpus`,
|
|
260
|
+
times their replicas), and where no limit records one it measures this machine's container runtime
|
|
261
|
+
(`measured`, which refuses a smaller machine until someone lowers it). Free disk and the cold start
|
|
262
|
+
time have no source and are never proposed. Sources `init` could not use, including a runtime it
|
|
263
|
+
could not measure, are listed in `interview.inferenceSkipped`.
|
|
189
264
|
|
|
190
265
|
### Without a terminal
|
|
191
266
|
|
|
@@ -193,12 +268,15 @@ An agent or CI job has no terminal, so `--interactive` refuses with `INIT_TERMIN
|
|
|
193
268
|
consent and answers as arguments instead; there is no blanket `--yes`.
|
|
194
269
|
|
|
195
270
|
1. Run the `--json` preview. It returns the `previewSha256` and, under `interview.outstanding`, every
|
|
196
|
-
field the interview will still ask, in order, each with a `why
|
|
271
|
+
field the interview will still ask, in order, each with a `why`, its `proposals` and `confirmedBy`.
|
|
197
272
|
2. Write the answers as TOML keyed by field, and show them to the human with the digest.
|
|
198
273
|
3. Rerun with `--accept-preview <previewSha256>` and `--answers <file>`. The run stops at the first
|
|
199
274
|
unanswered field, or at `configuration.defaults`, where `result.question.document` is the review
|
|
200
|
-
draft (an array of lines)
|
|
201
|
-
the
|
|
275
|
+
draft (an array of lines). Its provenance comments split the surfaced defaults in two: schema
|
|
276
|
+
defaults and the cockpit's own layout, which the agent accepts, and the security boundaries
|
|
277
|
+
(protected branches, guard allow and deny lists, approved MCP servers, resettable volumes,
|
|
278
|
+
generated host paths), which a person confirms. `result.question.expectedSha256` covers only the
|
|
279
|
+
second group, and the human reads it before accepting that digest.
|
|
202
280
|
4. Rerun with `--accept-defaults <expectedSha256>` as well. A digest that is not the pending one is
|
|
203
281
|
refused (`INIT_PREVIEW_NOT_ACCEPTED`, `INIT_DEFAULTS_NOT_ACCEPTED`).
|
|
204
282
|
|
|
@@ -239,11 +317,11 @@ vendor_endpoint_hosts = []
|
|
|
239
317
|
| `environment.install_policies` | the build and test commands per toolchain and lockfile; `[]` for none |
|
|
240
318
|
| `environment.test_data` | exactly the boolean keys `seeded_data` and `signed_in_users`; `false` states it is not needed |
|
|
241
319
|
| `environment.compose_files` | the Compose files that run the product, relative to the cockpit root |
|
|
242
|
-
| `environment.machine` | the runtime floor: `runtime_memory_mb`, `runtime_cpus`, `free_disk_mb`, `cold_start_seconds`;
|
|
320
|
+
| `environment.machine` | the runtime floor: `runtime_memory_mb`, `runtime_cpus`, `free_disk_mb`, `cold_start_seconds`; memory and CPUs are proposed, free disk and cold start never |
|
|
243
321
|
| `environment.posture` | `addressing`, `authentication` and `posture_requirements` ([Declare environment postures](environment.md#declare-environment-postures)) |
|
|
244
322
|
| `testing` | the product's `[testing]` stages and gates; `"none"` records that it has no tests yet, so no work can be graded PASS and `doctor` warns (`TESTING_GATE_UNDECLARED`) |
|
|
245
323
|
| `guards` | `hosted_db_hosts` and `vendor_endpoint_hosts` of every non-local environment; `[]` for both records that none exists |
|
|
246
|
-
| `provenance` | optional; `"human"` (the default)
|
|
324
|
+
| `provenance` | optional; `"human"` (the default), `"agent-default"` or `"derived"` per field. An `"agent-default"` answer stays under `unconfirmed` until `cockpit confirm` observes it or a person confirms it ([Mark the answers you chose](#mark-the-answers-you-chose)) |
|
|
247
325
|
|
|
248
326
|
A key that names no field is refused. Recorded answers are kept, so the same file can be passed on every
|
|
249
327
|
run; a different value for a recorded field is refused (`INIT_ANSWER_CONFLICT`) before anything is
|
|
@@ -277,7 +355,7 @@ compose_files = ["compose.yml"]
|
|
|
277
355
|
`[ports.bases]` variable, and a service without a healthcheck warns. The rules are in
|
|
278
356
|
[Environment lifecycle](environment.md#environment-modes); a working layout is
|
|
279
357
|
[examples/compose-first](https://github.com/b0dea/cockpit/blob/main/examples/compose-first/README.md). Changing a product's Compose file is a
|
|
280
|
-
product change:
|
|
358
|
+
product change: an agent makes it on a branch, as the [safety contract](#safety-contract) says.
|
|
281
359
|
|
|
282
360
|
**Data.** `seed` and `resettable_volumes` fill and wipe the stack's data
|
|
283
361
|
([Demo data, test users and roles](environment.md#demo-data-test-users-and-roles)). `cockpit reset` previews the change and needs a person
|
|
@@ -557,6 +635,12 @@ group stops, `session` calls `sleep`, which stops the stack only if no other che
|
|
|
557
635
|
it. Interrupting `session` stops only the process group it started, and a `session` inside another
|
|
558
636
|
is refused. Use plain `up` only when the stack should outlive one command.
|
|
559
637
|
|
|
638
|
+
While it runs, `ps` shows each service, and `restart`, `rebuild` and `exec` act on one of them by its
|
|
639
|
+
`--service` name; `up --profile <name>` adds a Compose profile. To work on a sibling in a worktree,
|
|
640
|
+
`use <slug> <checkout>` points this cockpit checkout's stack at it, `pull` fast-forwards every
|
|
641
|
+
checkout, and `stacks prune` removes the stack a deleted worktree left behind. All of them are in
|
|
642
|
+
[Environment lifecycle](environment.md#serve-a-sibling-from-a-worktree).
|
|
643
|
+
|
|
560
644
|
To remove the stack and its containers, run `down`. It reads the active Docker context once,
|
|
561
645
|
refuses one that is not local, and deletes only from that daemon, so a deletion never lands on a
|
|
562
646
|
remote daemon or on a context switched mid-command
|
package/docs/harness-surfaces.md
CHANGED
|
@@ -171,8 +171,9 @@ refused even the `test-run` its own skill asks for. The generated `.claude/setti
|
|
|
171
171
|
allows, by prefix, the cockpit commands the shipped skills tell an agent to run and the guard
|
|
172
172
|
admits (see [Cockpit commands an agent can run](safety-and-autonomy.md#cockpit-commands-an-agent-can-run)),
|
|
173
173
|
spelled both as `npx --no cockpit <command>` and as `./node_modules/.bin/cockpit <command>`.
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
Commands that are always a person's, such as `init` and `sibling add`, have no rule and keep
|
|
175
|
+
prompting. A command the policy decides, such as `sync` or `work accept`, has a rule: the guard hook
|
|
176
|
+
still runs first, and its ask or deny wins over a rule. Claude Code ignores a project's allow rules
|
|
176
177
|
until a person has trusted the workspace by starting Claude Code there once. Measured with Claude
|
|
177
178
|
Code 2.1.316 on 2026-11-02 beside a command with no rule.
|
|
178
179
|
|
|
@@ -248,6 +249,52 @@ environment and pass `PATH`, the same non-secret variables product test stages r
|
|
|
248
249
|
`USER`, `LOGNAME`, `TMPDIR`, `LANG`, `LC_ALL`, `LC_CTYPE`, `TZ`) and the declared environment
|
|
249
250
|
names.
|
|
250
251
|
|
|
252
|
+
### Remote servers
|
|
253
|
+
|
|
254
|
+
A remote (streamable HTTP) server is declared in the same file, in Claude Code's spelling:
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{ "mcpServers": {
|
|
258
|
+
"tracker": { "type": "http", "url": "https://mcp.example.test/mcp",
|
|
259
|
+
"headers": { "Authorization": "Bearer ${TRACKER_TOKEN}" } },
|
|
260
|
+
"docs": { "type": "http", "url": "https://docs.example.test/mcp", "headersHelper": "bin/mcp-headers docs" }
|
|
261
|
+
} }
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The URL must use `https`, or `http` only to a loopback host, and may carry no user information,
|
|
265
|
+
credential-named query parameter or `${...}` reference. Each header value is exactly `${NAME}`, or
|
|
266
|
+
`Bearer ${NAME}` in `Authorization`; a literal is refused, so no credential enters a tracked file.
|
|
267
|
+
`headersHelper` is a command and plain arguments, relative to the sibling, that prints a JSON object
|
|
268
|
+
of headers when the tool connects; it runs without a shell, so quoting and expansion belong in the
|
|
269
|
+
script. SSE servers are refused because Codex cannot connect to them. The approval digest covers the
|
|
270
|
+
URL, the header references and the helper's command, arguments and directory, so changing any of
|
|
271
|
+
them needs a new approval. Like a local server's command, the helper script's content is not in the
|
|
272
|
+
digest.
|
|
273
|
+
|
|
274
|
+
| Tool | Header references | Headers helper |
|
|
275
|
+
| --- | --- | --- |
|
|
276
|
+
| Claude Code | `headers` in `.mcp.json`, expanded from its environment | `headersHelper` |
|
|
277
|
+
| Codex | `bearer_token_env_var` and `env_http_headers` in `.codex/config.toml` | `http_headers_helper` |
|
|
278
|
+
| OpenCode | `{env:NAME}` in the `headers` of a `remote` server | none: the server is not written |
|
|
279
|
+
| Cursor, Grok Build | not written | not written |
|
|
280
|
+
|
|
281
|
+
A tool that cannot carry a server's credential gets nothing for that server, rather than a server
|
|
282
|
+
that starts and fails to authenticate; `sync` and `check` report `MCP_TRANSPORT_UNAVAILABLE` with the
|
|
283
|
+
tools it was left out of. The [capability matrix](capability-matrix.md) records the run behind each
|
|
284
|
+
cell. Claude Code runs a `headersHelper` from the project `.mcp.json` only after a person trusts the
|
|
285
|
+
workspace; until then it connects without those headers.
|
|
286
|
+
|
|
287
|
+
A header reference resolves from the environment the agent tool was launched in, so a tool started
|
|
288
|
+
from a desktop launcher may not see a variable set in a shell profile. A helper reads the credential
|
|
289
|
+
when the tool connects instead, wherever it keeps it. The helper runs through a generated wrapper,
|
|
290
|
+
`.cockpit/mcp/<id>.headers.sh`, started from the cockpit root like a local server's wrapper: it
|
|
291
|
+
changes to the sibling and passes the same inherited variables, without the header names.
|
|
292
|
+
|
|
293
|
+
`doctor` checks each approved server without starting it or using the network: a local server's
|
|
294
|
+
command and a remote server's helper must resolve (`MCP_COMMAND_UNRESOLVED`), and every environment
|
|
295
|
+
name it reads must be set where doctor runs (`MCP_ENVIRONMENT_UNSET`). It names variables, never
|
|
296
|
+
values.
|
|
297
|
+
|
|
251
298
|
Browser transport is published only for harnesses that can use it. A harness with no applicable
|
|
252
299
|
MCP server receives no MCP-only output; its instructions, skills and permissions still publish.
|
|
253
300
|
Verify the result with `./node_modules/.bin/cockpit check --config cockpit.toml --json` after
|
|
@@ -294,6 +341,26 @@ project root, so the committed pattern is `{file:.cockpit/local/opencode-grant-<
|
|
|
294
341
|
substitutes the absolute sibling directory that `sync` writes to that machine-local, ignored file,
|
|
295
342
|
and refuses to start, naming the file, until `sync` has run on the machine.
|
|
296
343
|
|
|
344
|
+
A checkout `cockpit use` serves from outside the declared one needs a grant that names a path on one
|
|
345
|
+
machine, which no committed file can hold. Measured on 2026-11-04, each run writing into the granted
|
|
346
|
+
directory and into an ungranted control directory beside it:
|
|
347
|
+
|
|
348
|
+
- Claude Code 2.1.318, `claude -p --permission-mode acceptEdits`: a directory listed in
|
|
349
|
+
`.claude/settings.local.json` `permissions.additionalDirectories` was written and the control was
|
|
350
|
+
refused. A twin whose list was a string was reported as not loaded, and granted nothing. The run
|
|
351
|
+
was in an untrusted workspace, where Claude Code ignored the committed `.claude/settings.json`
|
|
352
|
+
list, so whether the two lists combine once a person trusts the workspace is unmeasured. `use`
|
|
353
|
+
writes the served checkout there.
|
|
354
|
+
- OpenCode 1.19.5, `opencode run`: the grant file holding the worktree path allowed the write, the
|
|
355
|
+
control was denied, and a pattern naming a missing grant file stopped OpenCode at start, naming the
|
|
356
|
+
file. `use` and `sync` write the served checkout there.
|
|
357
|
+
- Codex 0.166.0, `codex exec`: Codex reads no machine-local project file; its only per-project user
|
|
358
|
+
setting is the trust level. `--add-dir <dir>` at start made the worktree writable beside the
|
|
359
|
+
committed writable roots, and without it the same write was refused. `use` writes nothing for
|
|
360
|
+
Codex and prints that flag.
|
|
361
|
+
|
|
362
|
+
Cursor and Grok Build were not installed, so `use` writes nothing for them and says so.
|
|
363
|
+
|
|
297
364
|
The `[cockpit].guide_cap` limit applies to always-loaded guidance, copied sibling guides included;
|
|
298
365
|
going over it makes `sync`, `check` and `preflight` report `GUIDE_CAP_EXCEEDED` with the measured
|
|
299
366
|
lines and the cap. The same code reports cockpit's region of **AGENTS.md** passing 32768 bytes,
|
|
@@ -28,7 +28,12 @@ A cockpit command is allowed only when it matches an exact available public comm
|
|
|
28
28
|
application verifies the executable and working root; the command resolver checks the bounded
|
|
29
29
|
complete argument vector, resolved configuration path, declared services, permitted option roles
|
|
30
30
|
and inspected paths. Internal guard transport and public commands marked unavailable are excluded.
|
|
31
|
-
|
|
31
|
+
The command after `session --` or `exec --` is judged as one more invocation, so neither admits
|
|
32
|
+
what the guard would refuse on its own. `exec` runs it in a product container whose files the
|
|
33
|
+
guard cannot see, so a read-only proof about host paths does not carry over: the name-based
|
|
34
|
+
denials (`.env*` and the rest) still apply to it, and it is admitted only by a `[guards] allow`
|
|
35
|
+
rule or as a declared build or test command; otherwise it asks, which Codex and OpenCode turn into
|
|
36
|
+
a denial. Declared project build and test commands are allowed only as their exact argument vectors in their
|
|
32
37
|
own checkout. A wildcard over a command family never grants permission.
|
|
33
38
|
|
|
34
39
|
## Hard controls and prompts
|
|
@@ -69,7 +74,8 @@ truncating `dd` or `tee` writes, `ln` onto either file, a `chmod` mode that drop
|
|
|
69
74
|
permission or is copied with `--reference`, a patch delete or move, a Write tool call with empty
|
|
70
75
|
content, and a `>` redirect. Editing the configuration in place stays permitted, including bounded
|
|
71
76
|
`dd conv=notrunc` and `tee` append forms under the normal write checks; the edit takes effect only
|
|
72
|
-
after a
|
|
77
|
+
after `sync` runs, and only a person's sync applies an edit that
|
|
78
|
+
[widens what agents may do](#edits-the-guard-has-not-applied).
|
|
73
79
|
|
|
74
80
|
Writing anywhere under a `.git` directory is a hard denial, because Git configuration chooses
|
|
75
81
|
programs that read-only Git commands run. For the same reason, so is every `git config` form other
|
|
@@ -220,19 +226,24 @@ cockpit commands in
|
|
|
220
226
|
|
|
221
227
|
| Command | Decision | Why |
|
|
222
228
|
| --- | --- | --- |
|
|
223
|
-
| `npx --no cockpit check --config cockpit.toml`, and likewise `doctor`, `preflight`, `logs --service <service
|
|
229
|
+
| `npx --no cockpit check --config cockpit.toml`, and likewise `doctor`, `preflight`, `ps`, `logs --service <service>`, `stacks`, `stacks prune`, `docs check` and `sync --dry-run` | allowed | They read and report; nothing they do changes a file the guard relies on. |
|
|
224
230
|
| `npx --no -- cockpit --help`, `npx --no cockpit up --help`, and the version | allowed | They print and exit before any command runs. |
|
|
225
|
-
| `npx --no cockpit up --config cockpit.toml`, and likewise `sleep` and `
|
|
231
|
+
| `npx --no cockpit up --config cockpit.toml`, and likewise `sleep`, `down`, `restart --service <service>` and `rebuild --service <service>` | allowed | They act only on the stack cockpit declared and owns; `down` keeps data volumes, and deletes only from the local Docker daemon it fixes at the start of the run. |
|
|
232
|
+
| `up --profile <profile>` | allowed for a profile in `environment.profiles` that mounts no sibling with `gate = "operator"`, otherwise a prompt | Another profile starts services no person declared for agents, and an operator-gated sibling touches live data or local hardware. |
|
|
233
|
+
| `npx --no cockpit exec --config cockpit.toml --service <service> -- <command>` | allowed when a `[guards] allow` rule or a declared build or test command admits `<command>`, otherwise a prompt | The command runs in a container whose files the guard cannot see, so it is never proven read-only, and the name-based denials still apply to it. |
|
|
234
|
+
| `npx --no cockpit pull --config cockpit.toml` | allowed | It only fetches and fast-forwards, and leaves a modified or diverged checkout as it was. |
|
|
235
|
+
| `npx --no cockpit use <slug> <checkout> --config cockpit.toml`, and `use <slug> --clear` | allowed for a checkout inside a directory the agent may already write, otherwise a prompt | The choice is recorded for this checkout of the cockpit only, so it never widens what the agent can reach. |
|
|
226
236
|
| `npx --no cockpit runtime measure --config cockpit.toml --image <local-image>` | allowed | The probe runs a disposable stack under its own project, removes it, and records the result only in this machine's git-ignored state; `cockpit.toml` never changes. |
|
|
227
|
-
| `npx --no cockpit session --config cockpit.toml -- <command
|
|
237
|
+
| `npx --no cockpit session --config cockpit.toml -- <command>`, with a `--profile` that `up` admits | the decision for `<command>` | A session runs its command as the agent could run it directly, so it never admits more. |
|
|
228
238
|
| `npx --no cockpit test-run --config cockpit.toml --gate <gate>`, with an optional `--mode` and a `--select <kind>:<value>` whose value does not start with `-` | allowed for a gate `cockpit.toml` declares | The gate runs only the stages a person declared in the reviewed configuration, the trust `up` already has. |
|
|
229
|
-
| `npx --no cockpit work status --config cockpit.toml`, `work accept`, `work check`, `work note`, `work answer`, `work grade`, `work signoff`, `work recover` without `--apply
|
|
230
|
-
| `npx --no cockpit sync --config cockpit.toml`, and `upgrade`, whose sync child writes | allowed where `[autonomy] sync = "agent"`, otherwise a prompt | It regenerates the files the configuration
|
|
239
|
+
| `npx --no cockpit work status --config cockpit.toml`, `work accept`, `work check`, `work note`, `work decide`, `work answer`, `work acknowledge`, `work grade`, `work signoff`, `work recover` (with or without `--apply`), `work verify` and `cockpit grade --criteria <file>`, each with its own options | allowed | They report, or take a step [`[work.gates]`](#who-decides) gives the agent; a step it gives a person waits for the digest typed after `--interactive`, which no agent invocation carries. Grading runs in a separate evaluator. `work recover --apply` removes a lock only once it has shown the holder gone on the lock's own host and among the containers cockpit labels. |
|
|
240
|
+
| `npx --no cockpit sync --config cockpit.toml`, and `upgrade`, whose sync child writes | allowed where `[autonomy] sync = "agent"`, otherwise a prompt | It regenerates the files the configuration declares; after `cockpit.toml` changes, the guard admits it only when the edit [does not widen](#edits-the-guard-has-not-applied) what agents may do, so an agent's sync never publishes a widening of its own. |
|
|
241
|
+
| `npx --no cockpit tool add <tool> --config cockpit.toml`, with an optional `--dry-run` | allowed | It edits only `[surfaces] tools`, and an added tool [does not widen](#edits-the-guard-has-not-applied) what agents may do, so the agent's sync applies it. |
|
|
231
242
|
| `npx --no cockpit reset --config cockpit.toml --apply` | allowed where `[autonomy] reset = "agent"`, otherwise a prompt | It deletes stack data. |
|
|
232
|
-
| `npx --no cockpit
|
|
233
|
-
| `
|
|
234
|
-
| `work
|
|
235
|
-
| `sync --adopt`, `sync --interactive`, `reset --interactive`, `sibling add` and every other command | a prompt, which Codex and OpenCode turn into a denial | They
|
|
243
|
+
| `npx --no cockpit stacks prune --config cockpit.toml --apply` | allowed; the command itself refuses a prune that deletes volumes unless `[autonomy] reset = "agent"` | It removes only stacks whose checkout is gone, which bringing the stack up again recreates, and their data only where a reset could delete it. |
|
|
244
|
+
| `npx --no cockpit browser drive --config cockpit.toml`, and likewise `screenshot`, with an optional `--role` | allowed where `browser.request_preapproval` is on, otherwise a prompt | They sign in and capture the declared application, so they run unprompted only on the isolated, non-production data the configuration declares. Preapproval is on by default exactly when `browser.data` is isolated, not restored and not reaching production, and off otherwise; an explicit `request_preapproval` wins, and `true` on a posture that does not qualify is refused. `drive` also accepts `--fail-on-findings`. |
|
|
245
|
+
| `work accept`, `work answer`, `work acknowledge` and `work signoff` with `--interactive` | a prompt, which Codex and OpenCode turn into a denial | `--interactive` asks for a person at a terminal to type the digest of what it shows. |
|
|
246
|
+
| `sync --adopt`, `sync --interactive`, `reset --interactive`, `stacks prune --interactive`, `sibling add`, `sibling remove`, `tool remove` and every other command | a prompt, which Codex and OpenCode turn into a denial | They widen what agents may do through `cockpit.toml`, rewrite a team's own settings, ask for a person, or delete data. |
|
|
236
247
|
|
|
237
248
|
A file such a command names, like `--criteria`, is checked as a read:
|
|
238
249
|
the command may quote it in a refusal. A declared instance, a file below `.secrets` or a `.env` or
|
|
@@ -339,7 +350,7 @@ templates too, which `cat` in a shell still reads.
|
|
|
339
350
|
| --- | --- | --- |
|
|
340
351
|
| `sync` | whether the guard lets an agent run a writing `sync`; under `ci` a writing sync runs only where `CI` is set | `agent` |
|
|
341
352
|
| `stale_delete` | whether `sync` removes a file it generated before and no longer generates without a person typing the stale-removal digest | `agent` |
|
|
342
|
-
| `reset` | whether `reset --apply` deletes stack data without a person; otherwise a person approves the preview with `--interactive` | `person` |
|
|
353
|
+
| `reset` | whether `reset --apply`, and a `stacks prune --apply` that deletes volumes, delete stack data without a person; otherwise a person approves the preview with `--interactive` | `person` |
|
|
343
354
|
| `mcp_approve` | `person`: sync enables only the MCP servers whose digest a person recorded in `[mcp.approved]`, and `MCP_NOT_APPROVED` names the rest; `agent`: sync enables every declared server as declared now, which lets an agent start processes outside the guard, because a sibling's MCP source is a file the agent can write and each harness starts an enabled server outside every guard boundary | `person` |
|
|
344
355
|
|
|
345
356
|
<!-- cockpit:ref path=packages/cockpit/src/guards/policy-pin.ts --> The guard pins the policy: an agent's edit, write or patch that would change `[work]`,
|
|
@@ -371,6 +382,39 @@ A local `person` gate is best-effort: cockpit cannot tell a person from a progra
|
|
|
371
382
|
The only enforced human gate is a required CI job behind a protected environment whose reviewers must
|
|
372
383
|
approve it, such as the [`work verify` job](work-and-browser.md#who-passes-each-gate).
|
|
373
384
|
|
|
385
|
+
### Edits the guard has not applied
|
|
386
|
+
|
|
387
|
+
<!-- cockpit:ref path=packages/cockpit/src/guards/policy-change.ts --> Once `cockpit.toml` differs
|
|
388
|
+
from the configuration the guards were generated from, the guard loads both, the earlier from the
|
|
389
|
+
copy sync keeps in `.cockpit/local/guard-config`, and compares them with defaults applied. An edit that does
|
|
390
|
+
not widen what agents may do holds every tool call except `cockpit sync` and `cockpit check`, which
|
|
391
|
+
the agent may run under the rules above, and the hold says so (`GUARD_CONFIG_UNSYNCED`). Any other
|
|
392
|
+
edit holds every call, that sync included, until a person runs `sync` in a terminal, and the hold
|
|
393
|
+
names each field that widens.
|
|
394
|
+
|
|
395
|
+
An edit does not widen only when every difference is one of these:
|
|
396
|
+
|
|
397
|
+
- descriptive or host-only fields: a sibling's `purpose`, `host_reason` and `rebuild_inputs`,
|
|
398
|
+
`cockpit.guide_cap`, `[ports]`, `environment.entrypoint_derivatives`, `environment.machine` and
|
|
399
|
+
`docs.living`;
|
|
400
|
+
- added agent tools, `unconfirmed` answers and sibling operator gates;
|
|
401
|
+
- removed Compose files, Compose profiles and resettable volumes, and an install policy that admits no
|
|
402
|
+
command it did not.
|
|
403
|
+
|
|
404
|
+
Every other difference widens. That includes any change, in either direction, to `[guards]`,
|
|
405
|
+
`[work]`, `[autonomy]`, `[mcp]`, `[testing]` (whose stages `test-run` runs unprompted) and `[browser]`;
|
|
406
|
+
a new sibling, wherever its directory is; a sibling's changed `dir`, `guides` (sync copies each guide
|
|
407
|
+
into the root `AGENTS.md`), environment files or derived MCP sources; and every command field, such
|
|
408
|
+
as `environment.seed`. A field the classification has no rule for widens too, so a field added to
|
|
409
|
+
the schema is a person's decision until a rule says otherwise. A missing or mismatched
|
|
410
|
+
copy of the generated configuration cannot show an edit safe, so it holds as a widening edit does.
|
|
411
|
+
`check` reports the same classification: `GUARD_CONFIG_UNSYNCED` as a warning, `GUARD_CONFIG_WIDENED`
|
|
412
|
+
as an error naming the fields.
|
|
413
|
+
|
|
414
|
+
Whoever runs it, sync refuses a guide that is, or links to, a `.env` or `.env.*` file, a file below a
|
|
415
|
+
`.secrets` directory or a declared environment instance (`PROJECTION_GUIDE_SECRET`), so a guide never
|
|
416
|
+
copies what the guard keeps from agents into the root `AGENTS.md`.
|
|
417
|
+
|
|
374
418
|
## Native adapter behavior
|
|
375
419
|
|
|
376
420
|
The [transport and adapter owner](https://github.com/b0dea/cockpit/blob/main/packages/cockpit/src/guards/harness-adapter.ts) translates a
|
package/docs/troubleshooting.md
CHANGED
|
@@ -121,7 +121,8 @@ the harness enforces anything.
|
|
|
121
121
|
### MCP and restrictions
|
|
122
122
|
|
|
123
123
|
For `MCP_INPUT_INVALID` or `MCP_DECLARATION_INVALID`, correct the declaration, digest,
|
|
124
|
-
same-name environment reference,
|
|
124
|
+
same-name environment reference, confined working directory, or remote server URL, header
|
|
125
|
+
reference or `headersHelper` named by the message.
|
|
125
126
|
`MCP_COMMAND_CONFLICT` means two sources give one server name different commands; make them agree or give them distinct names. `MCP_NOT_APPROVED` leaves a declared
|
|
126
127
|
server disabled because `[mcp.approved]` has no entry for it, or its declaration changed since it
|
|
127
128
|
was approved; a person, only after reviewing its command, arguments, working directory, environment
|
|
@@ -129,6 +130,9 @@ names and sources, sets its name to the sha256 in the message under `[mcp.approv
|
|
|
129
130
|
While `[autonomy] mcp_approve` is `person`, the default, the guard refuses an agent's edit of `[mcp]`. `MCP_APPROVAL_UNKNOWN` means the allowlist names no
|
|
130
131
|
declaration. `MCP_EXECUTABLE_UNAVAILABLE` comes from the generated wrapper when its declared
|
|
131
132
|
executable is absent or not executable; restore that executable rather than changing the wrapper.
|
|
133
|
+
`MCP_TRANSPORT_UNAVAILABLE` names a remote server left out of the tools that cannot carry its
|
|
134
|
+
credential, such as OpenCode for a server with a `headersHelper`; see
|
|
135
|
+
[Remote servers](harness-surfaces.md#remote-servers) for what each tool can carry.
|
|
132
136
|
|
|
133
137
|
For `RESTRICTION_INPUT_INVALID`, `RESTRICTION_ADAPTER_INVALID`, `RESTRICTION_EVENT_UNADAPTED`,
|
|
134
138
|
`RESTRICTION_TEMPLATE_INVALID` or `RESTRICTION_OUTPUT_LIMIT`, correct the named guard policy,
|
|
@@ -202,7 +206,17 @@ progress per checkout. A state diagnostic's target names the exact directory.
|
|
|
202
206
|
|
|
203
207
|
These records are how cockpit knows which containers and ports a stack owns. Do not edit them by
|
|
204
208
|
hand, and do not delete them while the stack runs: its containers would keep running with nothing
|
|
205
|
-
that knows about them.
|
|
209
|
+
that knows about them.
|
|
210
|
+
|
|
211
|
+
A stack whose worktree was deleted, and state folders an earlier cockpit build left, are removed by
|
|
212
|
+
`stacks prune`, which previews by default and removes only what no checkout can reach; see
|
|
213
|
+
[List and prune stacks across the machine](environment.md#list-and-prune-stacks-across-the-machine).
|
|
214
|
+
`doctor` warns with `STACKS_ORPHANED` when it finds such a stack, and with `STATE_RECORD_MALFORMED`
|
|
215
|
+
for another cockpit's state folder this version cannot read; `up` and `sleep` ignore that folder's
|
|
216
|
+
port leases.
|
|
217
|
+
|
|
218
|
+
`stacks prune` keeps a stack whose checkout still exists. To clear the state of a checkout you still
|
|
219
|
+
have:
|
|
206
220
|
|
|
207
221
|
1. Stop the stack and release its claims from the cockpit directory:
|
|
208
222
|
`./node_modules/.bin/cockpit down --config cockpit.toml`.
|
|
@@ -212,10 +226,7 @@ that knows about them. To clear one cockpit's state:
|
|
|
212
226
|
`rm -rf "$HOME/Library/Application Support/cockpit/state/v1/cockpits/cockpit_duo_<hash>"`.
|
|
213
227
|
|
|
214
228
|
When this cockpit's own state cannot be read, runtime commands refuse with
|
|
215
|
-
`STATE_RECORD_MALFORMED` or `STATE_FORMAT_UNSUPPORTED` until you clear it
|
|
216
|
-
another cockpit, such as a directory left by an earlier cockpit build, does not stop you: `up` and
|
|
217
|
-
`sleep` ignore its port leases, and only `doctor` warns with `STATE_RECORD_MALFORMED`, naming that
|
|
218
|
-
directory and the `rm -rf` command. Remove it with the same steps once no cockpit uses it.
|
|
229
|
+
`STATE_RECORD_MALFORMED` or `STATE_FORMAT_UNSUPPORTED` until you clear it this way.
|
|
219
230
|
|
|
220
231
|
<!-- cockpit:diagnostic-index:begin -->
|
|
221
232
|
## Codes with a fixed remedy
|
|
@@ -226,6 +237,7 @@ Every diagnostic message names what failed and how to fix it. These codes always
|
|
|
226
237
|
| --- | --- |
|
|
227
238
|
| `AUTONOMY_CI_ONLY` | push the change and let the CI job run the command, or have a person change the field in cockpit.toml and accept the change at sync |
|
|
228
239
|
| `AUTONOMY_PERSON_REQUIRED` | a person runs the same command with --interactive in a terminal outside CI, or a person changes the field in cockpit.toml and accepts the change at sync |
|
|
240
|
+
| `BROWSER_ROUTE_FINDINGS` | this run asked for a clean route (--fail-on-findings). Read result.receipt.surfaces[].diagnostics, including excerpt.messages where present: fix the product for each console error, uncaught page error and failed request that matters, then rerun npx --no cockpit browser drive --config <your cockpit.toml> --route <name> --fail-on-findings; third-party traffic never counts |
|
|
229
241
|
| `CLAIM_CO_TENANT` | [see above](#common-refusal-guidance) |
|
|
230
242
|
| `COCKPIT_LAUNCHER_UNPROVEN` | run cockpit as ./node_modules/.bin/cockpit <command> --config <your cockpit.toml> from the cockpit root, or remove what stops npx from proving it: a .npmrc in the cockpit root, a bin or directories.bin in its package.json, or a node_modules/.bin/cockpit that npm install did not link to the installed package |
|
|
231
243
|
| `COCKPIT_REVISION_UNSTAMPED` | install a released @b00dea/cockpit when the resolved data must name the exact cockpit source commit |
|
|
@@ -233,7 +245,13 @@ Every diagnostic message names what failed and how to fix it. These codes always
|
|
|
233
245
|
| `COMPOSE_FILE_UNREADABLE` | make environment.compose_files name a readable Compose file inside the cockpit root, then run npx --no cockpit check --config <your cockpit.toml> |
|
|
234
246
|
| `CONFIG_ENCODING_INVALID` | save the configuration as UTF-8, then retry |
|
|
235
247
|
| `DATA_SEED_UNAVAILABLE` | make sure the Docker daemon this stack runs on answers docker volume ls, then rerun npx --no cockpit up --config <your cockpit.toml> |
|
|
236
|
-
| `
|
|
248
|
+
| `DECISION_INDEX_ENTRY_MISSING` | correct the link to the record's current file name, or remove the entry if the record was deleted on purpose |
|
|
249
|
+
| `DECISION_LINK_UNRESOLVED` | correct the number or link to name an existing record, or restore the record it names |
|
|
250
|
+
| `DECISION_NUMBER_REUSED` | renumber the later record to the next free number, then update the index and every supersedes line that cites it |
|
|
251
|
+
| `DECISION_UNINDEXED` | add a line linking the record to the decision index |
|
|
252
|
+
| `DOCS_NOT_DECLARED` | add a [docs] table to cockpit.toml: living = ["README.md", "docs/**/*.md"] lists the documents that must stay true, and the optional decisions = "docs/adr" and decisions_index = "docs/adr/README.md" name the decision records and their index; then rerun npx --no cockpit docs check --config <your cockpit.toml> |
|
|
253
|
+
| `DOCS_REFERENCE_REMOVED` | cite the path that replaced it (a rename is named in the message), or rewrite or delete the sentence if what it described is gone; then rerun npx --no cockpit docs check --config <your cockpit.toml> |
|
|
254
|
+
| `DOCS_TARGET_REMOVED` | cite the target or command that replaced it, or rewrite or delete the sentence if the step is gone; then rerun npx --no cockpit docs check --config <your cockpit.toml> |
|
|
237
255
|
| `DOCUMENT_ESTATE_TOPOLOGY_MISMATCH` | declare one sibling for each repository the message says init observed, with that slug and dir, and no other; add any other repository after init with npx --no cockpit sibling add <slug> --config <your cockpit.toml> |
|
|
238
256
|
| `DOCUMENT_GUARD_HOSTS_NONE` | list the hosts in guards.hosted_db_hosts and guards.vendor_endpoint_hosts and run npx --no cockpit sync --config <your cockpit.toml> once a non-local environment exists |
|
|
239
257
|
| `DOCUMENT_RUNTIME_NOT_DECLARED` | once a product runs, declare environment.compose_files and run npx --no cockpit sync --config <your cockpit.toml> |
|
|
@@ -257,9 +275,11 @@ Every diagnostic message names what failed and how to fix it. These codes always
|
|
|
257
275
|
| `LOGS_TRUNCATED` | lower --tail to the number of recent records you need, or read the older records from the container runtime directly |
|
|
258
276
|
| `MCP_APPROVAL_UNKNOWN` | [see above](#mcp-and-restrictions) |
|
|
259
277
|
| `MCP_COMMAND_CONFLICT` | [see above](#mcp-and-restrictions) |
|
|
278
|
+
| `MCP_COMMAND_UNRESOLVED` | install the command or correct it in the sibling's MCP declaration, then run npx --no cockpit sync --config <your cockpit.toml>; a changed declaration needs a person to approve its new sha256 under [mcp.approved] |
|
|
260
279
|
| `MCP_DECLARATION_INVALID` | [see above](#mcp-and-restrictions) |
|
|
261
280
|
| `MCP_INPUT_INVALID` | [see above](#mcp-and-restrictions) |
|
|
262
281
|
| `MCP_NOT_APPROVED` | [see above](#mcp-and-restrictions) |
|
|
282
|
+
| `MCP_TRANSPORT_UNAVAILABLE` | [see above](#mcp-and-restrictions) |
|
|
263
283
|
| `OUTPUT_EXISTS` | choose a new path; replacement requires a future explicit option |
|
|
264
284
|
| `PORT_FAMILY_COLLISION` | [see above](#common-refusal-guidance) |
|
|
265
285
|
| `PORT_LEASE_EXHAUSTED` | [see above](#common-refusal-guidance) |
|
|
@@ -313,6 +333,7 @@ Every diagnostic message names what failed and how to fix it. These codes always
|
|
|
313
333
|
| `SKILL_RENDER_INVENTORY_INVALID` | [see above](#sibling-projection-and-skills) |
|
|
314
334
|
| `SKILL_STANDING_COST_EXCEEDED` | [see above](#sibling-projection-and-skills) |
|
|
315
335
|
| `SKILL_TOOL_EQUIVALENCE_MISSING` | [see above](#sibling-projection-and-skills) |
|
|
336
|
+
| `STACKS_ORPHANED` | [see above](#clear-cockpit-state) |
|
|
316
337
|
| `STATE_FORMAT_UNSUPPORTED` | [see above](#clear-cockpit-state) |
|
|
317
338
|
| `STATE_RECORD_MALFORMED` | [see above](#clear-cockpit-state) |
|
|
318
339
|
| `SURFACE_ADOPTION_REFUSED` | [see above](#merge-ownership-and-generation) |
|
|
@@ -357,5 +378,5 @@ Every diagnostic message names what failed and how to fix it. These codes always
|
|
|
357
378
|
| `UPGRADE_VERSION_INVALID` | give a full version such as 1.2.3, not a range or tag |
|
|
358
379
|
| `WORK_CHECK_FAILED` | read result.results: fix the product for a check that failed, make one that did not run runnable from the cockpit root, then rerun npx --no cockpit work check --config <your cockpit.toml> --work-order <id> |
|
|
359
380
|
| `WORK_PERSON_REQUIRED` | stop and ask a person to run the same command with --interactive in a terminal outside CI, read what it shows, and type the digest; never type it for them |
|
|
360
|
-
| `WORK_VERIFY_FAILED` | for an order changed since acceptance, run npx --no cockpit work accept --config <your cockpit.toml> --work-order <id> or revert the change; for a done order without a passing grade, regrade it with work grade |
|
|
381
|
+
| `WORK_VERIFY_FAILED` | for an order changed since acceptance, run npx --no cockpit work accept --config <your cockpit.toml> --work-order <id> or revert the change; for a done order without a passing grade, regrade it with work grade; for a decision record that is missing or no longer cites its order, restore it from git or put back its "Work order: <id>" line |
|
|
361
382
|
<!-- cockpit:diagnostic-index:end -->
|
package/docs/tutorial.md
CHANGED
|
@@ -145,13 +145,14 @@ with data, add `resettable_volumes` and `seed` as
|
|
|
145
145
|
|
|
146
146
|
## Bring the stack up
|
|
147
147
|
|
|
148
|
-
With Docker running, measure the runtime once with a local image, then start the stack,
|
|
149
|
-
command against it, and remove it:
|
|
148
|
+
With Docker running, measure the runtime once with a local image, then start the stack, list its
|
|
149
|
+
services, run one command against it, and remove it:
|
|
150
150
|
|
|
151
151
|
```sh
|
|
152
152
|
docker pull node:22-alpine
|
|
153
153
|
./node_modules/.bin/cockpit runtime measure --config cockpit.toml --image node:22-alpine
|
|
154
154
|
./node_modules/.bin/cockpit up --config cockpit.toml
|
|
155
|
+
./node_modules/.bin/cockpit ps --config cockpit.toml
|
|
155
156
|
./node_modules/.bin/cockpit session --config cockpit.toml -- sh -c 'curl -fsS "http://127.0.0.1:$API_HOST_PORT/health"'
|
|
156
157
|
./node_modules/.bin/cockpit down --config cockpit.toml
|
|
157
158
|
```
|