feat(claude-code-bridge): cloud-mirror reads instanceId for per-vault scoping (Phase D2.1)#14
Merged
Merged
Conversation
Adds an optional `instanceId` field to OpenClawConfig. Validates 1-128 chars matching `[A-Za-z0-9_-]+` so the value can serve as a filesystem-safe path component. When set, downstream features (memory-wiki vault path, cloud-mirror state file, health snapshot, shard directory layout) scope per-instance resources to this id. When unset, single-user Tier A defaults apply. This is the foundation PR for Phase D2.1 (per-instance harness hardening); subsequent PRs surface the field on health, scope the memory-wiki vault, and update the cloud-mirror daemon. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
… scoping (Phase D2.1)
The cloud-mirror daemon now reads `instanceId` from
~/.openclaw/openclaw.json (or `BENCH_INSTANCE_ID` env override) and:
- Watches the per-instance vault dir (`~/.openclaw/wiki/{instanceId}/`)
instead of the hardcoded `main/`.
- Uses a per-instance state file
(`~/.openclaw/state/wiki-mirror.{instanceId}.json`) so switching
instanceId looks like a fresh sync rather than re-POSTing the
previous vault.
- Stamps each ingest payload with `sourceInstanceId` so the cloud
side (`/api/v1/wiki/ingest`) can attribute deltas to the correct
Bench instance.
InstanceId validation matches `src/config/zod-schema.ts`
(`/^[A-Za-z0-9_-]{1,128}$/`) — kept local because the daemon runs
without the TS toolchain. Falls back to `main` on any invalid input.
Depends on PR #11 (the field has to be valid in openclaw.json before
this daemon will see it).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
3 tasks
LightDriverCS
added a commit
that referenced
this pull request
Apr 28, 2026
Phase D2.1 foundation. Adds optional top-level instanceId to OpenClawConfig with strict regex /^[A-Za-z0-9_-]{1,128}$/ for filesystem-safe per-instance scoping. Stack of #12 (health), #13 (memory-wiki vault), #14 (cloud-mirror) follows.
Codex Anvil (gpt-5.5 xhigh) verdict: PASS. 54 tests pass; pnpm config:schema:check + pnpm config:docs:check both green. Repair patch from first smoke (regenerate config-baseline.sha256) applied as second commit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The cloud-mirror daemon now reads
instanceIdfrom~/.openclaw/openclaw.json(orBENCH_INSTANCE_IDenv override) and scopes its filesystem footprint per-instance.Why
Phase D2.1 — when multiple Bench instances eventually share infrastructure (Tier B local, Tier C cloud), the cloud-mirror daemon needs to:
~/.openclaw/wiki/).instanceIddoesn't re-POST the previous vault.sourceInstanceIdso the cloud side (/api/v1/wiki/ingest) can attribute deltas correctly.Changes
extensions/claude-code-bridge/cloud-mirror.mjs:readInstanceIdFromConfig()— readsinstanceIdfrom openclaw.json (env override first), validates against/^[A-Za-z0-9_-]{1,128}$/(local copy of the same regex used insrc/config/zod-schema.ts— daemon runs without TS toolchain).VAULT_DIRderived from~/.openclaw/wiki/{instanceId || "main"}/.wiki-mirror.{instanceId}.jsonwhen scoped,wiki-mirror.jsonotherwise.sourceInstanceId(when set) for upstream tagging.instanceId.Stacked PR
Stacked on #11. Once #11 merges, GitHub auto-rebases this onto
main.Test plan
BENCH_INSTANCE_ID=test-shard, verify~/.openclaw/state/wiki-mirror.test-shard.jsonis created when the daemon runs and deltas hit/api/v1/wiki/ingestwithsourceInstanceId: "test-shard".🤖 Generated with Claude Code
Anvil Handoff
.mjs, no TS) readsinstanceIdfrom~/.openclaw/openclaw.json(orBENCH_INSTANCE_IDenv override) at startup. Watches per-instance vault, uses per-instance state filewiki-mirror.{instanceId}.json, stampssourceInstanceIdon each ingest payload. Validation regex is a third local copy of[A-Za-z0-9_-]{1,128}. Stacked on feat(config): top-level instanceId field (Phase D2.1 foundation) #11.extensions/claude-code-bridge/cloud-mirror.mjsinstanceIdorphans the previouswiki-mirror.jsonstate and triggers a full re-POST of the new vault — confirm cloud-side/api/v1/wiki/ingesthandles re-POST of pre-existing slugs without duplicate creation. (2)BENCH_INSTANCE_IDenv override bypasses the openclaw.json check entirely; intentional for advanced/test scenarios but worth verifying it doesn't shadow operational misconfig. (3) Read-side bundle hooks need to honorsourceInstanceIdfor tenant scoping — confirm a pairedBenchAGI_Mono_Repo` PR is wired or in-flight.BENCH_INSTANCE_ID=test-shard node extensions/claude-code-bridge/cloud-mirror.mjs— verify (a)~/.openclaw/state/wiki-mirror.test-shard.jsonis created, (b) ingest payloads includesourceInstanceId: "test-shard". Diff the regex constants across this PR + feat(config): top-level instanceId field (Phase D2.1 foundation) #11 + feat(memory-wiki): scope vault path to instanceId (Phase D2.1) #13 byte-for-byte. Confirm thesourceInstanceIdfield name matches what the cloud-side ingest endpoint expects.