Skip to content

fix: ~/ paths in list-entry includes and placeholder values point under the env root after migrate - #983

Merged
shakkernerd merged 9 commits into
mainfrom
migrate-tilde-deferred-cases
Nov 2, 2026
Merged

shakkernerd merged 9 commits into
mainfrom
migrate-tilde-deferred-cases

Conversation

@shakkernerd

@shakkernerd shakkernerd commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Refs #972

What Problem This Solves

Fixes: ~/... path values in includes placed at a list position and ~/... path values containing a ${VAR} placeholder point under the new environment root after ocm migrate or ocm adopt import, and home-relative trust roots and worker folders change meaning without any warning.

#946 made migration spell out ~/... config paths that point outside ~/.openclaw, because a migrated environment runs with OPENCLAW_HOME set to its root and OpenClaw expands a leading ~ against OPENCLAW_HOME before HOME. It deliberately left four cases as written and tracked them in #972:

  • Values in an include placed at a list position, for example skills.load.extraDirs: [{"$include": "./dir.json"}]. Include scopes were recorded as plain strings, so once arrays from several includes are concatenated a list index could not be told apart from a digit-only object key, and fix: ~/ config paths outside ~/.openclaw point at missing locations after migrate #946 treated every recorded segment as a key.
  • Values containing a ${VAR} placeholder, such as ~/${SKILLS_DIR}/shared. OpenClaw substitutes placeholders before it resolves the path, so resolving .. before substitution could pick a different directory.
  • The trust roots skills.load.allowSymlinkTargets and security.installPolicy.exec.trustedDirs. After migration a ~/... entry names a directory under the environment root, so it stops trusting what the plain install trusted.
  • nodeHost.workerRuns.folders, the folders a node host lets workers use. OpenClaw's check (src/node-host/node-worker-device-folder.ts) replaces the leading ~ and then calls fs.realpathSync.native.

On current main all four are copied verbatim and silently resolve under the environment root. For example, migrating a home with skills.load.extraDirs: [{"$include": "./skills-dir.json"}], where the include holds "~/listdir", leaves an environment whose skills directory is <env root>/listdir. Both commands exit 0 and nothing says so.

User Impact

User impact: after ocm migrate or ocm adopt import, path values in list-entry includes and placeholder paths keep naming the directories the plain install used, and every home-relative value migration cannot safely carry over is named in a warning instead of changing meaning silently.

  • Includes at a list position. Path values in an include placed at a list position, including in arrays concatenated from several includes, are now rewritten like any other path value. A digit-only object key such as "0" under paths is still not treated as a list entry.
  • Placeholders. In a value containing a ${VAR} placeholder, only the literal directories before the first placeholder are resolved; the placeholder and everything after it stay as written for OpenClaw to substitute and resolve. ~/${SKILLS_DIR}/shared becomes <home>/${SKILLS_DIR}/shared, treated exactly like its absolute spelling, so a placeholder that itself leads into ~/.openclaw names the source's state directory, as <home>/${X} already would. A placeholder value under ~/.openclaw, such as ~/.openclaw/${SUB}/skills, stays as written so it keeps naming the environment's copy, and migration warns, because a placeholder such as SUB=.. could still lead outside ~/.openclaw. The same applies to a placeholder value that reaches ~/.openclaw through a symlink, such as ~/alias/${SUB} with alias linking to ~/.openclaw: migration's later relocation of state paths would treat the placeholder as a directory name, while OpenClaw substitutes it before resolving ... An escaped $${VAR}, which OpenClaw reads as the literal text ${VAR}, does not split the value, but a spelled-out value containing it gets the same relocation check, because OpenClaw unescapes it before resolving the path.
  • Trust roots are not rewritten. Spelling out a trust root would change what the new environment trusts, so skills.load.allowSymlinkTargets and security.installPolicy.exec.trustedDirs keep their ~/... entries as written, as before. Migration now warns about each such setting whose entries resolve differently.
  • Worker folders are not rewritten. nodeHost.workerRuns.folders keeps every ~/... entry exactly as on main, and migration now warns about the setting. These entries are a permission boundary resolved through symlinks, and migration itself can change the links and directories they resolve through: it copies the state directory into the environment, relocates absolute state paths into the copy, and imports a linked or external workspace as workspaces/default. Earlier revisions of this PR spelled worker entries out and guarded the result, and each revision still had a layout in which the written entry admitted a folder the plain install rejected (a directory next to the environment, the imported workspace, a missing directory). Keeping the entry and saying so is the only choice that never makes migration grant access the plain install did not; the remaining gap stays open in migrate still leaves ~/ in nodeHost.workerRuns.folders and in list-entry includes of concatenated arrays #972.

The warnings go to stderr like the existing migration warnings, one per setting, with [] standing for a list entry; --json output is unchanged:

warning: env demo keeps the ~/ entries of trust root skills.load.allowSymlinkTargets[] as written; they now resolve under the env root instead of the source home, so OCM did not carry that trust over. Replace them with absolute paths to keep trusting the original directories
warning: env demo keeps the ~/ entries of nodeHost.workerRuns.folders[] as written; OpenClaw now resolves them against the env root, so workers may be allowed or refused different folders than before. Replace them with absolute paths to keep the original folders
warning: env demo keeps the ~/ entries of skills.load.extraDirs[] that contain a ${VAR} placeholder and point into ~/.openclaw as written; if a placeholder leads them outside ~/.openclaw, they now resolve under the env root instead of the source home. Replace such entries with absolute paths

Entries under ~/.openclaw and absolute entries of the trust roots produce no warning; absolute worker folders and worker entries that are not home-relative (OpenClaw does not trim them) produce none either. Environments that already exist are not touched: the rewrite runs only while migrate or adopt import creates an environment. env clone, env export and env import are unchanged.

A copied include used both at a position that is spelled out and at one that is kept, for example one file included as a skills.load.extraDirs entry and as a trust-root entry, cannot be rewritten for one and kept for the other. Migration refuses it with the existing shared-include message, as it already does for includes shared between differently handled settings. Before this change both uses were left as written.

Why This Change Was Made

  • Include traversal now records whether each scope step is an object key or a list index. The include reader already knows this when it descends into an array or object, before arrays from several includes are merged, so it now records typed steps instead of strings. Every reader of include scopes uses them: migration's ~ expansion relies on the type, and the Gateway port, plugin load path and agent directory rewrites compare each step by its spelling exactly as before, so their behavior does not change.
  • The settings rule now says how each setting is handled. Settings OpenClaw resolves lexically keep fix: ~/ config paths outside ~/.openclaw point at missing locations after migrate #946's expansion. The trust roots and nodeHost.workerRuns.folders are marked as kept, and the expansion reports each kept setting whose entries may now resolve elsewhere, together with placeholder values it keeps under ~/.openclaw. The CLI prints one warning per reported setting.
  • Placeholder values are split before the first placeholder. OpenClaw's config loader resolves includes, then substitutes ${VAR}, then expands ~ and resolves the path. Replacing the leading ~ and resolving only the literal directories before the placeholder gives the same result after substitution, whatever the placeholder holds, as long as nothing later rewrites the value. Migration's relocation of absolute state paths runs afterwards and follows links, so a spelled-out placeholder value that relocation would move is kept as written and reported instead; the expansion asks that same relocation, on a scratch copy of the value, before writing. A value that resolves to the filesystem root, such as ~/../.. from a two-level home, is spelled /.

docs/USAGE.md replaces the list of cases that were not rewritten with these rules, the warnings and the worker-folder limit, and CHANGELOG.md has an Unreleased entry.

Evidence

Before and after. A Linux debug build (main at 31fc297, then this branch), isolated HOME and OCM_HOME, migrated a home whose config has worker folders ["~/work", "~/hop/../work2", "~/.openclaw/wf"], hooks built from two concatenated includes where b.json places {"$include": "./p.json"} ("~/bin") at a list entry, skills.load.extraDirs: [{"$include": "./skills-dir.json"}, "~/${SKILLS_SUB}/shared"], logging.file: "~/${LOG_NAME}.log", and the two trust roots as ~/.... Each value was then resolved the way OpenClaw resolves it, for the plain install with HOME and for the environment with the OPENCLAW_HOME reported by ocm env exec. ocm migrate and ocm adopt import gave identical results:

Value Plain install Migrated, main Migrated, this PR
list-entry include ~/bin <home>/bin <env root>/bin <home>/bin
list-entry include ~/listdir <home>/listdir <env root>/listdir <home>/listdir
~/${SKILLS_SUB}/shared <home>/sk/shared <env root>/sk/shared <home>/sk/shared
~/${LOG_NAME}.log <home>/gw.log <env root>/gw.log <home>/gw.log
trust roots ~/trusted, ~/bin <home>/… <env root>/…, silent <env root>/…, warning names both settings
worker folders ~/work, ~/hop/../work2 <home>/… <env root>/…, silent <env root>/…, warning names the setting
worker folder ~/.openclaw/wf source state env copy env copy, same warning

Tests. tests/migrate_command_tests.rs, each case through both migrate and adopt import:

  • migrate_and_adopt_expand_home_relative_paths_in_includes_at_list_entries (replaces the test that asserted the old spelling): a skills.load.extraDirs list-entry include, and the concatenated hooks includes where a digit-only "0" key under paths stays as written while the list-entry include is expanded.
  • migrate_and_adopt_expand_home_relative_paths_with_placeholders_before_substitution: placeholders after the home, after .., inside a file name, under ~/.openclaw (kept, with exactly one warning naming skills.load.extraDirs[]), and in message text (kept, no warning).
  • migrate_and_adopt_keep_home_relative_trust_roots_and_name_them: both trust roots kept, including an entry from a list-entry include with whitespace that OpenClaw trims, and exactly one warning per setting.
  • migrate_and_adopt_keep_placeholder_paths_that_lead_into_the_state_dir_through_a_link: ~/alias/${SUB} through a link to ~/.openclaw is kept and named, while ~/shared/${SUB} is spelled out.
  • migrate_and_adopt_name_trust_roots_with_placeholders_under_the_state_dir: ~/.openclaw/${...} trust-root entries, one from a list-entry include, are kept and named.
  • migrate_and_adopt_do_not_name_trust_roots_that_keep_their_meaning: ~/.openclaw/... and absolute trust roots produce no warning.
  • migrate_and_adopt_keep_worker_folders_and_name_them: ~/work, ~/hop/../work (through a symlink), ~/.openclaw/wf, a placeholder entry, a whitespace-prefixed entry and an absolute entry all stay byte-for-byte as written, with exactly one warning.
  • migrate_and_adopt_do_not_name_absolute_worker_folders: absolute and non-home-relative worker entries produce no warning.
  • migrate_and_adopt_refuse_an_include_shared_by_a_path_list_and_a_trust_root: one list-entry include used as a skills.load.extraDirs entry and as a trust root is refused with the shared-include message, and the source file is untouched.
  • The existing broad test now asserts that nodeHost.workerRuns.folders: ["~/work"] stays as written.

Unit tests in src/store/openclaw_config.rs pin the placeholder split and the $${VAR} escape, values resolving to the filesystem root (no panic, /), the rule for each setting, the setting names used in warnings, and that include traversal records the list index for p.json in the concatenated layout.

Review corrections. Review of earlier revisions found that skills.load.extraDirs: ["~/../../../../../../../.."] made migration panic (exit 101; it now becomes /), that ~/.openclaw/${SUB}/../../shared was kept silently (it now produces the placeholder warning), that ~/alias/${SUB} through a link to ~/.openclaw was relocated so that SUB=../external named <env root>/external instead of <home>/external (it is now kept and named), that ~/$${X}/skills with a $${X} link into ~/.openclaw was relocated although OpenClaw reads it as ~/${X}/skills (it is now kept and named), and several layouts in which a spelled-out worker folder admitted a folder the plain install rejected. Each was reproduced through ocm migrate against OpenClaw's own worker-folder check at a7fe06b17a9; the worker-folder cases led to keeping those entries as written, as described above.

Upgrade compatibility. OCM v0.3.8 (the latest release) migrated a home with a list-entry include, a placeholder path, a trust root, a worker folder, a session store and a workspace file. This build then ran env list, env status, env exec (reading the workspace file and the session store back), and env clone on that environment; all succeeded, and every file in the environment was byte-identical before and after. A new ocm migrate of the same home with this build succeeded and printed the worker-folder and trust-root warnings. The rewrite runs only while migrate or adopt import creates an environment, so existing environments are never changed.

Checks on Linux for this commit: git diff --check, cargo fmt --check, cargo check --workspace --all-targets --locked, cargo test --locked --lib store::, and every integration test file that uses config includes: migrate_command_tests, dev_command_tests, env_import_tests, env_export_plugin_path_tests, env_clone_tests, env_snapshot_tests, env_status_tests, launcher_help_tests, shell_init_tests, start_command_tests, upgrade_checkpoint_scope_tests and upgrade_command_tests. On the first revision runtime_command_tests had 89 passed and runtime_build_local_preserves_native_companion_dependency_bindings failed with Cannot find module 'external-bridge'; it fails the same way on main 31fc297 on that machine and does not involve config rewriting. The full Linux, macOS and Windows suites run in hosted CI on this PR.

Limits. OpenClaw's resolution for the rewritten settings is applied from its source rules (resolveConfigEnvVars, materializeRuntimeConfig, expandHomePrefix), not by starting a Gateway. A placeholder whose value leads into ~/.openclaw from outside it is not detected, and names the source's state directory, as the value's absolute spelling already does. Worker folders and trust roots keep their main behavior and are only reported, so #972 stays open for them.

…nt under the env root after migrate

`ocm migrate` and `ocm adopt import` now also keep `~/...` values in `nodeHost.workerRuns.folders`, in includes placed at a list position and in values containing a `${VAR}` placeholder pointing at the location the plain install used. Home-relative trust roots in `skills.load.allowSymlinkTargets` and `security.installPolicy.exec.trustedDirs` stay as written, and migration now warns that they resolve under the new environment root.

Fixes #972.
@clawsweeper

clawsweeper Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

…lders, handle root paths

A `~/.openclaw/...` value with a `${VAR}` placeholder stays as written and is now named in a migration warning, because the placeholder may lead outside the state directory. A worker folder under `~/.openclaw` whose `..` does not lead to an existing directory stays as written, so OpenClaw keeps rejecting it instead of the copied target. A value resolving to the filesystem root no longer panics.
…missing directory

A worker folder whose `..` leaves `~/.openclaw` is spelled out again, so it keeps naming the plain install's target instead of a directory under the env root. Only an entry the later relocation would move into the copied state although its source path does not resolve stays as written. Placeholder entries in trust roots are covered by tests, and a list-entry include shared by a path list and a trust root is pinned as refused.
Migration can change the copied state's links and directories, for example when it imports a linked workspace, so a worker folder whose `..` or placeholder leads into `~/.openclaw` cannot be spelled out to the same target. It now stays as written and migration prints a warning naming nodeHost.workerRuns.folders. Entries the state relocation leaves alone are still spelled out against the source home.
Migration can change the links and directories a worker folder resolves through, and OpenClaw uses that folder as a permission boundary, so `nodeHost.workerRuns.folders` entries are no longer spelled out or relocated. Every home-relative entry stays exactly as on main and migration prints a warning naming the setting. The limit is documented in USAGE and stays open in #972.
@shakkernerd shakkernerd changed the title fix: ~/ worker folders, list-entry include paths and placeholder paths point under the env root after migrate fix: ~/ paths in list-entry includes and placeholder values point under the env root after migrate Nov 2, 2026
… link

A spelled-out placeholder value that leads into `~/.openclaw` through a symlink would be relocated into the env as if the placeholder were a directory name, while OpenClaw substitutes it before resolving `..`. Such values stay as written and are named in the placeholder warning. An escaped `$${VAR}` is no longer treated as a placeholder.
OpenClaw unescapes `$${X}` to the literal `${X}` before resolving a path, so a spelled-out value whose `$${X}` component is a link into `~/.openclaw` would be relocated to the wrong directory. The relocation guard now covers every value containing `${`, escaped or not. USAGE and CHANGELOG name placeholder values that reach `~/.openclaw` through a symlink.
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Nov 2, 2026
@clawsweeper

clawsweeper Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex review: needs maintainer review before merge.

What this changes

This PR preserves home-relative paths in list-entry includes and placeholder values during migration, and warns about settings deliberately kept unchanged.

Example: Alice migrates a home where skills.load.extraDirs includes skills-dir.json containing "~/listdir".

  • Before: The copied value resolves to the new environment's listdir directory.
  • After: The copied value becomes /home/alice/listdir and retains its original target.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The scoped patch is sound and supported by CLI and upgrade evidence; overall coverage remains partial relative to the linked issue.
Proof confidence 🐚 platinum hermit (4/6) Sufficient (live_output): The PR reports isolated Linux runs through migrate and adopt import, with resolved before-and-after path results and warning controls; the added v0.3.8 upgrade scenario exercises existing settings, workspace data and session data without modifying their files.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Product

Kind: Bug fix · Worth it: Yes · Fix scope: Partial
User problem: Migration silently redirects some configured directories from the source home into the managed environment.
Reason: The maintainer-authored repair restores supported path behavior without widening worker permissions; its linked issue appropriately remains open for the remaining cases.

Merge readiness

✅ Ready for maintainer review

Keep this PR open: it provides a useful migration fix absent from current main, with no actionable introduced defect found.

Priority: P2
Reviewed head: 1e3533d39ec32b06c8e61fd48c8fabe6ea4c4a67

Before merge

None.

Findings

None.

Tests

  • Missing end-to-end proof: The committed regression tests are not explicitly shown failing on the base; the supplied CLI before-and-after results establish the changed behavior.
Agent review details

How this fits together

OCM's shared migration writer receives copied OpenClaw configuration and include scopes, rewrites paths for the new environment, and returns warnings to the migrate and adopt import CLI handlers.

flowchart LR
A[Plain OpenClaw home] --> B[Migration copy]
B --> C[Typed include traversal]
C --> D[Home path rewrite]
D --> E[Existing state relocation]
E --> F[Managed environment config]
D --> G[CLI warnings]
Loading

Technical review

Best possible solution:

Land the scoped migration repair through the existing include and rewrite owners, retaining the separate permission-preservation follow-up.

Do we have a high-confidence way to reproduce the issue?

Current-main source leaves list-entry include scopes untyped and skips placeholder paths; the PR supplies matching CLI before-and-after results, while this read-only review ran no target code.

Is this the best way to solve the issue?

Recording segment types during include traversal fixes the ambiguity at its owner, and placeholder expansion preserves substitution order while reusing existing relocation checks.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 779c5cc648f2.

Provenance checked

  • Home-relative migration expansion changes intended behavior with a stated reason (83e44c1: Preserve external path targets while deferring ambiguous include positions, placeholders and permission-sensitive roots.)
  • Include scopes and agent-directory rewrites keeps the original intent (5d47ee7: Track include mount scopes to preserve configured agent directories without changing unrelated shared consumers.)
  • Included Gateway port rewriting keeps the original intent (42b5f0b: Give migrated environments their assigned Gateway port even when configuration comes from includes.)
  • Projected include reads keeps the original intent (e9fe46b: Preserve authored included settings while enforcing caller-supplied include-read authority.)

Testing

Proof path: shipped entry point.

Security

None.

Evidence

What I checked:

  • Pinned introduction and current-main comparison: Reviewed all eight introduced files against the pinned base; current main still lacks the typed include scopes, placeholder expansion and kept-setting warnings. (src/store/openclaw_config.rs:240, 1e3533d39ec3)
  • Complete behavior and upgrade evidence: The complete PR body reports isolated Linux migrate/adopt before-and-after results and a v0.3.8-created environment exercised with env list, status, exec and clone, preserving existing environment files byte-for-byte; this addresses the previous review's upgrade request. (1e3533d39ec3)
  • Accepted permission-boundary limit: The maintainer-authored direction explicitly retains worker-folder and trust-root spellings, adds warnings, and leaves their unresolved preservation problem in migrate still leaves ~/ in nodeHost.workerRuns.folders and in list-entry includes of concatenated arrays #972 rather than claiming a complete fix. (src/store/openclaw_config.rs:360, 1e3533d39ec3)
  • Authoritative dependency contract: OCM explicitly derives its path rules and proof from this OpenClaw revision, establishing the dependency-policy signal; inspected its root policy, environment substitution, materialization, home expansion and worker-folder validation contracts. (src/config/materialize.ts, a7fe06b17a96)
  • Feature history and original intent: History identifies the existing migration expansion owner and the earlier include-scope, agent-directory and port-rewrite contracts; fix: ~/ config paths outside ~/.openclaw point at missing locations after migrate #946 explicitly deferred the cases this PR addresses. One follow-history traversal reached an unavailable old blob, without affecting the inspected introduction commits. (src/store/openclaw_config.rs, 779c5cc648f2)
  • Current-head validation: All 14 reported checks completed successfully for the reviewed head, including formatting, Rust minimum-version coverage, Linux/macOS tests and Windows compilation. (1e3533d39ec3)

Labels

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.

Label justifications:

  • P2: The defect affects specific migration configurations with list-entry includes or placeholder paths.
  • merge-risk: 🚨 compatibility: Newly migrated configuration changes spelling, and an include shared between differently handled settings can now be refused; the maintainer-authored direction explicitly documents and accepts that tradeoff.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.
  • proof: sufficient: Contributor real behavior proof is sufficient.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (1 earlier review cycle)
  • reviewed 2026-11-02T12:43:22.629Z sha 4065c0d :: blocked before merge. :: none

Reviewed November 2, 2026, 9:11 AM ET / 14:11 UTC (Revision 2).

@shakkernerd

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Nov 2, 2026
@shakkernerd
shakkernerd merged commit 52a2c76 into main Nov 2, 2026
14 checks passed
@shakkernerd
shakkernerd deleted the migrate-tilde-deferred-cases branch November 2, 2026 14:13
@shakkernerd

Copy link
Copy Markdown
Contributor Author

Fixed: ocm migrate and ocm adopt import now keep ~/ paths in list-entry includes and placeholder values pointing at the plain install's locations, and warn about the home-relative trust roots, worker folders and placeholder paths they keep as written.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant