Skip to content

feat: add reply-router skill#211

Open
armstrongsam25 wants to merge 4 commits into
runxhq:mainfrom
armstrongsam25:feat/reply-router-skill
Open

feat: add reply-router skill#211
armstrongsam25 wants to merge 4 commits into
runxhq:mainfrom
armstrongsam25:feat/reply-router-skill

Conversation

@armstrongsam25

Copy link
Copy Markdown

reply-router skill

A native runx skill that classifies inbound reply messages and either appends a suppression event for unsubscribes or emits a bounded routing decision for all other classifications. Never sends — just routes.

What it does

  • Classifies replies as: interested, objection, out_of_office, wrong_person, unsubscribe
  • For unsubscribe: appends a suppression event to a local event store with CAS version checking and idempotency key
  • For other classifications: emits a runx.reply.routing.v1 routing decision with a bounded send target
  • Never sends messages — routing decisions are consumed by a separate governed send-as run

Harness

Both inline cases pass:

  • sealed_unsubscribe_suppression: unsubscribe reply → suppression event committed
  • stop_ambiguous_or_unsealed: ambiguous reply → stops with failure (no suppression, no routing)
$ runx harness ./skills/reply-router --json
{"status":"passed","case_count":2,"assertion_error_count":0,...}

Files

  • skills/reply-router/SKILL.md — skill contract with all required sections
  • skills/reply-router/X.yaml — execution profile with typed inputs/outputs and inline harness
  • skills/reply-router/run.mjs — implementation (classification, suppression, routing)

Built for Frantic bounty #70.

…e, route governed send-as

Skill structure:
- SKILL.md contract with compliance category
- X.yaml graph runner with classify → append_suppression / emit_routing / human_lane steps
- classify.mjs: validates sealed receipt, matches unsubscribe signals, routes affirmative replies
- append_event.mjs: CAS append_event to registry:runx/data-store@0.1.2 with idempotency key
- emit_route.mjs: emits runx.reply.routing.v1 naming a separate governed send-as run
- dogfood.mjs: self-contained runner exercising all branches

Harness cases:
- sealed_unsubscribe_suppression: sealed receipt + unsubscribe text → suppress
- stop_ambiguous_or_unsealed: unsealed receipt + ambiguous text → needs_agent

Fixtures: unsubscribe, ambiguous/unsealed, routed reply
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