- publish-10050.mjs: publishes Cayce kind 10050 (NIP-65 message-relays/
inbox) listing the 6 relays where the listener actually reads DMs.
EXECUTED once with operator authorization: event id
188ef397824e8f29b5e1bea661ae65b1f8532ee97617747b9fbde57c6e8dfce9,
accepted 6/6 relays.
- initiative.mjs: the cycle DM to the supervisor now includes a summary
of outbound_drafts from the last 24h (id, type, first 15 words) so the
operator reviews what the agent WANTED to publish.
- initiative.mjs: supervisor directive (CAYCE_DIRECTIVE_BTCPAY=1,
reversible) injected into the cycle prompt: grants/opportunity search
SUSPENDED, single priority = consolidate the BTCPay Server proposal
(opportunity #106 / draft #33) ready for HUMAN sending. MANDATE text
untouched (only the supervisor can change it).
- initiative.mjs: add_opportunity now rejects duplicates (the agent had
re-registered OpenSats ×10, HRF ×6).
- opportunity #106 status -> priority-1.
- check-relay-silence.mjs: queries the relays for Cayce-signed events
since a timestamp; allows only kind 10050 and supervisor DMs; exits 1
on any violation. Verified: 0 events, 0 violations since deployment.
- deploy.sh: sudo for the daemon restart, optional files tolerated.
Gate: make check green (96 tests).
Problem: Cayce publishes straight to relays with no approval gate —
cayce-initiative publish_note, core.mjs digest/opinion/reflection/events,
mention auto-replies, social promo (Facebook/Instagram via sfeed), and
mail — while the operator believed approvals existed (they never did;
ADR-0005 Telegram queue was never implemented).
Mechanism (outbox.mjs, deployed to all runtimes):
- CAYCE_PUBLISH_MODE=draft (default): gateOutbound() stages EVERY outbound
artifact into outbound_drafts (entity DB) with identity_path +
identity_hash (sha256 of prompts/cayce-identity.md) before anything
else happens. Fail-closed: if staging fails, the event is discarded,
never published.
- CAYCE_PUBLISH_MODE=live: original behavior, unchanged (reversible with
one line per service .env).
- Chokepoint: the nostr daemon /publish endpoint gates ALL callers
(initiative publish_note, core.mjs ×4, banner kind 0); the daemon own
mention-reply path gates too, storing original_event for context;
startup profile publish gates as well. DM-to-supervisor (/dm) is
internal and stays live.
Identity (point 8b):
- prompts/cayce-identity.md: the 5 hardcoded voice blocks extracted
VERBATIM (verified byte-identical by runtime test) with block markers.
- core.mjs / editorials.mjs now load their voice blocks from this file
(loadIdentityBlock); identity hash recorded on every draft.
- runtime/ holds the versioned copies of the previously-unversioned
runtime scripts + deploy.sh installer.
No timers enabled or disabled. No production data modified.