Command responsibilities and migration

The public grammar is wecom-channel-cli <resource> <action>. A command's resource, state owner, output and side effects determine its place in the tree. Operator authority comes from the private socket and policy, never from a noun, flag, alias or the fact that a command appears in help.

Canonical tree

wecom-channel-cli
  channel   list
  member    list
  post      list | get | propose
  reply     list | get | propose
  reaction  types | list | propose
  search    start | get
  event     list | get | context | watch
  relay     run | status | claim | consume | resolve
  proposal  list | get | approve | reject | resolve
  policy    example | validate
  broker    serve
  config    path | get-contexts | set-context | use-context | delete-context
  auth      guide | check
  skill     show | path | status | install
  doctor
  version

This inventory omits Cobra's built-in help/completion. The generated reference is authoritative for flags and examples.

Surface Primitive and result Authority / state owner
channel list, member list Discover channels/members in one bounded page Broker policy; explicit channel list --bot-id is credential-based operator bootstrap
post/reply list Retrieve a bounded page of current content Broker read scope
post/reply get Retrieve current content for an exact known ID Broker read scope
reaction types Discover the offline native emoji enum No network or credentials
reaction list Inspect current reaction membership on one target General or exact-mention read scope
post/reply/reaction propose Build and persist one immutable intent; no remote action Agent socket can propose; action-specific fields stay with the resource
proposal get Inspect the intent and current execution/reconciliation state Agent or operator socket within allowed scope
proposal list/approve/reject/resolve Enumerate retained proposals, execute an approved pending intent, reject, or record a verified uncertain outcome Private operator socket; resolve never resends
search start Initiate a server-side search and return its job identity Observation through broker; not a host/agent job
search get --job Read one bounded page of that search's results Same broker context as the search
event list/get Read retained observation/mention metadata once Broker ledger; these commands do not listen
event context Read the post and exact reply authorized by a fresh human mention Mention-specific permission, unlike general content browsing
event watch Stream bounded observations to NDJSON Consumer checkpoint records successful output, not processing
relay run Collect, queue, filter, batch and deliver to one configured host adapter Separate trusted service; optional durable queue, explicit ACK or documented HTTP acceptance
relay status Inspect sender delivery or worker claims Read-only local files, no network or liveness probe
relay claim Atomically claim new batch/event IDs before work Worker-owned state; no sender credentials; no automatic reclaim
relay consume Report processed/failed for a matching claim Idempotent worker report; does not send channel content
relay resolve Record verified host outcome for an uncertain batch Trusted sender operator; never guess from a timeout
policy example/validate Generate or validate broker authorization policy offline Operator-owned configuration; neither command installs it
broker serve Run the credential-holding service from that policy Isolated broker identity
config ... Manage local connection coordinates and selected context Client configuration; never changes broker permissions
auth guide Explain credential ownership and bootstrap Offline
auth check Perform a bounded upstream authentication check Private operator socket; remote I/O
doctor Check local broker readiness and read-only policy Does not verify upstream authentication
skill ..., version Inspect/install agent guidance and report build identity Local software metadata; installation is an explicit local write

Choosing an observation primitive

Use event list/get for a one-time inspection of retained events, event watch for a bounded foreground stream, and relay run for unattended change delivery. A relay is a stateful service with its own queue and lifecycle, so its status belongs under relay, not under event. There is one broker scan path behind watch and relay; neither adds a second upstream observation engine.

event context deliberately stays separate from post/reply get: it expresses the narrower permission granted by a fresh authenticated human mention. It is not an alternative to config contexts and does not fetch arbitrary history. Likewise, propose creates an intent while approve executes it; combining them into a generic send command would conceal the independent operator boundary.

The three resource-specific proposal commands remain because text, replies and native reactions have different target and validation rules. Their resulting resource has one lifecycle under proposal. There is no separately stored approval resource to list. Native reaction types and the family's conventional config *-context verbs are intentional vocabulary, not reasons to add synonyms.

Audit findings and fixes

Previous ambiguity Resolution
event relay and compound event relay-status mixed event reads with a service lifecycle relay run/status; run --config names the service config
config mixed client connection state and operator authorization policy config owns client contexts; policy example/validate owns offline policy tooling
proposal get versus approval list split a single stored resource All proposal lifecycle actions are discoverable under proposal; private-socket gates remain
auth status returned exactly the same readiness response as doctor One canonical readiness command, doctor; auth check explicitly tests upstream credentials
search result used a result noun as a retrieval action search get --job, with pagination retained
Generic help described exact reads, job initiation and mention context as the same page read Operation-specific summaries, precise discovery paths and accurate per-command limits
Explicit --limit 0 silently became the API default Usage error before broker access; content pages accept 1–50, search result pages 1–20, retained events/proposals 1–100

The rewrite changes CLI routing, documentation and local input validation, not the broker protocol. Existing approval.* and search.result operation names remain wire compatibility details. Both CLI routes use the same command factories and therefore the same request builders, socket checks, dry runs and write gates.

Published compatibility

Published path Canonical path
config example, config validate policy example, policy validate
approval list/approve/reject/resolve proposal list/approve/reject/resolve
auth status doctor
search result search get

Published paths remain callable with their existing data and authorization semantics. They emit a structured stderr notice with deprecated_command and replacement, and are hidden from ordinary help, completion and generated reference. Consumers should already separate stderr notices from stdout data. There is no scheduled removal in this change; removal requires a documented compatibility release. New examples and Skills use only canonical paths.

The earlier relay paths existed only in this unreleased change. They are replaced directly: use relay run --config FILE --state FILE and relay status --state FILE. Its queue and webhook schema remain version 1, so a locally tested queue can resume through the new command without discarding state.

Family applicability

The seven maintained siblings and the kit were compared. All use the shared resource/action, config-context, error and output conventions. Jenkins log follow and OpenObserve tail are streams; Confluence watch changes a remote notification subscription; Calendar sync maintains a mirror; Bitbucket activity, Jira worklogs and Prometheus queries are bounded reads. These are different primitives and are not renamed to pretend they implement durable host delivery. The fx adapters do not call the channel-specific paths changed here. Shared host-integration design and migration guidance live in the workspace's event-driven agent integration guide.