--- kind: responsibility name: build-zulip-plugin description: > Generates and iteratively improves a Hermes Zulip platform plugin. Each run can produce a new version of the plugin, learning from previous runs and incrementally improving the adapter code. The contract itself can be updated to capture new patterns. --- ## Maintains - plugin_version: string — Current version of the generated plugin - generation_count: number — How many generations have been produced - last_generation: timestamp — When the last generation was created - known_issues: array — Issues discovered in the current version **Postconditions** (the plugin is GOOD when ALL pass): *Connectivity* - connected == true — Establishes and maintains Zulip event queue - reconnect_on_failure == true — Reconnects after queue expiry - recovers_from_network_loss == true — Handles temporary network drops - stream_subscription_check == true — Bot is subscribed to primary streams (Gen 5+) *Message Flow* - dm_response_time_ms < 10000 — DMs get a response within 10 seconds - dm_response_time_offline_verifiable == true — simulate_dm_latency() passes without live Zulip (Gen 6+) - stream_mention_detection == true — @mentions in streams are detected and routed - all_bots_detection == true — @all-bots mentions are detected - echo_loop_prevention == true — Never replies to its own messages *Code Quality* - syntax_check == "pass" — All Python files are valid - has_register_function == true — Exposes `register(ctx)` entry point - plugin_yaml_valid == true — plugin.yaml parses correctly - follows_base_adapter_pattern == true — Extends BasePlatformAdapter *Reliability* - graceful_disconnect == true — shutdown doesn't crash - handles_malformed_messages == true — Bad JSON doesn't kill the poll loop - typing_indicators_work == true — Sends typing notifications - known_issues_tracked == true — add_known_issue() persists problems across generations (Gen 6+) ## Status **Active** — for Hermes agents only. This plugin is NOT retired. It remains in service for any Hermes agent that connects to Zulip (Mumuni, Tanko, Koby, Koonimo). The pi Zulip extension was decommissioned 2026-07-04 but this contract targets the Hermes plugin system, which is unaffected. ## Parameters - zulip_site: string — Zulip server URL (default: "https://chat.sysloggh.net") - bot_email_prefix: string — Prefix for bot emails (default: "abiba-bot") - output_dir: string — Where to write the plugin (default: "plugins/platforms/zulip") - generation_goal: string — What to improve this generation (default: "fix bugs and improve reliability") ## Continuity The improvement cycle is **event-driven**, not just cron-based: - **On check failure**: If any postcondition fails, wake immediately to fix - **On user request**: `prose run build-zulip-plugin` — explicit upgrade - **On new pattern**: If another plugin or agent reports a better pattern, wake to assimilate - **Retrospective**: Every 24 hours if no other trigger fired — scan for subtle degradation - **On first deploy**: Always run Generation 1 when no plugin exists yet ## Remembers Each generation stores: - What worked well (success patterns) - What broke (failure modes) - What the user complained about (pain points) - Which postconditions passed and failed ## Generation Rules ### Rule 1: First Generation - Generate complete plugin.yaml, adapter.py, __init__.py - Follow Hermes BasePlatformAdapter pattern - Include: connect, disconnect, send, edit_message, send_typing - Include: DM-first routing, @mention detection, @all-bots support ### Rule 2: Subsequent Generations - Read the previous generation's output and known issues - Apply improvements based on generation_goal - Fix any issues from the previous generation - Add new capabilities if needed ### Rule 3: Testing - After generating, run syntax check on the Python code - Verify plugin.yaml is valid YAML - Log the generation result to knowledge graph ### Rule 4: Self-Improvement - After N generations, review the contract itself - If new patterns emerged, update the Generation Rules - If old rules are no longer relevant, remove them ## Execution 1. **Read state** — Check previous generations from knowledge graph node `build-zulip-plugin:state` 2. **Generate or improve** — Based on generation count: - Generation 1: Scaffold full plugin from scratch - Generation N: Read previous code, apply improvements 3. **Validate** — Syntax check, structure check, dependency check 4. **Run offline tests** — Always run `simulate_dm_latency()` and selftest() if no live Zulip 5. **Log** — Save generation result to knowledge graph as [LEARN] node. Update the `build-zulip-plugin:state` node with current generation_count, plugin_version, and known_issues. 6. **Report** — Output what was generated, what changed, what needs review ## State Persistence (Gen 6+) All generation state is stored in a knowledge graph node titled `build-zulip-plugin:state`: - `generation_count` — incremented on each verified run - `plugin_version` — current version string - `last_generation` — ISO timestamp of most recent run - `known_issues` — array of unresolved issues carried forward - `last_postcondition_results` — pass/fail map from most recent verification Agents executing this contract MUST read this node on startup and update it after validation. If the node does not exist, create it with generation_count=1. ## Example Output ```json { "generation": 1, "version": "1.0.0", "files_written": [ "plugins/platforms/zulip/plugin.yaml", "plugins/platforms/zulip/__init__.py", "plugins/platforms/zulip/adapter.py" ], "syntax_check": "pass", "known_issues": [], "next_generation_goal": "add streaming responses via placeholder->edit pattern" } ```