Skip to content

[Feature]: Vendor-neutral lifecycle export for terminal agent multiplexers #10167

Description

@JordanTheJet

Summary

Expose ZeroClaw agent lifecycle state through vendor-neutral terminal and hook interfaces so terminal multiplexers can integrate without vendor-specific code in ZeroClaw's core or runtime harness.

Problem statement

ZeroClaw has no generic way to tell a terminal agent multiplexer that an interactive agent is idle, working, blocked on approval, finished, or exiting.

PR #8337 fills that gap for Herdr by compiling Herdr's environment variables and Unix-socket protocol directly into zeroclaw-runtime. The implementation is careful, but the boundary does not generalize. Supporting Superset, Orca, or another multiplexer with the same pattern would require another in-tree client, protocol, and lifecycle-delivery implementation for every vendor.

The products use different rich-status mechanisms:

  • Superset treats managed lifecycle hooks as authoritative and uses terminal titles for display rather than status authority.
  • Orca treats managed hooks and IPC as authoritative, with title recognition as fallback and a proprietary structured OSC envelope for richer state.
  • Herdr uses lifecycle hooks or plugins when an agent exposes complete events, and screen or OSC manifests when hooks are incomplete.

OSC is the common terminal baseline, but it is not a complete structured-status contract. Gateway SSE is useful for remote monitoring, but it requires a running and authenticated gateway, none of these multiplexers consumes another agent's SSE feed natively, and ZeroClaw's current BroadcastObserver drops the authorization and completion variants added by #8337.

This integration is useful but niche, so its disabled path should cost nothing and its common path should not require polling, a gateway, or a vendor SDK.

Proposed solution

Define one vendor-neutral lifecycle state mapper and project it through two opt-in sinks:

  1. Emit OSC 2 titles and OSC 9;4 progress on semantic state changes as the zero-configuration terminal baseline.
  2. Add configured external command hooks that receive a versioned, content-free JSON lifecycle payload on stdin when a multiplexer or other local consumer needs structured state.

Use the same canonical state for both sinks so they cannot drift. Multiplexers own adapters that translate the generic payload into their own pane identity, authentication, endpoint, notification, and persistence model. ZeroClaw should contain no Herdr, Superset, Orca, or other vendor protocol constants.

The initial lifecycle vocabulary should cover:

  • session started and ended;
  • turn started and completed;
  • tool started, with an optional tool name but no arguments;
  • approval requested and responded;
  • semantic states idle, working, blocked, and done;
  • session and turn correlation on every state-changing event.

Payloads must exclude prompts, model responses, tool arguments and results, credentials, memory content, and unrestricted metadata.

Suggested delivery sequence:

  1. Finish and extract feat(zerocode): report turn state to the terminal over OSC title and progress #9876's OSC implementation, including supported termination-signal cleanup and interactive CLI coverage.
  2. Prove the terminal path live with Herdr while keeping the emitted sequences multiplexer-agnostic.
  3. Add the bounded external command-hook sink at the approved hooks boundary.
  4. Let multiplexers install or own their adapters.
  5. Add SSE or WIT projections later only when a concrete remote or plugin consumer needs them.

Non-goals / out of scope

Alternatives considered

  • Merge feat(observability): herdr agent reporting integration #8337 as-is: richest immediate Herdr integration, but it adds about 1,757 lines of vendor-specific code and establishes a per-vendor core-module pattern.
  • OSC only: universal and inexpensive for terminal state, but insufficient for durable identity, structured correlation, or authoritative rich status in every multiplexer.
  • SSE only: structured and remotely consumable, but gateway-dependent, not native to the three multiplexers, and incomplete for the required events today.
  • WASM plugin only: a clean long-term direction, but no executable observer or hook world currently exposes the complete live lifecycle. RFC: WASM plugin lifecycle observer subscriptions (PluginCapability::Observer) #7822's initial completion-only event cannot represent blocked state.
  • Screen scraping only: keeps ZeroClaw small, but duplicates fragile UI parsing in each multiplexer.

Acceptance criteria

  • One canonical lifecycle mapper defines the supported events, states, correlation, and content-free payload.
  • OSC emission occurs only on semantic state changes, with no polling or idle worker.
  • OSC titles are bounded and control-character sanitized; progress is cleared and prior title state is restored on supported graceful teardown paths.
  • The OSC path works in a bare terminal without a gateway or any multiplexer installed.
  • feat(zerocode): report turn state to the terminal over OSC title and progress #9876 or its successor is demonstrated live through Herdr using only generic OSC output.
  • Structured command hooks use argv arrays and JSON stdin, are disabled by default, and have bounded queues, timeouts, output, and concurrency.
  • Hook failure is observable but cannot fail or cancel the agent turn.
  • Conformance tests prove that terminal, command-hook, and any later SSE or WIT projections derive from the same semantic state.
  • Tests prove lifecycle payloads exclude prompts, arguments, results, credentials, and memory.
  • No multiplexer name, environment variable, endpoint, authentication rule, or wire method is compiled into the generic producer.
  • Disabled-path overhead is effectively zero; working updates are deduplicated or coalesced.

Architecture impact

The likely surfaces are apps/zerocode, the interactive CLI, and the generic hooks boundary. crates/zeroclaw-runtime is a transitional holding crate whose local guidance says not to add new functionality, so the reusable contract should land at an approved stable boundary rather than as another vendor integration there.

Related work:

Risk and rollback

External command execution expands the trust boundary. Require explicit configuration, argv arrays, absolute executable validation, no shell interpolation, event allowlists, and bounded timeout, output, queue, and concurrency. Configured hooks run with local-user authority and must be documented that way.

OSC output can leave stale terminal state or accept unsafe text. Sanitize control characters, pin exact bytes in tests, cover supported termination signals, clear progress, and restore the previous title where supported. SIGKILL cleanup remains impossible and should be documented.

Multiple projections can drift. Keep one canonical mapper and shared conformance fixtures.

Rollback is additive: disable configured lifecycle hooks and OSC emission, then revert the implementation PRs. The first iteration requires no migration of persisted user data or existing APIs.

Expected routing

Ordinary feature triage

Next decision surface

Use this issue to scope the canonical lifecycle boundary and its narrow implementation PRs. Use #9876 as the first terminal proof, then reconcile #8337 against the vendor-neutral path. Architecture details can be reviewed on the implementation PRs; promote this issue only if the work later crosses a documented RFC trigger.

Breaking change?

No

Data hygiene checks

  • I removed personal/sensitive data from examples, payloads, and logs.
  • I used neutral, project-focused wording and placeholders.

Activity

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

Metadata

Metadata

Assignees

Labels

cliconfigAuto scope: src/config/** changed.domain:architectureArchitecture domaindomain:securitySecurity domainenhancementNew feature or requestpriority:p2Medium priorityrisk:highTrust, credential, compatibility, governance, release-authority, or security boundary.runtimeAuto scope: src/runtime/** changed.status:in-progressOpen PR actively targets this issue; recheck when PR closes.zerocodeAuto scope: apps/zerocode/** changed.

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions