feat(health): surface instanceId on health snapshot (Phase D2.1)#12
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]>
Adds an optional `instanceId` field to `HealthSummary`. When the harness's `OpenClawConfig.instanceId` is set, the health snapshot includes it (under `instanceId`); when unset (Tier A single-user default), the field is omitted. This lets dashboards and the relay-side health probe identify which Bench instance a heartbeat belongs to without reaching back into the harness config. Depends on the top-level `instanceId` field from PR #11. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
3 tasks
Surfaced by Codex Anvil (PR #12 smoke 20260428T080048Z): 1. The Tier A test only checked `snap.instanceId === undefined`, which wouldn't catch `instanceId: undefined` set explicitly on the object (defeating the conditional-spread design). Tightened to also check `"instanceId" in snap === false` so accidental shape regressions surface. 2. The Control UI's typed gateway HealthSummary (`ui/src/ui/types.ts`) didn't include the new optional field, which would have made TS consumers reject snapshots emitting it. Added `instanceId?: string`. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
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
Adds an optional
instanceIdfield toHealthSummary. WhenOpenClawConfig.instanceIdis set, the snapshot includes it; when unset (Tier A single-user default), the field is omitted via conditional spread.Why
Phase D2.1 — relay-side health/heartbeat probes need to identify which Bench instance a harness belongs to without reaching back into the config file. Surfacing on
HealthSummaryis the cheapest path.Changes
src/commands/health.ts: conditional spread ofinstanceIdinto the snapshot whencfg.instanceIdis set.src/commands/health.types.ts: typedinstanceId?: stringonHealthSummarywith doc comment.src/commands/health.snapshot.test.ts: 2 new tests (Tier A omits, Phase D2.1 surfaces).Stacked PR
This PR is stacked on top of #11 (
feat(config): top-level instanceId field). Once #11 merges, GitHub will auto-rebase this PR ontomain.Test plan
pnpm vitest run src/commands/health.snapshot.test.ts— 6 tests pass🤖 Generated with Claude Code
Anvil Handoff
instanceId?: stringonHealthSummary. Conditional spread...(cfg.instanceId ? { instanceId } : {})so Tier A heartbeats omit the field rather than emitinstanceId: undefined. Stacked on feat(config): top-level instanceId field (Phase D2.1 foundation) #11.src/commands/health.ts,src/commands/health.types.ts,src/commands/health.snapshot.test.tspnpm vitest run src/commands/health.snapshot.test.ts→ 6 passed (2 new: Tier A omits, Phase D2.1 surfaces). Pre-commit green.HealthSummaryis consumed externally (relay-side health probe + monorepo dashboards). Adding an optional field is backward-compatible by spec, but downstream zod validators with.strict()would reject. Need to confirm relay-side parser tolerates the new shape.HealthSummary(relay, web app, dashboards) and verify the schema is permissive of the new optional field. Confirm test coverage distinguishes "field absent" from "field present and undefined" — the omit-via-spread pattern is intentional.