Repair containment validation history
- Status: historical; completed July 2026
- Owner: ClawSweeper maintainers
- Source of truth: the linked merged PRs, workflow runs, containment tests, and
- Last verified:
openclaw/clawsweeper@9c32c14c65b0551b43a10c2086c0031338ae41e7 - Update when: only to correct this historical record or point to a superseding
current repair operations reference
active containment reference
#Purpose
This historical handoff records how Linux repair-containment failures were moved from live repair jobs into deterministic local tests and a non-mutating production-runner smoke check. The work completed in July 2026; active containment behavior belongs in the implementation, tests, and repair operations documentation rather than this record.
This document does not authorize live apply/close operations or changes to external pull-request branches.
#Current status
Completed. PRs #596, #598, #599, and #602 are merged. The checked items below are retained as decision history, not outstanding work.
- PR openclaw/clawsweeper#596
- Repair workers on the same merged SHA subsequently failed in the Landlock ABI
- run 29418723701
- run 29419775915
- run 29420021518
- PR openclaw/clawsweeper#598
- Its green CI does not execute the unsupported-Landlock fallback path. The
- Two naturally dispatched repair workflows on the merged SHA completed
- run 29423502149
- run 29423499463
fixed exact-review lease contention handling and added a legacy readonly remount fallback when mount_setattr(2) returns ENOSYS.
capability probe, most likely syscall 444 (landlock_create_ruleset):
merged on 2026-07-15 and makes Landlock an optional defense-in-depth layer only when its capability probe returns ENOSYS or EOPNOTSUPP. Other probe errors, ABI versions below 3, and later Landlock operations remain fail closed.
ubuntu-latest job skips the critical Linux containment integration tests because its availability helper requires both delegated namespaces and Landlock ABI 3+: CI job 87373830736.
successfully, but their execute jobs were skipped, so they did not exercise the containment preflight:
#Completed two-PR execution plan
This section preserves the executed cross-session plan and its evidence.
#PR 1: deterministic policy and one compiled preflight
Status: PR openclaw/clawsweeper#599 merged as 98c8c4bdc613bd452e8c55ccb8bf1ec29907b8fd. Node 24 validation and autoreview completed with no actionable findings before merge.
Combine the code-owned work behind one authoritative containment implementation:
- make the embedded Python definitions importable while preserving the
- execute the real Landlock fallback and fail-closed decision table in
- gate Linux integration coverage on delegated namespaces rather than Landlock
- report safe stage, syscall, and errno diagnostics plus a capability summary;
- expose one compiled
repair:containment-smokeCLI for workflow callers.
production python3 -c entrypoint;
deterministic tests;
availability;
This PR must not add a new runner job, change repair/apply authority, or perform live repair mutations.
#PR 2: production-runner smoke workflow
Status: PR openclaw/clawsweeper#602 merged as cd68a14528558cbc26932629c4bce49f314269b0 on 2026-07-15. Its pull-request workflow supplied the authoritative two-sample Blacksmith proof because the Crabbox hydration workflow did not contain a Blacksmith Testbox action.
Remote proof for code commit 53304c7ce452e6accc2e0edc866c8131d7900c19: Actions run 29432924949 completed both matrix jobs on distinct Blacksmith Actions runners blacksmith-scale2-01kxk9vc8hkwy8gwphs6gpwxwg-16vcpu and blacksmith-scale2-01kxk9yxny7j6vxrax1hyxmt2j-16vcpu. Both reported mount_readonly=native landlock=unavailable. This proof used Blacksmith Actions, not Testbox-through-Crabbox, so it has no tbx_... Testbox ID.
- run the compiled CLI on
blacksmith-16vcpu-ubuntu-2404with two independent - replace the existing repair worker's inline Node preflight with the same
- trigger only for containment runtime, tests, CLI, or relevant workflow changes;
- use no repository or organization secrets and grant only read permissions;
- fail when containment is skipped or unavailable;
- do not dispatch repair, push branches, apply results, or close items.
runner samples;
compiled CLI;
The initial workflow admits pushes to main, manual dispatches, and same-repository pull requests. Fork pull requests are skipped until the fresh ephemeral VM and no-secrets contract has independent evidence.
Before enabling pull-request execution from forks, prove that Blacksmith uses a fresh ephemeral VM and exposes no repository or organization secrets. Otherwise restrict the workflow to trusted branches or the existing trusted remote validation path.
#Evidence-backed test gaps closed by PR 1
test/repair/command-runner.test.ts previously used linuxValidationContainmentAvailable() to gate the real Linux containment tests. PR 1 replaced that with a namespace-only availability probe, so the unsupported-Landlock mount fallback now executes instead of skipping.
test/repair/process-tree-containment.test.ts previously protected the fallback boundary only with source-text assertions. PR 1 now imports the authoritative embedded runtime and executes its syscall decision path deterministically.
The runtime is also difficult to test and diagnose because the path spans:
.github/workflows/repair-cluster-worker.ymlsrc/repair/contained-command-worker.ts- the embedded Python in
src/repair/process-tree-containment.ts - host kernel syscalls and provider seccomp policy
The containment protocol previously reported only an exception string, so both syscall 442 and syscall 444 surfaced as the same generic [Errno 38] Function not implemented message. PR 1 replaced that with validated stage, syscall, and errno fields.
#Completed work
#P0: deterministic fallback tests
- [x] Make the actual embedded Python definitions importable without executing
- [x] Exercise the real
landlock_abi()decision logic with an injected or - [x] Cover this decision table:
main(), while preserving the production python3 -c entrypoint.
monkey-patched syscall adapter; do not duplicate the decision in a TypeScript-only model.
| Probe/result | Required behavior |
|---|---|
syscall 444 returns ENOSYS | select mount-only fallback |
syscall 444 returns EOPNOTSUPP | select mount-only fallback |
probe returns EPERM, EACCES, or EINVAL | fail closed |
| probe returns ABI below 3 | fail closed |
| probe returns ABI 3 or newer | create and apply the Landlock ruleset |
| ruleset creation, add-rule, or restrict-self fails | fail closed |
- [x] Split namespace availability from Landlock availability in
- [x] Keep assertions that the sandbox exposes only configured writable roots,
linuxValidationContainmentAvailable(). When delegated namespaces are usable but Landlock is unavailable, run the mount-only containment tests instead of skipping them.
hides host paths and /run, drops all capabilities, isolates networking, and reaps descendant processes.
#P1: production-equivalent non-mutating smoke check
- [x] Add a narrowly scoped
containment-smokeCI job or workflow using the - [x] Run the compiled containment preflight only. Do not dispatch a repair,
- [x] Trigger it only when the containment worker, its tests, or the relevant
- [x] Run two independent runner samples because the observed Blacksmith
- [x] In this production-compatible job, treat a skipped containment test as a
same blacksmith-16vcpu-ubuntu-2404 runner class as repair execution.
push target branches, apply results, close items, or use target write credentials.
workflow surface changes.
fleet exposed different capabilities for the same ClawSweeper SHA.
failure rather than a green result.
Before enabling this job for fork pull requests, verify that it runs on a fresh ephemeral VM with no repository or organization secrets. If that contract is not proven, restrict the job to trusted branches or use the existing trusted remote-validation path.
#P1: actionable containment diagnostics
- [x] Report the failing containment stage, syscall number, and errno without
- [x] Distinguish at least
mount_setattr, legacy remount, - [x] Emit a safe capability summary such as
mount_readonly=native|legacyand - [x] Preserve fail-closed behavior for every mandatory containment stage.
including local paths, command contents, or secrets.
landlock_capability_probe, ruleset creation, add-rule, restrict-self, namespace setup, and capability drop.
landlock=abi-N|unavailable from the smoke preflight.
#P2: reduce workflow/runtime duplication
- [x] Move the inline Node preflight in
- [x] Keep workflow YAML responsible for orchestration and gates, not the
- [x] Preserve one authoritative copy of the Python runtime. Do not create a
.github/workflows/repair-cluster-worker.yml behind one compiled, locally callable CLI so workflow and local tests execute the same probe.
containment implementation.
separate test-only implementation that can drift from production.
#Capability policy to preserve
Mandatory containment remains:
- delegated user, mount, PID, and requested network namespaces;
- chroot and the minimal runtime bind mounts;
- recursive readonly mount policy with only explicit writable roots;
- host-path and write-escape preflight checks;
- capability bounding, effective, permitted, inheritable, and ambient sets all
- descendant process containment and reaping.
dropped;
Landlock may be optional only as defense in depth after the mandatory mount write allowlist is established and verified. An unsupported capability probe may choose the fallback; an operational failure after Landlock is known to be available must still fail closed.
#Acceptance criteria
- The unsupported-Landlock path is executed deterministically in local tests;
ENOSYScan be attributed to a named syscall and stage from one failure log.- A non-mutating check runs the real compiled worker on the production runner
- Critical containment coverage cannot silently turn green by skipping all
- Node 24 validation passes:
it is not proven solely with regular-expression assertions.
class before merge, or the documented trusted equivalent is used.
environment-dependent tests.
``bash corepack enable pnpm install pnpm run check ``
- Run autoreview before publishing the follow-up PR.
- After merge, observe naturally scheduled repair workers. Do not manually run
live apply/close and do not pause the sweep workflow.
#Out of scope
- Changes to
openclaw/clawsweeper-state; its dashboard/schema work is - Direct edits to external OpenClaw contributor branches.
- Weakening mandatory isolation merely to accommodate a runner.
- Requiring OpenClaw contributors to modify
CHANGELOG.md.
independent of repair containment.