Skip to content

feat: single shared presence topic, topic post patterns, dynamic tool descriptions#7

Merged
sharpTrick merged 2 commits into
mainfrom
feat/single-presence-topic
Jul 4, 2026
Merged

feat: single shared presence topic, topic post patterns, dynamic tool descriptions#7
sharpTrick merged 2 commits into
mainfrom
feat/single-presence-topic

Conversation

@sharpTrick

Copy link
Copy Markdown
Owner

What & why

Reworks presence and extends topic config, all inside bridge-core — no seam change, no plugin changes, and the shared conformance suite is untouched. Addresses five requests: presence noise (N muted topics), an over-frequent heartbeat, chat instances emitting heartbeats they can't use, no way for an agent to discover postable topics, and no way to post to ad-hoc topics.

Changes

  1. Single presence topic. hello/heartbeat/goodbye now post to one shared topic (presence.topic, default parley-presence) instead of a derived <topic>-parley-presence stream per allowlisted topic. The record is v2 and carries the emitter's subscribed topics[], so parley_list_users still reports liveness per topic while a human mutes one topic. parley_list_users does a single fetch and filters each entry by its advertised topics.
  2. Slower heartbeat. Default heartbeat_ms 30 000 → 600 000 (10 min). ttl_ms is now optional and defaults to 3× the heartbeat via a Zod .transform.
  3. Chat opts out of presence. presence.enabled: false set in all five remote-chat.yaml examples and the self-host config.
  4. Topic discovery via dynamic tool descriptions. Configured topics/patterns are interpolated into the tool descriptions at registration; the topic param gets a JSON-Schema enum when no pattern widens the set. No new tool.
  5. post_topics regex patterns. Full-match-anchored regexes that grant post + fetch on matching topics; subscribe/catch-up/presence/list_users-default still use only the explicit topics list. The Allowlist grew a two-dimensional check plus a reserved guard so no pattern (even .*) can target the presence topic and spoof the roster. Config .superRefine rejects uncompilable patterns and a topics entry colliding with presence.topic.

Wiring is centralized in one allowlistFor(cfg) helper shared by both composition roots.

Testing

  • Full suite green (172 passed, 8 skipped = network-backend conformance needing live servers); tsc -b clean.
  • End-to-end against real SQLite: two agents on a shared DB list live from one parley-presence stream with their advertised topics; scoping by a pattern-allowed topic works; post_topics ad-hoc post + fetch succeeds; posting/fetching the reserved presence topic is refused even under .*; tool descriptions show the interpolated topics and the enum on/off behavior.

Notes / risks

  • Wire-format change (v1v2): old (per-topic) and new (single-topic) bridges are mutually invisible in parley_list_users. Accepted pre-1.0; old derived streams age out via backend retention. Titled feat: (not feat!:) per the repo's pre-1.0 rule.
  • Keep presence.topic consistent across a deployment or the roster splits (documented in DESIGN §7).
  • ConfigSchema is now a ZodEffects; verified no consumer uses .shape/.extend.
  • Does not add presence-stream pruning (the pre-existing "grows forever" thread) — but collapses N streams → 1 and cuts the beat rate ~20×, so growth is far slower.
  • Includes a journal entry under docs/journal/ (testimony, not load-bearing).

🤖 Generated with Claude Code

sharpTrick and others added 2 commits July 3, 2026 22:57
… descriptions

Presence rework and topic-config extensions, all within bridge-core (no seam
change, no plugin changes, conformance suites untouched):

- Presence now announces on ONE shared topic (presence.topic, default
  parley-presence) instead of a derived <topic>-parley-presence stream per
  allowlisted topic. The record is v2 and carries the emitter's subscribed
  topics, so parley_list_users still reports liveness per topic while a human
  mutes a single topic on real chat backends.
- Heartbeat default 30s -> 10min; ttl_ms is optional and defaults to 3x the
  heartbeat via a Zod transform.
- Chat/reactive-only instances set presence.enabled: false (wired into the
  remote-chat example configs).
- post_topics: full-match regex patterns that extend post/fetch ONLY; subscribe,
  catch-up, presence, and list_users-default still use the explicit topics list.
  The Allowlist grows a two-dimensional check plus a reserved guard so no pattern
  can target the presence topic and spoof the roster.
- Tool descriptions interpolate the configured topics/patterns at registration,
  and the topic param carries a JSON-Schema enum when no pattern widens the set,
  so an agent discovers what it may post to with no extra call.

Note: the presence wire format is v1->v2; old and new bridges are mutually
invisible in parley_list_users (accepted pre-1.0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Guestbook testimony; not load-bearing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sharpTrick sharpTrick merged commit 135e635 into main Jul 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant