Skip to content
Skillv1.0.0

rar-rapp-estate-outbound

Write a signed neighborhood event to the operator's outbound lane on disk. Returns the file path + a publish hint. Refuses if the event is missing sig/pub/from or if the neighborhood rappid is empty.

by kody-w(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from kody-w/rapp-monorepo (repos/RAR/scout/bundles/native-13/skills/rar-rapp-estate-outbound/SKILL.md). Install upstream with npx skills add kody-w/rapp-monorepo --skill rar-rapp-estate-outbound. Copyright stays with the author.

Microsoft Scout runtime

This is the reversible Scout projection of @rapp/estate_outbound. The original RAPP agent is preserved byte-for-byte in estate_outbound_agent.py and in the RCI capsule.

When Scout can execute local files, resolve this skill directory and run:

python3 scripts/run_agent.py --preflight
echo '{}' | python3 scripts/run_agent.py

Pass the real JSON arguments instead of {}. The runner verifies the linked agent SHA-256 before importing it. If preflight reports a host dependency that Scout cannot satisfy, use the brainstem_chat MCP tool to run the canonical agent in the user's Brainstem. Never paraphrase the factory or agent into a new implementation. The generic direct-file commands in the generated Toaster section are recovery guidance; Scout should prefer the verified runner.

estate_outbound_agent.py — stage a signed event for federation roll-up.

The companion to commons_post_agent (and any future per-neighborhood post agent): commons_post composes + the host signs, then this agent writes the signed event to the operator's outbound lane (Article XLVIII), where each neighborhood's federation roll-up can find it on its beat.

Outbound lane layout (on disk):

~/.brainstem/outbound//.json

Filename: <sha256(pub_jwk_canonical)[:16]>-<ts:replace ':' with '-'>.json (matches events/SCHEMA.md so the federation roll-up can union without renaming.)

The agent does NOT push the lane to a public estate repo — pushing is the operator's responsibility (git -C ~/.brainstem push estate-outbound main or equivalent). The agent prints the hint, surfaces what was staged, and returns the path so the host UI can wire a "publish" button.

Future companion: an estate_publish_agent that wraps git add/commit/push against the operator's public-estate remote, with provenance logged into ~/.brainstem/bonds.json per CONSTITUTION Article XLVIII.

Runs in any host that exposes BasicAgent (Pyodide tether, server brainstem, swarm) — pure stdlib except for the (already-loaded) BasicAgent base.

Parameters

The typed contract this capability answers to (JSON Schema — the deterministic layer):

{
  "properties": {
    "event": {
      "description": "The signed event object. Must include schema, from, ts, sig, pub at minimum.",
      "type": "object"
    },
    "neighborhood_rappid": {
      "description": "Target neighborhood's rappid, consolidated form rappid:@<owner>/<slug>:<64hex>. Determines which subdir of ~/.brainstem/outbound/ receives the event.",
      "type": "string"
    }
  },
  "required": [
    "neighborhood_rappid",
    "event"
  ],
  "type": "object"
}

Run this — do not improvise

This capability's deterministic implementation is a RAPP single-file agent, linked beside this file as estate_outbound_agent.py and embedded as the fenced Python below (sha256 f4f677f2bba5a12b…; a byte-exact copy is also vaulted in the capsule comment at the end of this file). On a host with sandbox execution, run the linked file directly — if it is missing, write the fence contents verbatim to estate_outbound_agent.py first:

python3 estate_outbound_agent.py '{"key": "value"}'      # arguments as one JSON object
echo '{"key": "value"}' | python3 estate_outbound_agent.py   # or on stdin
python3 estate_outbound_agent.py --tool                      # emit the JSON tool contract

Treat stdout as a tool result. If it reports missing or unresolved inputs, stop and collect them. If it returns steps, execute those steps in order exactly as returned; if it returns instructions, follow them with the supplied inputs. Otherwise use the result verbatim. Do not invent behavior beyond that output. On a host without code execution, treat the Parameters schema and the code below as the exact specification and never paraphrase a step. Never edit inside the generated markers; a converter-equipped host can instead restore the original file checksum-verified with the installed rapp-agent-converter/scripts/toast.py convert SKILL.md --to agent.

"""estate_outbound_agent.py — stage a signed event for federation roll-up.

The companion to commons_post_agent (and any future per-neighborhood post
agent): commons_post composes + the host signs, then this agent writes
the signed event to the operator's outbound lane (Article XLVIII), where
each neighborhood's federation roll-up can find it on its beat.

Outbound lane layout (on disk):

  ~/.brainstem/outbound/<sanitized-neighborhood-rappid>/<event-filename>.json

Filename:   <sha256(pub_jwk_canonical)[:16]>-<ts:replace ':' with '-'>.json
            (matches events/SCHEMA.md so the federation roll-up can union
             without renaming.)

The agent does NOT push the lane to a public estate repo — pushing is the
operator's responsibility (`git -C ~/.brainstem push estate-outbound main`
or equivalent). The agent prints the hint, surfaces what was staged, and
returns the path so the host UI can wire a "publish" button.

Future companion: an `estate_publish_agent` that wraps `git add/commit/push`
against the operator's public-estate remote, with provenance logged into
`~/.brainstem/bonds.json` per CONSTITUTION Article XLVIII.

Runs in any host that exposes BasicAgent (Pyodide tether, server brainstem,
swarm) — pure stdlib except for the (already-loaded) BasicAgent base.
"""

from __future__ import annotations

import hashlib
import json
import os
import pathlib
import re

try:
    from agents.basic_agent import BasicAgent
except ImportError:
    try:
        from basic_agent import BasicAgent
    except ImportError:
        class BasicAgent:  # type: ignore
            def __init__(self, name, metadata):
                self.name = name
                self.metadata = metadata


__manifest__ = {
    "schema": "rapp-agent/1.0",
    "name": "@rapp/estate_outbound",
    "version": "1.0.2",
    "display_name": "EstateOutbound",
    "description": (
        "Writes an already-signed neighborhood event into ~/.brainstem/outbound/ for federation roll-up; pushing to the estate repo stays manual."
    ),
    "author": "RAPP",
    "tags": ["estate", "outbound", "federation", "neighborhood", "publish"],
    "category": "core",
    "quality_tier": "official",
    "requires_env": [],
    "dependencies": ["@rapp/basic_agent"],
    "example_call": {
        "args": {
            "neighborhood_rappid": "rappid:@rapp-commons/origin:3727bc584708e539d69792713fbb200688c634744cce2d9614fa5aefd4ff295f",
            "event": {"schema": "rapp-commons-event/1.0", "kind": "hello", "from": "...", "ts": "...", "body": "...", "sig": "...", "pub": {}}
        }
    },
}


def _outbound_root() -> pathlib.Path:
    return pathlib.Path(os.path.expanduser("~/.brainstem/outbound"))


def _sanitize_rappid(rappid: str) -> str:
    """Filesystem-safe slug for a rappid. Reversible enough for human reads;
    matches the rule used by the planted neighborhood's own naming.
    """
    return re.sub(r"[^A-Za-z0-9._-]+", "_", rappid)[:200]


def _canonical_json(d: dict) -> str:
    return json.dumps(d, sort_keys=True, separators=(",", ":"), ensure_ascii=False)


def _fingerprint(pub_jwk: dict) -> str:
    canonical = _canonical_json(pub_jwk)
    return hashlib.sha256(canonical.encode("utf-8")).hexdigest()


def _ts_safe(ts: str) -> str:
    return ts.replace(":", "-")


class EstateOutboundAgent(BasicAgent):
    def __init__(self):
        self.name = "StageOutboundEvent"
        self.metadata = {
            "name": self.name,
            "description": (
                "Write a signed neighborhood event to the operator's outbound "
                "lane on disk. Returns the file path + a publish hint. Refuses "
                "if the event is missing sig/pub/from or if the neighborhood "
                "rappid is empty."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "neighborhood_rappid": {
                        "type": "string",
                        "description": "Target neighborhood's rappid, consolidated form rappid:@<owner>/<slug>:<64hex>. Determines which subdir of ~/.brainstem/outbound/ receives the event.",
                    },
                    "event": {
                        "type": "object",
                        "description": "The signed event object. Must include schema, from, ts, sig, pub at minimum.",
                    },
                },
                "required": ["neighborhood_rappid", "event"],
            },
        }
        super().__init__(self.name, self.metadata)

    def perform(self, **kwargs) -> str:
        nbhd = (kwargs.get("neighborhood_rappid") or "").strip()
        event = kwargs.get("event")

        if not nbhd:
            return json.dumps({"error": "neighborhood_rappid is required"})
        if not isinstance(event, dict):
            return json.dumps({"error": "event must be an object"})
        for required in ("schema", "from", "ts", "sig", "pub"):
            if required not in event:
                return json.dumps({"error": f"event missing required field '{required}'"})
        if not isinstance(event["pub"], dict):
            return json.dumps({"error": "event.pub must be a JWK object"})

        # Filename per events/SCHEMA.md so the federation roll-up unions
        # without renaming.
        fp = _fingerprint(event["pub"])[:16]
        ts_safe = _ts_safe(str(event["ts"]))
        filename = f"{fp}-{ts_safe}.json"

        outbound_dir = _outbound_root() / _sanitize_rappid(nbhd)
        try:
            outbound_dir.mkdir(parents=True, exist_ok=True)
        except Exception as e:
            return json.dumps({"error": f"could not create {outbound_dir}: {e}"})

        out_path = outbound_dir / filename
        try:
            out_path.write_text(_canonical_json(event) + "\n", encoding="utf-8")
        except Exception as e:
            return json.dumps({"error": f"could not write {out_path}: {e}"})

        return json.dumps({
            "ok": True,
            "staged_at": str(out_path),
            "neighborhood": nbhd,
            "filename": filename,
            "publish_hints": [
                (
                    "To publish: commit your outbound lane to the operator's "
                    "public-estate repo and push. The neighborhood's "
                    "federation roll-up pulls outbound on its beat (commons "
                    "default: every 10 minutes via .github/workflows/federate.yml)."
                ),
                (
                    "If you don't have a public-estate repo yet, see "
                    "kody-w/RAPP/pages/docs/ESTATE_SPEC.md for the two-tier "
                    "spec (Article XLVIII)."
                ),
                (
                    f"Quick local check: cat '{out_path}' | jq ."
                ),
            ],
        }, indent=2)

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/kody-w-rapp-monorepo-rar-rapp-estate-outbound/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

kody-w-rapp-monorepo-rar-rapp-estate-outbound.ocm.jsonjson
{
  "ocm": "1",
  "id": "kody-w-rapp-monorepo-rar-rapp-estate-outbound",
  "kind": "skill",
  "name": "rar-rapp-estate-outbound",
  "description": "Write a signed neighborhood event to the operator's outbound lane on disk. Returns the file path + a publish hint. Refuses if the event is missing sig/pub/from or if the neighborhood rappid is empty.",
  "publisher": "kody-w",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general"
    ],
    "tags": [
      "skill-md",
      "estate",
      "outbound",
      "federation",
      "neighborhood",
      "publish",
      "github"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Write a signed neighborhood event to the operator's outbound lane on disk. Returns the file path + a publish hint. Refuses if the event is missing sig/pub/from or if the neighborhood rappid is empty."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "github",
      "repository": "https://github.com/kody-w/rapp-monorepo",
      "path": "repos/RAR/scout/bundles/native-13/skills/rar-rapp-estate-outbound/SKILL.md",
      "ref": "634639ef14412264b22cc963a3e2acd649385236",
      "url": "https://github.com/kody-w/rapp-monorepo/blob/634639ef14412264b22cc963a3e2acd649385236/repos/RAR/scout/bundles/native-13/skills/rar-rapp-estate-outbound/SKILL.md",
      "key": "kody-w/rapp-monorepo/repos/RAR/scout/bundles/native-13/skills/rar-rapp-estate-outbound/SKILL.md"
    }
  },
  "instructions": "## Microsoft Scout runtime\n\nThis is the reversible Scout projection of `@rapp/estate_outbound`. The original RAPP\nagent is preserved byte-for-byte in `estate_outbound_agent.py` and in the RCI capsule.\n\nWhen Scout can execute local files, resolve this skill directory and run:\n\n```bash\npython3 scripts/run_agent.py --preflight\necho '{}' | python3 scripts/run_agent.py\n```\n\nPass the real JSON arguments instead of `{}`. The runner verifies the linked\nagent SHA-256 before importing it. If preflight reports a host dependency that\nScout cannot satisfy, use the `brainstem_chat` MCP tool to run the canon",
  "cost": {
    "context_tokens": 4607
  }
}

Fetch it by URL: GET /api/v1/registry/kody-w-rapp-monorepo-rar-rapp-estate-outbound/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.