@b00dea/cockpit 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +474 -0
- package/LICENSE +21 -0
- package/README.md +25 -2
- package/bin/cockpit.mjs +33 -0
- package/cockpit.schema.json +2644 -0
- package/dist/autonomy.d.ts +45 -0
- package/dist/autonomy.js +173 -0
- package/dist/bounded-read.d.ts +14 -0
- package/dist/bounded-read.js +42 -0
- package/dist/browser/commands.d.ts +117 -0
- package/dist/browser/commands.js +453 -0
- package/dist/browser/package-paths.d.ts +1 -0
- package/dist/browser/package-paths.js +6 -0
- package/dist/browser/proxy.d.ts +22 -0
- package/dist/browser/proxy.js +37 -0
- package/dist/browser/runtime.d.ts +118 -0
- package/dist/browser/runtime.js +186 -0
- package/dist/browser/surfaces.d.ts +141 -0
- package/dist/browser/surfaces.js +561 -0
- package/dist/browser/ui-gate.d.ts +15 -0
- package/dist/browser/ui-gate.js +18 -0
- package/dist/canonical-json.d.ts +2 -0
- package/dist/canonical-json.js +5 -0
- package/dist/cli-guard.d.ts +5 -0
- package/dist/cli-guard.js +71 -0
- package/dist/cli-main.d.ts +176 -0
- package/dist/cli-main.js +1584 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +16 -0
- package/dist/command-table.d.ts +121 -0
- package/dist/command-table.js +664 -0
- package/dist/config/load.d.ts +183 -0
- package/dist/config/load.js +367 -0
- package/dist/config/sibling-toml.d.ts +48 -0
- package/dist/config/sibling-toml.js +160 -0
- package/dist/config/surface-tools-toml.d.ts +9 -0
- package/dist/config/surface-tools-toml.js +37 -0
- package/dist/config/unconfirmed-toml.d.ts +9 -0
- package/dist/config/unconfirmed-toml.js +29 -0
- package/dist/config/verified-write.d.ts +43 -0
- package/dist/config/verified-write.js +89 -0
- package/dist/diagnostics.d.ts +26 -0
- package/dist/diagnostics.js +344 -0
- 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/emit.d.ts +22 -0
- package/dist/emit.js +43 -0
- package/dist/entrypoint-kinds.d.ts +3 -0
- package/dist/entrypoint-kinds.js +11 -0
- package/dist/environment/application/confirm.d.ts +35 -0
- package/dist/environment/application/confirm.js +122 -0
- package/dist/environment/application/destructive.d.ts +6 -0
- package/dist/environment/application/destructive.js +429 -0
- package/dist/environment/application/doctor.d.ts +94 -0
- package/dist/environment/application/doctor.js +247 -0
- package/dist/environment/application/guard.d.ts +49 -0
- package/dist/environment/application/guard.js +677 -0
- package/dist/environment/application/health.d.ts +143 -0
- package/dist/environment/application/health.js +385 -0
- package/dist/environment/application/lifecycle-context.d.ts +235 -0
- package/dist/environment/application/lifecycle-context.js +154 -0
- package/dist/environment/application/lifecycle-state.d.ts +25 -0
- package/dist/environment/application/lifecycle-state.js +202 -0
- package/dist/environment/application/lifecycle.d.ts +18 -0
- package/dist/environment/application/lifecycle.js +737 -0
- package/dist/environment/application/logs.d.ts +45 -0
- package/dist/environment/application/logs.js +127 -0
- package/dist/environment/application/services.d.ts +60 -0
- package/dist/environment/application/services.js +89 -0
- package/dist/environment/application/setup.d.ts +129 -0
- package/dist/environment/application/setup.js +741 -0
- package/dist/environment/application/shared.d.ts +11 -0
- package/dist/environment/application/shared.js +61 -0
- package/dist/environment/application/siblings.d.ts +43 -0
- package/dist/environment/application/siblings.js +269 -0
- package/dist/environment/claims.d.ts +389 -0
- package/dist/environment/claims.js +1701 -0
- package/dist/environment/codex-hook-trust.d.ts +11 -0
- package/dist/environment/codex-hook-trust.js +185 -0
- package/dist/environment/compose-environment.d.ts +1 -0
- package/dist/environment/compose-environment.js +6 -0
- package/dist/environment/compose-ownership.d.ts +21 -0
- package/dist/environment/compose-ownership.js +117 -0
- package/dist/environment/compose-topology.d.ts +125 -0
- package/dist/environment/compose-topology.js +490 -0
- package/dist/environment/contract.d.ts +522 -0
- package/dist/environment/contract.js +794 -0
- package/dist/environment/declaration.d.ts +14 -0
- package/dist/environment/declaration.js +39 -0
- package/dist/environment/destructive-composition.d.ts +29 -0
- package/dist/environment/destructive-composition.js +333 -0
- package/dist/environment/docker-daemon.d.ts +30 -0
- package/dist/environment/docker-daemon.js +78 -0
- package/dist/environment/docker-endpoint.d.ts +10 -0
- package/dist/environment/docker-endpoint.js +19 -0
- package/dist/environment/env-schema-observation.d.ts +46 -0
- package/dist/environment/env-schema-observation.js +241 -0
- package/dist/environment/evidence.d.ts +136 -0
- package/dist/environment/evidence.js +437 -0
- package/dist/environment/executable.d.ts +38 -0
- package/dist/environment/executable.js +190 -0
- package/dist/environment/generated-application/authorities.d.ts +5 -0
- package/dist/environment/generated-application/authorities.js +61 -0
- package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
- package/dist/environment/generated-application/bootstrap-skill.js +328 -0
- package/dist/environment/generated-application/check.d.ts +13 -0
- package/dist/environment/generated-application/check.js +191 -0
- package/dist/environment/generated-application/custom-surface.d.ts +26 -0
- package/dist/environment/generated-application/custom-surface.js +289 -0
- package/dist/environment/generated-application/prepare.d.ts +29 -0
- package/dist/environment/generated-application/prepare.js +278 -0
- package/dist/environment/generated-application/publication.d.ts +33 -0
- package/dist/environment/generated-application/publication.js +547 -0
- package/dist/environment/generated-application/shared.d.ts +492 -0
- package/dist/environment/generated-application/shared.js +354 -0
- package/dist/environment/generated-application/surface-observation.d.ts +4 -0
- package/dist/environment/generated-application/surface-observation.js +69 -0
- package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
- package/dist/environment/generated-application/surface-outputs.js +400 -0
- package/dist/environment/generated-application/surfaces.d.ts +3 -0
- package/dist/environment/generated-application/surfaces.js +704 -0
- package/dist/environment/generated-application/sync.d.ts +6 -0
- package/dist/environment/generated-application/sync.js +124 -0
- package/dist/environment/git-observation.d.ts +202 -0
- package/dist/environment/git-observation.js +553 -0
- package/dist/environment/health-composition.d.ts +12 -0
- package/dist/environment/health-composition.js +645 -0
- package/dist/environment/host-observation.d.ts +56 -0
- package/dist/environment/host-observation.js +52 -0
- package/dist/environment/identity.d.ts +48 -0
- package/dist/environment/identity.js +85 -0
- package/dist/environment/init-application.d.ts +333 -0
- package/dist/environment/init-application.js +726 -0
- package/dist/environment/install-policy-observation.d.ts +71 -0
- package/dist/environment/install-policy-observation.js +284 -0
- package/dist/environment/install-policy.d.ts +48 -0
- package/dist/environment/install-policy.js +96 -0
- package/dist/environment/instance.d.ts +33 -0
- package/dist/environment/instance.js +122 -0
- package/dist/environment/instruction-pointer.d.ts +19 -0
- package/dist/environment/instruction-pointer.js +144 -0
- package/dist/environment/lifecycle-composition.d.ts +31 -0
- package/dist/environment/lifecycle-composition.js +742 -0
- package/dist/environment/lifecycle-stage.d.ts +120 -0
- package/dist/environment/lifecycle-stage.js +408 -0
- package/dist/environment/lifecycle.d.ts +75 -0
- package/dist/environment/lifecycle.js +354 -0
- package/dist/environment/logs.d.ts +132 -0
- package/dist/environment/logs.js +519 -0
- 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 +46 -0
- package/dist/environment/observations.js +346 -0
- package/dist/environment/operator-application.d.ts +79 -0
- package/dist/environment/operator-application.js +197 -0
- package/dist/environment/ports.d.ts +182 -0
- package/dist/environment/ports.js +1205 -0
- package/dist/environment/posture-observation.d.ts +68 -0
- package/dist/environment/posture-observation.js +253 -0
- package/dist/environment/presence.d.ts +4 -0
- package/dist/environment/presence.js +26 -0
- package/dist/environment/read-composition.d.ts +32 -0
- package/dist/environment/read-composition.js +397 -0
- package/dist/environment/readiness-composition.d.ts +57 -0
- package/dist/environment/readiness-composition.js +151 -0
- package/dist/environment/reclaim.d.ts +370 -0
- package/dist/environment/reclaim.js +1940 -0
- package/dist/environment/repository-identity.d.ts +13 -0
- package/dist/environment/repository-identity.js +108 -0
- package/dist/environment/runtime-measurement-record.d.ts +38 -0
- package/dist/environment/runtime-measurement-record.js +111 -0
- package/dist/environment/runtime-measurement.d.ts +27 -0
- package/dist/environment/runtime-measurement.js +224 -0
- package/dist/environment/runtime-probe-residue.d.ts +43 -0
- package/dist/environment/runtime-probe-residue.js +148 -0
- package/dist/environment/runtime-probe.d.ts +72 -0
- package/dist/environment/runtime-probe.js +725 -0
- package/dist/environment/runtime.d.ts +551 -0
- package/dist/environment/runtime.js +2405 -0
- package/dist/environment/seed.d.ts +16 -0
- package/dist/environment/seed.js +43 -0
- package/dist/environment/selftest-application.d.ts +86 -0
- package/dist/environment/selftest-application.js +713 -0
- package/dist/environment/sensitive.d.ts +3 -0
- package/dist/environment/sensitive.js +48 -0
- package/dist/environment/served-checkout-grants.d.ts +53 -0
- package/dist/environment/served-checkout-grants.js +182 -0
- package/dist/environment/setup-observation.d.ts +62 -0
- package/dist/environment/setup-observation.js +1473 -0
- package/dist/environment/setup.d.ts +43 -0
- package/dist/environment/setup.js +176 -0
- package/dist/environment/sibling-checkouts.d.ts +119 -0
- package/dist/environment/sibling-checkouts.js +254 -0
- package/dist/environment/sibling-instructions.d.ts +33 -0
- package/dist/environment/sibling-instructions.js +224 -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/sibling-registration.d.ts +45 -0
- package/dist/environment/sibling-registration.js +538 -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 +410 -0
- package/dist/environment/state.js +2153 -0
- package/dist/environment/templates.d.ts +140 -0
- package/dist/environment/templates.js +685 -0
- package/dist/environment/tool-registration.d.ts +9 -0
- package/dist/environment/tool-registration.js +92 -0
- package/dist/environment/upgrade-application.d.ts +19 -0
- package/dist/environment/upgrade-application.js +175 -0
- package/dist/environment-exec/execute.d.ts +105 -0
- package/dist/environment-exec/execute.js +1179 -0
- package/dist/environment-exec/libexec-program.d.ts +6 -0
- package/dist/environment-exec/libexec-program.js +22 -0
- package/dist/environment-exec/verified-digest.d.ts +4 -0
- package/dist/environment-exec/verified-digest.js +16 -0
- package/dist/exact-keys.d.ts +7 -0
- package/dist/exact-keys.js +15 -0
- package/dist/fix-catalogue.d.ts +32 -0
- package/dist/fix-catalogue.js +60 -0
- package/dist/freshness.d.ts +29 -0
- package/dist/freshness.js +75 -0
- package/dist/generated-environment/adopt.d.ts +16 -0
- package/dist/generated-environment/adopt.js +271 -0
- package/dist/generated-environment/command.d.ts +47 -0
- package/dist/generated-environment/command.js +75 -0
- package/dist/generated-environment/transaction.d.ts +186 -0
- package/dist/generated-environment/transaction.js +1770 -0
- package/dist/grading/evaluate.d.ts +71 -0
- package/dist/grading/evaluate.js +403 -0
- package/dist/grading/grade.d.ts +33 -0
- package/dist/grading/grade.js +57 -0
- package/dist/guards/answer-confirmation.d.ts +41 -0
- package/dist/guards/answer-confirmation.js +109 -0
- package/dist/guards/evaluator.d.ts +130 -0
- package/dist/guards/evaluator.js +1258 -0
- package/dist/guards/harness-adapter.d.ts +17 -0
- package/dist/guards/harness-adapter.js +57 -0
- package/dist/guards/host.d.ts +8 -0
- package/dist/guards/host.js +10 -0
- package/dist/guards/invocation-parser.d.ts +66 -0
- package/dist/guards/invocation-parser.js +595 -0
- package/dist/guards/local-identity.d.ts +44 -0
- package/dist/guards/local-identity.js +129 -0
- package/dist/guards/policy-change.d.ts +43 -0
- package/dist/guards/policy-change.js +159 -0
- package/dist/guards/policy-pin.d.ts +13 -0
- package/dist/guards/policy-pin.js +177 -0
- package/dist/guards/protected-locations.d.ts +62 -0
- package/dist/guards/protected-locations.js +461 -0
- package/dist/guards/read-only.d.ts +37 -0
- package/dist/guards/read-only.js +315 -0
- package/dist/init/command.d.ts +41 -0
- package/dist/init/command.js +330 -0
- package/dist/init/derive.d.ts +53 -0
- package/dist/init/derive.js +819 -0
- package/dist/init/draft.d.ts +140 -0
- package/dist/init/draft.js +1228 -0
- package/dist/init/render.d.ts +47 -0
- package/dist/init/render.js +104 -0
- package/dist/init/scaffold.d.ts +53 -0
- package/dist/init/scaffold.js +121 -0
- package/dist/invocation.d.ts +13 -0
- package/dist/invocation.js +20 -0
- package/dist/package-metadata.d.ts +9 -0
- package/dist/package-metadata.js +19 -0
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.js +88 -0
- package/dist/references/named.d.ts +24 -0
- package/dist/references/named.js +27 -0
- package/dist/refusal.d.ts +15 -0
- package/dist/refusal.js +7 -0
- package/dist/registry-derivation.d.ts +31 -0
- package/dist/registry-derivation.js +32 -0
- package/dist/registry-resolve/command.d.ts +47 -0
- package/dist/registry-resolve/command.js +226 -0
- package/dist/registry-resolve/registry.d.ts +68 -0
- package/dist/registry-resolve/registry.js +292 -0
- package/dist/registry-resolve/render-shell.d.ts +18 -0
- package/dist/registry-resolve/render-shell.js +36 -0
- package/dist/repair.d.ts +29 -0
- package/dist/repair.js +8 -0
- package/dist/repository-path.d.ts +9 -0
- package/dist/repository-path.js +16 -0
- package/dist/schema-json.d.ts +1 -0
- package/dist/schema-json.js +177 -0
- package/dist/schema.d.ts +1289 -0
- package/dist/schema.js +985 -0
- package/dist/setup/command.d.ts +4 -0
- package/dist/setup/command.js +4 -0
- package/dist/sha256.d.ts +1 -0
- package/dist/sha256.js +4 -0
- package/dist/surfaces/adoption.d.ts +41 -0
- package/dist/surfaces/adoption.js +217 -0
- package/dist/surfaces/consumer-instructions.d.ts +20 -0
- package/dist/surfaces/consumer-instructions.js +43 -0
- package/dist/surfaces/contract.d.ts +42 -0
- package/dist/surfaces/contract.js +169 -0
- package/dist/surfaces/core-declarations.d.ts +24 -0
- package/dist/surfaces/core-declarations.js +79 -0
- package/dist/surfaces/development-markers.d.ts +1 -0
- package/dist/surfaces/development-markers.js +18 -0
- package/dist/surfaces/generator-adapter.d.ts +71 -0
- package/dist/surfaces/generator-adapter.js +809 -0
- package/dist/surfaces/harness-registry.d.ts +260 -0
- package/dist/surfaces/harness-registry.js +146 -0
- package/dist/surfaces/mcp.d.ts +145 -0
- package/dist/surfaces/mcp.js +349 -0
- package/dist/surfaces/merge.d.ts +30 -0
- package/dist/surfaces/merge.js +105 -0
- package/dist/surfaces/ownership.d.ts +190 -0
- package/dist/surfaces/ownership.js +795 -0
- package/dist/surfaces/projection.d.ts +136 -0
- package/dist/surfaces/projection.js +716 -0
- package/dist/surfaces/render.d.ts +79 -0
- package/dist/surfaces/render.js +636 -0
- package/dist/surfaces/restrictions.d.ts +130 -0
- package/dist/surfaces/restrictions.js +447 -0
- package/dist/surfaces/selftest.d.ts +162 -0
- package/dist/surfaces/selftest.js +393 -0
- package/dist/surfaces/skill-contract.d.ts +85 -0
- package/dist/surfaces/skill-contract.js +449 -0
- package/dist/surfaces/sync.d.ts +57 -0
- package/dist/surfaces/sync.js +164 -0
- package/dist/team-metadata.d.ts +41 -0
- package/dist/team-metadata.js +513 -0
- package/dist/testing/gates.d.ts +91 -0
- package/dist/testing/gates.js +182 -0
- package/dist/testing/hooks.d.ts +59 -0
- package/dist/testing/hooks.js +139 -0
- package/dist/testing/test-protection.d.ts +34 -0
- package/dist/testing/test-protection.js +137 -0
- package/dist/testing/verdict.d.ts +29 -0
- package/dist/testing/verdict.js +62 -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 +6 -0
- package/dist/work-orders/application.js +223 -0
- package/dist/work-orders/composition.d.ts +101 -0
- package/dist/work-orders/composition.js +1202 -0
- package/dist/work-orders/contract.d.ts +77 -0
- package/dist/work-orders/contract.js +140 -0
- package/dist/work-orders/decisions.d.ts +23 -0
- package/dist/work-orders/decisions.js +55 -0
- package/dist/work-orders/store.d.ts +207 -0
- package/dist/work-orders/store.js +291 -0
- package/docs/README.md +68 -0
- package/docs/architecture.md +136 -0
- package/docs/capability-matrix.md +58 -0
- package/docs/cli-reference.md +807 -0
- package/docs/command-list.md +62 -0
- package/docs/compose-patterns.md +99 -0
- package/docs/concepts.md +173 -0
- package/docs/configuration-essentials.md +177 -0
- package/docs/configuration-reference.md +636 -0
- package/docs/docs-check.md +76 -0
- package/docs/environment.md +948 -0
- package/docs/extending.md +43 -0
- package/docs/faq.md +113 -0
- package/docs/getting-started.md +692 -0
- package/docs/harness-surfaces.md +500 -0
- package/docs/joining-a-team.md +76 -0
- package/docs/release-policy.md +49 -0
- package/docs/safety-and-autonomy.md +463 -0
- package/docs/troubleshooting.md +382 -0
- package/docs/tutorial.md +171 -0
- package/docs/work-and-browser.md +420 -0
- package/libexec/browser-operation.cjs +270 -0
- package/libexec/fence-marker.cjs +101 -0
- package/libexec/fence-marker.d.cts +24 -0
- package/libexec/fenced-group-runner.cjs +77 -0
- package/libexec/fenced-supervisor.cjs +137 -0
- package/libexec/generated-filesystem.cjs +731 -0
- package/libexec/install-filesystem.cjs +225 -0
- package/libexec/rulesync-generator.NOTICE.md +1112 -0
- package/libexec/rulesync-generator.cjs +743 -0
- package/libexec/surface-generator-worker.cjs +266 -0
- package/libexec/surface-output-reader.cjs +99 -0
- package/libexec/surface-scratch-cleanup.cjs +14 -0
- package/libexec/validate-harness-evidence.d.mts +183 -0
- package/libexec/validate-harness-evidence.mjs +1312 -0
- package/package.json +74 -4
- package/surfaces/README.md +33 -0
- package/surfaces/agents/evaluator.agent.md +76 -0
- package/surfaces/guards/bash-guard.sh +48 -0
- package/surfaces/guards/claude.adapter.json +25 -0
- package/surfaces/guards/codex.adapter.json +24 -0
- package/surfaces/guards/opencode.adapter.json +25 -0
- package/surfaces/references/browser.md +63 -0
- package/surfaces/references/test-data-and-personas.md +84 -0
- package/surfaces/references/testing-tiers.md +11 -0
- package/surfaces/skills/cockpit-browser.skill.md +59 -0
- package/surfaces/skills/cockpit-explain.skill.md +32 -0
- package/surfaces/skills/cockpit-fix.skill.md +37 -0
- package/surfaces/skills/cockpit-setup.skill.md +39 -0
- package/surfaces/skills/cockpit-work.skill.md +34 -0
- package/surfaces/skills/collection.json +5 -0
- package/surfaces/skills/procedures/explain.md +66 -0
- package/surfaces/skills/procedures/fix.md +95 -0
- package/surfaces/skills/procedures/setup.md +452 -0
- package/surfaces/skills/procedures/work.md +134 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owns the text edits `sibling add` and `sibling remove` make to cockpit.toml: append one
|
|
3
|
+
* `[[sibling]]` table, delete one table with its sub-tables, or switch one `acquire = "none"`
|
|
4
|
+
* row to a recorded remote.
|
|
5
|
+
*
|
|
6
|
+
* It edits lines and leaves every other byte alone, so comments and formatting elsewhere in the
|
|
7
|
+
* file survive. It does not judge the result: `verified-write.ts` re-parses the edited file through
|
|
8
|
+
* the real schema and refuses anything that is not exactly the intended change. A layout this
|
|
9
|
+
* module cannot locate rows in (an inline `sibling = [...]` array, dotted keys) is refused by name
|
|
10
|
+
* rather than guessed at.
|
|
11
|
+
*/
|
|
12
|
+
const HEADER = /^\s*(\[\[?)\s*([^\]]+?)\s*\]\]?\s*(?:#.*)?$/;
|
|
13
|
+
/** Remove strings and comments so bracket counting sees only structure. */
|
|
14
|
+
function structuralText(line) {
|
|
15
|
+
let out = '';
|
|
16
|
+
let quote = null;
|
|
17
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
18
|
+
const char = line[index];
|
|
19
|
+
if (quote !== null) {
|
|
20
|
+
if (quote === '"' && char === '\\')
|
|
21
|
+
index += 1;
|
|
22
|
+
else if (char === quote)
|
|
23
|
+
quote = null;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (char === '"' || char === "'")
|
|
27
|
+
quote = char;
|
|
28
|
+
else if (char === '#')
|
|
29
|
+
break;
|
|
30
|
+
else
|
|
31
|
+
out += char;
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
function delimiterCount(line, delimiter) {
|
|
36
|
+
return line.split(delimiter).length - 1;
|
|
37
|
+
}
|
|
38
|
+
/** Every table header outside multi-line strings and open arrays, by zero-based line. */
|
|
39
|
+
export function scanHeaders(lines) {
|
|
40
|
+
const headers = [];
|
|
41
|
+
let multiline = null;
|
|
42
|
+
let depth = 0;
|
|
43
|
+
for (const [line, text] of lines.entries()) {
|
|
44
|
+
if (multiline !== null) {
|
|
45
|
+
if (delimiterCount(text, multiline) % 2 === 1)
|
|
46
|
+
multiline = null;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const match = depth === 0 ? HEADER.exec(text) : null;
|
|
50
|
+
if (match) {
|
|
51
|
+
headers.push({ line, array: match[1] === '[[', path: match[2] });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
for (const delimiter of ['"""', "'''"]) {
|
|
55
|
+
if (multiline === null && delimiterCount(text, delimiter) % 2 === 1)
|
|
56
|
+
multiline = delimiter;
|
|
57
|
+
}
|
|
58
|
+
if (multiline !== null)
|
|
59
|
+
continue;
|
|
60
|
+
const structure = structuralText(text);
|
|
61
|
+
depth = Math.max(0, depth + (structure.match(/[[{]/g)?.length ?? 0) - (structure.match(/[\]}]/g)?.length ?? 0));
|
|
62
|
+
}
|
|
63
|
+
return headers;
|
|
64
|
+
}
|
|
65
|
+
const isSiblingRow = (header) => header.array && header.path === 'sibling';
|
|
66
|
+
const isSiblingSubtable = (header) => /^sibling\s*\./.test(header.path);
|
|
67
|
+
function locateSiblingTables(text) {
|
|
68
|
+
const lines = text.split('\n');
|
|
69
|
+
const headers = scanHeaders(lines);
|
|
70
|
+
const locations = [];
|
|
71
|
+
for (const [index, header] of headers.entries()) {
|
|
72
|
+
if (!isSiblingRow(header))
|
|
73
|
+
continue;
|
|
74
|
+
let nextOwn = lines.length;
|
|
75
|
+
let next = lines.length;
|
|
76
|
+
for (const following of headers.slice(index + 1)) {
|
|
77
|
+
if (nextOwn === lines.length)
|
|
78
|
+
nextOwn = following.line;
|
|
79
|
+
if (isSiblingSubtable(following))
|
|
80
|
+
continue;
|
|
81
|
+
next = following.line;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
// Blank lines and comments just before the next header introduce that header, not this row.
|
|
85
|
+
let end = next - 1;
|
|
86
|
+
while (end > header.line && /^\s*(?:#.*)?$/.test(lines[end]))
|
|
87
|
+
end -= 1;
|
|
88
|
+
locations.push({ start: header.line, end, ownKeysEnd: Math.min(nextOwn, end + 1) });
|
|
89
|
+
}
|
|
90
|
+
return locations;
|
|
91
|
+
}
|
|
92
|
+
const quote = (value) => JSON.stringify(value);
|
|
93
|
+
function siblingTable(row) {
|
|
94
|
+
return ['[[sibling]]',
|
|
95
|
+
`slug = ${quote(row.slug)}`,
|
|
96
|
+
`dir = ${quote(row.dir)}`,
|
|
97
|
+
...(row.remote === undefined ? [] : [`remote = ${quote(row.remote)}`]),
|
|
98
|
+
`mount = ${quote(row.mount)}`,
|
|
99
|
+
`acquire = ${quote(row.acquire)}`,
|
|
100
|
+
`var = ${quote(row.var)}`,
|
|
101
|
+
`toolchain = ${quote(row.toolchain)}`,
|
|
102
|
+
...(row.instruction_pointer === true ? ['instruction_pointer = true'] : []),
|
|
103
|
+
`purpose = ${quote(row.purpose)}`, ''].join('\n');
|
|
104
|
+
}
|
|
105
|
+
function unsupported(reason) {
|
|
106
|
+
return { kind: 'unsupported', reason };
|
|
107
|
+
}
|
|
108
|
+
/** `expected` is how many sibling rows the parsed configuration has; every one must be a `[[sibling]]` table. */
|
|
109
|
+
function locateAll(text, expected) {
|
|
110
|
+
const found = locateSiblingTables(text);
|
|
111
|
+
return found.length === expected ? found
|
|
112
|
+
: `found ${found.length} \`[[sibling]]\` tables for ${expected} parsed siblings; the file declares siblings some other way (an inline array or dotted keys) and cockpit will not guess at it`;
|
|
113
|
+
}
|
|
114
|
+
/** Placed after the last sibling row so the siblings stay together; the first row when the file has none. */
|
|
115
|
+
export function appendSiblingTable(text, row, existingRows) {
|
|
116
|
+
const located = locateAll(text, existingRows);
|
|
117
|
+
if (typeof located === 'string')
|
|
118
|
+
return unsupported(located);
|
|
119
|
+
const lines = text.split('\n');
|
|
120
|
+
const last = located.at(-1);
|
|
121
|
+
if (last === undefined) {
|
|
122
|
+
const separator = text.length === 0 || text.endsWith('\n\n') ? '' : text.endsWith('\n') ? '\n' : '\n\n';
|
|
123
|
+
return { kind: 'edited', text: `${text}${separator}${siblingTable(row)}` };
|
|
124
|
+
}
|
|
125
|
+
lines.splice(last.end + 1, 0, '', ...siblingTable(row).split('\n').slice(0, -1));
|
|
126
|
+
return { kind: 'edited', text: lines.join('\n') };
|
|
127
|
+
}
|
|
128
|
+
export function removeSiblingTable(text, index, existingRows) {
|
|
129
|
+
const located = locateAll(text, existingRows);
|
|
130
|
+
if (typeof located === 'string')
|
|
131
|
+
return unsupported(located);
|
|
132
|
+
const { start, end } = located[index];
|
|
133
|
+
const lines = text.split('\n');
|
|
134
|
+
let after = end + 1;
|
|
135
|
+
while (after < lines.length && lines[after].trim() === '')
|
|
136
|
+
after += 1;
|
|
137
|
+
const kept = [...lines.slice(0, start), ...lines.slice(after)];
|
|
138
|
+
// Removing the last table must not leave the blank line that separated it from the table before.
|
|
139
|
+
if (after >= lines.length) {
|
|
140
|
+
while (kept.length > 0 && kept.at(-1).trim() === '')
|
|
141
|
+
kept.pop();
|
|
142
|
+
kept.push('');
|
|
143
|
+
}
|
|
144
|
+
return { kind: 'edited', text: kept.join('\n') };
|
|
145
|
+
}
|
|
146
|
+
export function recordSiblingRemote(text, index, existingRows, remote) {
|
|
147
|
+
const located = locateAll(text, existingRows);
|
|
148
|
+
if (typeof located === 'string')
|
|
149
|
+
return unsupported(located);
|
|
150
|
+
const { start, ownKeysEnd } = located[index];
|
|
151
|
+
const lines = text.split('\n');
|
|
152
|
+
const own = (pattern) => lines.slice(start + 1, ownKeysEnd).flatMap((line, offset) => pattern.test(line) ? [start + 1 + offset] : []);
|
|
153
|
+
const acquire = own(/^\s*acquire\s*=\s*"none"\s*(?:#.*)?$/);
|
|
154
|
+
if (acquire.length !== 1)
|
|
155
|
+
return unsupported('the row has no single `acquire = "none"` line to switch; edit it by hand');
|
|
156
|
+
const dir = own(/^\s*dir\s*=/);
|
|
157
|
+
lines[acquire[0]] = lines[acquire[0]].replace('"none"', '"auto"');
|
|
158
|
+
lines.splice((dir[0] ?? acquire[0]) + 1, 0, `remote = ${quote(remote)}`);
|
|
159
|
+
return { kind: 'edited', text: lines.join('\n') };
|
|
160
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owns the text edit `tool add` and `tool remove` make to cockpit.toml: set the one `tools` line of
|
|
3
|
+
* the `[surfaces]` table, adding the table when the file has none. Every other byte is left alone.
|
|
4
|
+
* The verified write re-parses the result and refuses anything beyond that one change; a layout this
|
|
5
|
+
* module cannot locate the list in (a multi-line array, an inline or dotted `surfaces`) is refused by
|
|
6
|
+
* name rather than guessed at.
|
|
7
|
+
*/
|
|
8
|
+
import { type SiblingEdit } from './sibling-toml.js';
|
|
9
|
+
export declare function setSurfaceTools(text: string, tools: readonly string[]): SiblingEdit;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owns the text edit `tool add` and `tool remove` make to cockpit.toml: set the one `tools` line of
|
|
3
|
+
* the `[surfaces]` table, adding the table when the file has none. Every other byte is left alone.
|
|
4
|
+
* The verified write re-parses the result and refuses anything beyond that one change; a layout this
|
|
5
|
+
* module cannot locate the list in (a multi-line array, an inline or dotted `surfaces`) is refused by
|
|
6
|
+
* name rather than guessed at.
|
|
7
|
+
*/
|
|
8
|
+
import { scanHeaders } from './sibling-toml.js';
|
|
9
|
+
const TOOLS_KEY = /^\s*tools\s*=/;
|
|
10
|
+
const SINGLE_LINE_ARRAY = /^\s*tools\s*=\s*\[[^\]#]*\]\s*(#.*)?$/;
|
|
11
|
+
export function setSurfaceTools(text, tools) {
|
|
12
|
+
const line = `tools = [${tools.map(tool => JSON.stringify(tool)).join(', ')}]`;
|
|
13
|
+
const lines = text.split('\n');
|
|
14
|
+
const headers = scanHeaders(lines);
|
|
15
|
+
const firstHeader = headers[0]?.line ?? lines.length;
|
|
16
|
+
if (lines.slice(0, firstHeader).some(row => /^\s*surfaces\s*[.=]/.test(row))) {
|
|
17
|
+
return { kind: 'unsupported', reason: 'surfaces is written as a top-level inline table or dotted key, and cockpit edits only a [surfaces] table' };
|
|
18
|
+
}
|
|
19
|
+
const index = headers.findIndex(header => !header.array && header.path === 'surfaces');
|
|
20
|
+
if (index < 0) {
|
|
21
|
+
const separator = text.length === 0 || text.endsWith('\n\n') ? '' : text.endsWith('\n') ? '\n' : '\n\n';
|
|
22
|
+
return { kind: 'edited', text: `${text}${separator}[surfaces]\n${line}\n` };
|
|
23
|
+
}
|
|
24
|
+
const start = headers[index].line;
|
|
25
|
+
const end = headers[index + 1]?.line ?? lines.length;
|
|
26
|
+
const keys = lines.slice(start + 1, end).flatMap((row, offset) => TOOLS_KEY.test(row) ? [start + 1 + offset] : []);
|
|
27
|
+
if (keys.length === 0) {
|
|
28
|
+
lines.splice(start + 1, 0, line);
|
|
29
|
+
return { kind: 'edited', text: lines.join('\n') };
|
|
30
|
+
}
|
|
31
|
+
const current = SINGLE_LINE_ARRAY.exec(lines[keys[0]]);
|
|
32
|
+
if (keys.length > 1 || !current) {
|
|
33
|
+
return { kind: 'unsupported', reason: 'the [surfaces] tools list is not written on one line as tools = [...]' };
|
|
34
|
+
}
|
|
35
|
+
lines[keys[0]] = current[1] === undefined ? line : `${line} ${current[1]}`;
|
|
36
|
+
return { kind: 'edited', text: lines.join('\n') };
|
|
37
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owns the text edit `confirm` makes to cockpit.toml: drop one answer from the top-level
|
|
3
|
+
* `unconfirmed = [...]` line, or the whole line once the list empties. Every other byte, comments
|
|
4
|
+
* included, is left alone. The verified write re-parses the result and refuses anything beyond that
|
|
5
|
+
* change; a layout this module cannot locate the list in (a multi-line array, a list inside a table)
|
|
6
|
+
* is refused by name rather than guessed at.
|
|
7
|
+
*/
|
|
8
|
+
import { type SiblingEdit } from './sibling-toml.js';
|
|
9
|
+
export declare function removeUnconfirmedAnswer(text: string, answer: string): SiblingEdit;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owns the text edit `confirm` makes to cockpit.toml: drop one answer from the top-level
|
|
3
|
+
* `unconfirmed = [...]` line, or the whole line once the list empties. Every other byte, comments
|
|
4
|
+
* included, is left alone. The verified write re-parses the result and refuses anything beyond that
|
|
5
|
+
* change; a layout this module cannot locate the list in (a multi-line array, a list inside a table)
|
|
6
|
+
* is refused by name rather than guessed at.
|
|
7
|
+
*/
|
|
8
|
+
import { scanHeaders } from './sibling-toml.js';
|
|
9
|
+
const UNCONFIRMED_KEY = /^\s*unconfirmed\s*=/;
|
|
10
|
+
const SINGLE_LINE_ARRAY = /^(\s*unconfirmed\s*=\s*)\[([^\]#]*)\](\s*(?:#.*)?)$/;
|
|
11
|
+
export function removeUnconfirmedAnswer(text, answer) {
|
|
12
|
+
const lines = text.split('\n');
|
|
13
|
+
const firstHeader = scanHeaders(lines)[0]?.line ?? lines.length;
|
|
14
|
+
const keys = lines.slice(0, firstHeader).flatMap((row, index) => UNCONFIRMED_KEY.test(row) ? [index] : []);
|
|
15
|
+
const at = keys[0];
|
|
16
|
+
const current = at === undefined ? null : SINGLE_LINE_ARRAY.exec(lines[at]);
|
|
17
|
+
if (keys.length !== 1 || !current) {
|
|
18
|
+
return { kind: 'unsupported', reason: 'the unconfirmed list is not written on one line as unconfirmed = [...] before the first table' };
|
|
19
|
+
}
|
|
20
|
+
const rows = current[2].split(',').map(row => row.trim()).filter(row => row !== '');
|
|
21
|
+
const kept = rows.filter(row => row !== JSON.stringify(answer) && row !== `'${answer}'`);
|
|
22
|
+
if (kept.length === rows.length)
|
|
23
|
+
return { kind: 'unsupported', reason: `the unconfirmed list does not spell ${answer} as a plain string` };
|
|
24
|
+
if (kept.length === 0)
|
|
25
|
+
lines.splice(at, 1);
|
|
26
|
+
else
|
|
27
|
+
lines[at] = `${current[1]}[${kept.join(', ')}]${current[3]}`;
|
|
28
|
+
return { kind: 'edited', text: lines.join('\n') };
|
|
29
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** What failed and the remedy, kept apart so the remedy reaches the reader as the diagnostic's fix. */
|
|
2
|
+
export interface VerifiedWriteRefusal {
|
|
3
|
+
readonly message: string;
|
|
4
|
+
readonly fix: string;
|
|
5
|
+
}
|
|
6
|
+
export interface VerifiedWriteMessages {
|
|
7
|
+
/** Said when the file changed between the caller's read and the write. */
|
|
8
|
+
readonly changedBefore: VerifiedWriteRefusal;
|
|
9
|
+
/** Said when the file changed while the candidate was being prepared. */
|
|
10
|
+
readonly changedDuring: VerifiedWriteRefusal;
|
|
11
|
+
/** Said when the candidate does not parse; `reason` is the loader's own summary. */
|
|
12
|
+
readonly invalid: (reason: string) => VerifiedWriteRefusal;
|
|
13
|
+
/** Said when the candidate parses but is more than the intended change. */
|
|
14
|
+
readonly notExact: VerifiedWriteRefusal;
|
|
15
|
+
/** Said when re-reading the written file shows more than the intended change. */
|
|
16
|
+
readonly writtenMismatch: VerifiedWriteRefusal;
|
|
17
|
+
}
|
|
18
|
+
export interface VerifiedWriteInput {
|
|
19
|
+
readonly path: string;
|
|
20
|
+
/** Digest of the bytes the caller decided from; a different file on disk is never overwritten. */
|
|
21
|
+
readonly expectedSha256: string;
|
|
22
|
+
/** Names the temporary file (`.<name>.<tag>-<random>`). */
|
|
23
|
+
readonly temporaryTag: string;
|
|
24
|
+
readonly edit: (original: string) => string;
|
|
25
|
+
/** True only for a parsed configuration that is the caller's base plus exactly the intended change. */
|
|
26
|
+
readonly isExactChange: (config: unknown) => boolean;
|
|
27
|
+
readonly messages: VerifiedWriteMessages;
|
|
28
|
+
}
|
|
29
|
+
export type VerifiedWriteResult = Readonly<{
|
|
30
|
+
kind: 'complete';
|
|
31
|
+
}> | Readonly<{
|
|
32
|
+
kind: 'refused';
|
|
33
|
+
code: string;
|
|
34
|
+
message: string;
|
|
35
|
+
fix: string;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Write through a sibling temporary file and an atomic rename, so a reader sees the old or the new
|
|
39
|
+
* configuration and never half of one. The original's identity and digest are checked again just
|
|
40
|
+
* before the rename: the caller may have run for minutes, and an edit made meanwhile must not be
|
|
41
|
+
* overwritten.
|
|
42
|
+
*/
|
|
43
|
+
export declare function writeVerifiedConfig(input: VerifiedWriteInput): Promise<VerifiedWriteResult>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owns the one way cockpit rewrites an existing cockpit.toml: edit through a sibling temporary
|
|
3
|
+
* file, re-parse it through the real schema, accept it only when it is exactly the intended
|
|
4
|
+
* change, then rename it over the original.
|
|
5
|
+
*
|
|
6
|
+
* It does not decide what the edit is: callers supply the text edit and the predicate that
|
|
7
|
+
* recognises the intended change. It never spawns a process. Callers: `sibling add` /
|
|
8
|
+
* `sibling remove` and `sync --adopt`.
|
|
9
|
+
*/
|
|
10
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
11
|
+
import { constants } from 'node:fs';
|
|
12
|
+
import { lstat, mkdir, open, rename, rmdir, unlink } from 'node:fs/promises';
|
|
13
|
+
import { basename, dirname, join } from 'node:path';
|
|
14
|
+
import { ENVIRONMENT_CODES } from '../environment/contract.js';
|
|
15
|
+
import { loadCockpitConfig, readBoundedInput } from './load.js';
|
|
16
|
+
/**
|
|
17
|
+
* Write through a sibling temporary file and an atomic rename, so a reader sees the old or the new
|
|
18
|
+
* configuration and never half of one. The original's identity and digest are checked again just
|
|
19
|
+
* before the rename: the caller may have run for minutes, and an edit made meanwhile must not be
|
|
20
|
+
* overwritten.
|
|
21
|
+
*/
|
|
22
|
+
export async function writeVerifiedConfig(input) {
|
|
23
|
+
const { path, expectedSha256, messages } = input;
|
|
24
|
+
const refuse = (code, refusal) => ({ kind: 'refused', code, ...refusal });
|
|
25
|
+
const before = await lstat(path);
|
|
26
|
+
if (!before.isFile() || before.isSymbolicLink())
|
|
27
|
+
return refuse(ENVIRONMENT_CODES.CONFIG_UNREADABLE, { message: 'cockpit.toml is not a regular file; nothing was written',
|
|
28
|
+
fix: 'replace the link or special file at the --config path with the cockpit.toml file itself, then run the command again' });
|
|
29
|
+
const read = await readBoundedInput(path);
|
|
30
|
+
if (read.kind !== 'complete')
|
|
31
|
+
return refuse(ENVIRONMENT_CODES.CONFIG_UNREADABLE, { message: 'cockpit.toml exceeds the input limit; nothing was written',
|
|
32
|
+
fix: 'cut cockpit.toml below the input limit by moving embedded data into the files it names, then run the command again' });
|
|
33
|
+
if (createHash('sha256').update(read.bytes).digest('hex') !== expectedSha256) {
|
|
34
|
+
return refuse(ENVIRONMENT_CODES.CONFIG_CHANGED_DURING_EXECUTION, messages.changedBefore);
|
|
35
|
+
}
|
|
36
|
+
const next = input.edit(read.bytes.toString('utf8'));
|
|
37
|
+
// Keep the candidate's basename equal to the real configuration name. Declared provenance
|
|
38
|
+
// may intentionally name cockpit.toml without observed_on; validating it under a random
|
|
39
|
+
// temporary basename would reject bytes that become valid at the atomic destination.
|
|
40
|
+
const temporaryRoot = join(dirname(path), `.${basename(path)}.${input.temporaryTag}-${randomBytes(8).toString('hex')}`);
|
|
41
|
+
const temporary = join(temporaryRoot, basename(path));
|
|
42
|
+
let created = false;
|
|
43
|
+
let rootCreated = false;
|
|
44
|
+
try {
|
|
45
|
+
await mkdir(temporaryRoot, { mode: 0o700 });
|
|
46
|
+
rootCreated = true;
|
|
47
|
+
const handle = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, before.mode & 0o777);
|
|
48
|
+
created = true;
|
|
49
|
+
try {
|
|
50
|
+
await handle.writeFile(next);
|
|
51
|
+
await handle.sync();
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
await handle.close();
|
|
55
|
+
}
|
|
56
|
+
const candidate = await loadCockpitConfig(temporary);
|
|
57
|
+
if (candidate.kind !== 'complete') {
|
|
58
|
+
return refuse(candidate.diagnostics[0]?.code ?? ENVIRONMENT_CODES.CONFIG_SCHEMA_INVALID, messages.invalid(candidate.diagnostics[0]?.message ?? 'unreadable'));
|
|
59
|
+
}
|
|
60
|
+
if (!input.isExactChange(candidate.result.config))
|
|
61
|
+
return refuse(ENVIRONMENT_CODES.CONFIG_SCHEMA_INVALID, messages.notExact);
|
|
62
|
+
const current = await lstat(path);
|
|
63
|
+
const recheck = await readBoundedInput(path);
|
|
64
|
+
if (current.dev !== before.dev || current.ino !== before.ino || current.size !== before.size || current.mtimeMs !== before.mtimeMs
|
|
65
|
+
|| recheck.kind !== 'complete' || createHash('sha256').update(recheck.bytes).digest('hex') !== expectedSha256) {
|
|
66
|
+
return refuse(ENVIRONMENT_CODES.CONFIG_CHANGED_DURING_EXECUTION, messages.changedDuring);
|
|
67
|
+
}
|
|
68
|
+
await rename(temporary, path);
|
|
69
|
+
created = false;
|
|
70
|
+
const directory = await open(dirname(path), constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
71
|
+
try {
|
|
72
|
+
await directory.sync();
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
await directory.close();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
if (created)
|
|
80
|
+
await unlink(temporary);
|
|
81
|
+
if (rootCreated)
|
|
82
|
+
await rmdir(temporaryRoot);
|
|
83
|
+
}
|
|
84
|
+
const written = await loadCockpitConfig(path);
|
|
85
|
+
if (written.kind !== 'complete' || !input.isExactChange(written.result.config)) {
|
|
86
|
+
return refuse(ENVIRONMENT_CODES.CONFIG_CHANGED_DURING_EXECUTION, messages.writtenMismatch);
|
|
87
|
+
}
|
|
88
|
+
return { kind: 'complete' };
|
|
89
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Diagnostic, type SetupRefusalEvidence } from './environment/contract.js';
|
|
2
|
+
import type { InvocationRecord } from './invocation.js';
|
|
3
|
+
import { type FixContext } from './fix-catalogue.js';
|
|
4
|
+
export type { Diagnostic } from './environment/contract.js';
|
|
5
|
+
interface HumanReviewOutcome {
|
|
6
|
+
readonly status: number;
|
|
7
|
+
readonly result: unknown;
|
|
8
|
+
readonly diagnostics?: readonly Diagnostic[];
|
|
9
|
+
}
|
|
10
|
+
interface HumanReviewContext {
|
|
11
|
+
readonly command: string | undefined;
|
|
12
|
+
readonly outcome: HumanReviewOutcome;
|
|
13
|
+
}
|
|
14
|
+
export declare function renderHumanValue(value: unknown): string;
|
|
15
|
+
export declare function renderHumanDiagnostics(diagnostics: readonly Diagnostic[], review?: HumanReviewContext, fixContext?: FixContext, usageHint?: string): string;
|
|
16
|
+
export declare function renderJsonResponse(outcome: {
|
|
17
|
+
result: unknown;
|
|
18
|
+
diagnostics: readonly Diagnostic[];
|
|
19
|
+
evidence?: SetupRefusalEvidence;
|
|
20
|
+
invocation?: InvocationRecord;
|
|
21
|
+
progress?: Readonly<{
|
|
22
|
+
applied: readonly string[];
|
|
23
|
+
notApplied: readonly string[];
|
|
24
|
+
attempted?: readonly string[];
|
|
25
|
+
}>;
|
|
26
|
+
}, fixContext?: FixContext): string;
|