5
0
Fork
You've already forked hark
0

Wire hark dialect publish/subscribe/query/list through the daemon #4

Closed
opened 2026年05月11日 13:12:04 +02:00 by hugooconnor · 0 comments

Background

PR #3 (SPEC-009 sketch branch) sketched hark dialect publish | query | subscribe as CLI subcommands that only printed canonical (meta ...) frames to stdout and returned success without contacting the daemon or router. Review feedback flagged this as misleading: users got a "successful" no-op, and there is no working pipe-through-hark reply path either because the send path rejects meta performatives. The sketch commands were removed in ec565d8 to stop shipping that misleading surface.

The protocol itself is end-to-end-capable. After PR #3 plus cbcl-router PR #5, the router accepts:

  • (meta (teach @router (define ...))) — publish
  • (meta (subscribe (speak? <pattern>))) — subscribe
  • (meta (unsubscribe)) — drop subscription
  • (meta (query (speak? <name>))) — query a single dialect
  • (meta (query (list))) — enumerate

And hark's daemon already handles the receive side: DialectCache::try_install runs incoming teach-pushes through cbcl-rs's R1–R5 pipeline, installs them, and triggers auto re-hello. What's missing is any CLI surface to initiate publish / subscribe / query from a hark agent.

Scope

Wire three CLI commands through local_api → daemon → router, matching the shape of the existing hark reply / error / progress plumbing.

hark dialect publish

  • Reads a complete (define <name> ...) form from --define flag or stdin.
  • POSTs to a new daemon endpoint (e.g. /v1/agents/<handle>/meta/teach).
  • Daemon validates the inner define through cbcl_parser::run_pipeline (R1–R5) before sending — same defense-in-depth as the router does on receipt.
  • Daemon writes (meta (teach @router <define>)) to the router socket and waits for the reply.
  • Returns the router's :ok :digest "..." :name "..." reply to the CLI; CLI prints it.
  • Error cases: invalid CBCL (exit 8 cbcl_validation_failed), router connection failure (exit 9), no agent handle (exit 6).

hark dialect subscribe <pattern>

  • Pattern is positional; supports the router's * / <prefix>* / <exact> grammar.
  • POSTs to /v1/agents/<handle>/meta/subscribe.
  • Daemon writes (meta (subscribe (speak? <pattern>))) to the router socket. No reply is expected (fire-and-forget per the existing subscribe path).
  • Subsequent matching teach-pushes flow into the existing receive queue and get installed by DialectCache::try_install (already working).
  • Companion hark dialect unsubscribe writes (meta (unsubscribe)).

hark dialect query <name> (and hark dialect list)

  • For query <name>: writes (meta (query (speak? <name>))), waits for the router's teach-back, installs the define into the local cache, and prints :digest + :name on success or router-does-not-speak on miss.
  • For list: writes (meta (query (list))), prints the joined :names "..." response. (Slice-3 router PR ships the list query type.)

Implementation notes

  • Daemon API version: each new endpoint is a schema addition. Bump LOCAL_API_VERSION again on landing (currently 2).
  • The existing meta-frame builders in src/router.rs (build_meta_teach_frame, build_meta_query_frame, build_meta_subscribe_frame) are already in place and exercised by tests; the wiring reuses them.
  • Reuse the existing send path's plumbing: validation, agent handle resolution, error mapping. send_message_command in src/cli.rs is the closest template.
  • New local-api error codes: dialect_router_error (router refused), possibly dialect_validation_failed if we surface R1–R5 violations distinctly from generic cbcl_validation_failed.
  • Tests follow the pattern in tests/router_integration.rs (mock router, assert outbound frame, assert reply handling).

Non-goals

  • Persistent agent-side state for "which dialects have I subscribed to." Subscriptions are router-side; restart = resubscribe.
  • A richer query result type beyond what the router currently returns (:names "a b c" for list; teach-back for speak?).
  • A hark dialect describe <name> UX — depends on the cbcl-router dialect or :description clauses landing, neither of which exists today.
  • PR #3 — initial SPEC-009 sketch (this scope was carved out of it)
  • cbcl-router PR #5(meta (query (list))) + (meta (unsubscribe)) handlers; the slice-3 protocol additions this issue's CLI commands target.
## Background PR #3 (SPEC-009 sketch branch) sketched `hark dialect publish | query | subscribe` as CLI subcommands that only printed canonical `(meta ...)` frames to stdout and returned success without contacting the daemon or router. Review feedback flagged this as misleading: users got a "successful" no-op, and there is no working pipe-through-`hark reply` path either because the send path rejects `meta` performatives. The sketch commands were removed in `ec565d8` to stop shipping that misleading surface. The protocol itself is end-to-end-capable. After PR #3 plus cbcl-router PR #5, the router accepts: - `(meta (teach @router (define ...)))` — publish - `(meta (subscribe (speak? <pattern>)))` — subscribe - `(meta (unsubscribe))` — drop subscription - `(meta (query (speak? <name>)))` — query a single dialect - `(meta (query (list)))` — enumerate And hark's daemon already handles the *receive* side: `DialectCache::try_install` runs incoming teach-pushes through cbcl-rs's R1–R5 pipeline, installs them, and triggers auto re-hello. What's missing is any CLI surface to *initiate* publish / subscribe / query from a hark agent. ## Scope Wire three CLI commands through `local_api → daemon → router`, matching the shape of the existing `hark reply / error / progress` plumbing. ### `hark dialect publish` - Reads a complete `(define <name> ...)` form from `--define` flag or stdin. - POSTs to a new daemon endpoint (e.g. `/v1/agents/<handle>/meta/teach`). - Daemon validates the inner define through `cbcl_parser::run_pipeline` (R1–R5) before sending — same defense-in-depth as the router does on receipt. - Daemon writes `(meta (teach @router <define>))` to the router socket and waits for the reply. - Returns the router's `:ok :digest "..." :name "..."` reply to the CLI; CLI prints it. - Error cases: invalid CBCL (exit 8 `cbcl_validation_failed`), router connection failure (exit 9), no agent handle (exit 6). ### `hark dialect subscribe <pattern>` - Pattern is positional; supports the router's `*` / `<prefix>*` / `<exact>` grammar. - POSTs to `/v1/agents/<handle>/meta/subscribe`. - Daemon writes `(meta (subscribe (speak? <pattern>)))` to the router socket. No reply is expected (fire-and-forget per the existing subscribe path). - Subsequent matching teach-pushes flow into the existing receive queue and get installed by `DialectCache::try_install` (already working). - Companion `hark dialect unsubscribe` writes `(meta (unsubscribe))`. ### `hark dialect query <name>` (and `hark dialect list`) - For `query <name>`: writes `(meta (query (speak? <name>)))`, waits for the router's teach-back, installs the define into the local cache, and prints `:digest` + `:name` on success or `router-does-not-speak` on miss. - For `list`: writes `(meta (query (list)))`, prints the joined `:names "..."` response. (Slice-3 router PR ships the `list` query type.) ## Implementation notes - Daemon API version: each new endpoint is a schema addition. Bump `LOCAL_API_VERSION` again on landing (currently `2`). - The existing meta-frame builders in `src/router.rs` (`build_meta_teach_frame`, `build_meta_query_frame`, `build_meta_subscribe_frame`) are already in place and exercised by tests; the wiring reuses them. - Reuse the existing send path's plumbing: validation, agent handle resolution, error mapping. `send_message_command` in `src/cli.rs` is the closest template. - New local-api error codes: `dialect_router_error` (router refused), possibly `dialect_validation_failed` if we surface R1–R5 violations distinctly from generic `cbcl_validation_failed`. - Tests follow the pattern in `tests/router_integration.rs` (mock router, assert outbound frame, assert reply handling). ## Non-goals - Persistent agent-side state for "which dialects have I subscribed to." Subscriptions are router-side; restart = resubscribe. - A richer `query` result type beyond what the router currently returns (`:names "a b c"` for list; teach-back for `speak?`). - A `hark dialect describe <name>` UX — depends on the cbcl-router dialect or `:description` clauses landing, neither of which exists today. ## Related - PR #3 — initial SPEC-009 sketch (this scope was carved out of it) - cbcl-router PR #5 — `(meta (query (list)))` + `(meta (unsubscribe))` handlers; the slice-3 protocol additions this issue's CLI commands target.
hugooconnor changed title from (削除) Wire through the daemon (削除ここまで) to Wire hark dialect publish/subscribe/query/list through the daemon 2026年05月11日 13:12:15 +02:00
Sign in to join this conversation.
No Branch/Tag specified
main
fix/spec-013-ib3-keyready-announce
docs/spec-013-cbcl-bus-interop
feat/spec-016-onboarding-dx
feat/impl-013-mls
No results found.
Labels
Clear labels
No items
No labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
anuna/hark#4
Reference in a new issue
anuna/hark
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?