Skip to content

hyp status shows a permanent 'attach openclaw [pending]', 'not attached', and an inert client_attach_missing repair for probe-less clients #544

Description

@bgmcmullen

On a joined host with @hypaware/openclaw enabled, hyp status reports three things that can never resolve:

  clients:
    - openclaw  [configured, not attached]  [local]
  client actions:
    - attach openclaw  [pending]
  diagnostics:
    [WARN ] client_attach_missing: '@hypaware/openclaw' is enabled but openclaw settings show no HypAware marker - run 'hyp attach --client openclaw'

Nothing is actually broken: routing is owned by the steering plugin (LLP 0152 / 0159) and the adapter intentionally declares no attachProbe and writes no marker (LLP 0143). But the pending is permanent, the not attached rendering is misleading (the honest answer is "not applicable"), and the printed repair is inert: hyp attach --client openclaw resolves the adapter's deliberate no-op (hypaware-core/plugins-workspace/openclaw/src/index.js, the LLP 0143 block) and writes no marker either, so running it clears nothing. Raised post-merge on PR #510 (#510 (comment)).

Root cause: status derives declared-attach targets by a different rule than the reconciler

The reconciler's desired() skips probe-less descriptors, exactly as LLP 0143 intends:

// src/core/config/action_attach.js:114
if (!descriptor.attachProbe) continue

So no attach target is ever emitted for openclaw, perform() never runs, and no marker is ever written. But three status surfaces derive against the attach contract without that gate:

  1. buildClientActionsReport builds declaredAttach from every enabled client descriptor on a joined host, with no attachProbe check (src/core/daemon/status.js:889-901); at status.js:945-947 no marker + declared + hasCentral resolves to pending, permanently.
  2. The clients row maps a probe-less descriptor to { attached: false } (status.js:591-593), rendering not attached where nothing is attachable.
  3. The client_attach_missing diagnostic fires on configured && !probe.attached, ungated (status.js:604), and its fallback repair is the inert generic attach when the picker declares no configure_command.

The doc comment above buildClientActionsReport already states the intended invariant, "pending / n/a are derived for declared targets the reconciler would act on but has not yet", so this is a missed gate, not a design choice.

Not new to PR #510

attach claude-desktop [pending] shows the same way, since Desktop dropped its probe first (LLP 0115 #no-attach-on-join, #444 / #445). The OpenClaw adapter just makes it a second instance.

Suggested fix

Gate all three surfaces on descriptor.attachProbe: a probe-less client renders n/a rather than pending, is not shown as not attached, and does not raise client_attach_missing. That keeps status agreeing with desired() the same way readAttachPolicy / readBackfillPolicy already keep the two sides from disagreeing about on_join.

Refs: LLP 0044 (attach status surface), LLP 0143 (no attach probe for openclaw), LLP 0115, #444, #445, PR #510.

Metadata

Metadata

Assignees

No one assigned

    Labels

    neutral:fixDelegate this issue to neutral for an autonomous fix attempt (reproduce -> fix -> PR)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions