Files
cayce 34a5f331ac
ci / lint-test-leaks (pull_request) Canceled after 0s
skeleton: package, schema, config, CLI, alembic, CI, deploy, docs
- cayceops core: env-only config (CAYCE_OPS_*), engine/session, ORM models
  with state machines (proposal/mail/content) and audited writes
- provider-agnostic LLM interface (null provider default, stdlib openai-compat)
- Typer CLI with lazy component loading (scanner/executor/maild/publisher/monitor)
- alembic 0001 initial schema; sqlite-portable JSON columns
- tests: 7 passing on throwaway sqlite; fixtures invented, never real data
- ci: ruff + alembic smoke + pytest + gitleaks(full history) in
  .gitea/workflows + .github/workflows; local gate = make check
- deploy: docker-compose (postgres 16) + hardened systemd units/timers
- docs: DECISIONS D1-D9; README project (grant text retired)
2026-10-19 21:35:50 +00:00

71 lines
3.2 KiB
Markdown

# Cayce is an agent-operated project run by Gustavo.
Cayce Ops is the autonomous operations stack behind Cayce — an agent that runs
[bitcoinhotels.org](https://bitcoinhotels.org) (Bitcoin-native travel guides)
and [hardcap.news](https://hardcap.news) (Bitcoin security intelligence).
Five decoupled components share one Postgres database. Each is a CLI command,
driven by cron/systemd timers. Nothing runs without an audit trail.
| Component | What it does | Human gate |
|---|---|---|
| **scanner** | Discovers opportunities (affiliates, partnerships, content gaps) from configured sources; files them as `proposals` | none — it only proposes |
| **executor** | Runs `approved` proposals through registered action plugins; full audit of who approved, what ran, what happened | approval required (`AUTONOMOUS_MODE=false` by default) |
| **mail-negotiator** | Classifies merchant replies (approval / rejection / question / other) over IMAP; drafts replies; SMTP sends **only human-approved drafts** | draft approval required |
| **publisher** | Themed content calendar. Nostr (NIP-01) adapter first; Facebook/Instagram adapters exist but are **disabled by default**; brand images via Pillow templates | publish requires approved items |
| **monitor** | Static status page: daemon health, last runs, proposal queue, recent errors. No sensitive data | none — read-only |
State machines:
```
proposal: proposed -> approved -> running -> done | failed
mail: inbound classified; draft: none -> drafted -> approved -> sent
content: draft -> approved -> published
```
## Quickstart (local)
```bash
uv sync --frozen # installs Python 3.12 + locked deps
cp .env.example .env # fill in; values are placeholders
docker compose up -d db # Postgres 16
uv run alembic upgrade head
uv run cayceops scanner run
uv run pytest
```
`docker compose up` (everything) runs all five daemons in loops; on a VPS use
[deploy/systemd](deploy/systemd/README.md) instead.
## Layout
```
cayceops/ the package
config.py env-var config (CAYCE_OPS_*), no config files
db.py engine/session/upgrade helpers
models.py ORM schema + state machines + audit helper
llm.py provider-agnostic LLM interface (null by default)
components/
scanner/ discovery -> proposals (never executes)
executor/ plugin execution + audit
maild/ IMAP classify, drafts, SMTP gated on approval
publisher/ calendar, nostr adapter, image templates
monitor/ static status page builder
alembic/ migrations (production schema path)
tests/ pytest suite (invented fixtures only)
deploy/systemd/ VPS units + timers
docs/DECISIONS.md architectural decisions and their costs
```
## Security posture
- Config exclusively via env vars; `.env` is gitignored, `.env.example` holds placeholders.
- `make check` (and CI): ruff, pytest, alembic smoke, **gitleaks over the full history**.
- SMTP send, social publish, and proposal execution all require a human action
recorded in the audit log — unless `AUTONOMOUS_MODE=true`, which enables one
narrow, capped, audited exception (see [docs/DECISIONS.md](docs/DECISIONS.md) D5).
## License
MIT — see [LICENSE](LICENSE).