Operations Runbook
Triage
GET /health→{"status":"ok"}when the process is up (not connector auth).pulse status- DB path, event counts, time range, cursors.pulse logs- recent events (-n,--source,--allas needed).- Re-read
pulse.tomland env if jobs skip unexpectedly.
Web UI (GET /)
Paths, timezone, scheduler + connector counts. POST actions return to / with a flash:
| Action | Effect |
|---|---|
/actions/pull | Pull all active pull connectors |
/actions/test-telegram | Test Telegram (needs tokens) |
Webhooks and MCP
POST /webhooks/telegram- always mounted; valid message payload → 202, bad payload → 400.
Default install: pull connectors only unless you register push connectors with webhook paths.
Scheduler (baseline jobs)
aggregation (hourly), plus pull jobs for each enabled connector.
When [discovery] enabled = true, a discovery job runs every interval_days starting at at (config timezone). It runs the headless agent subprocess against the long-horizon profile and notifies only if the agent records a new or changed pattern in the vault. There is no gate on recent activity: findings are structural and months old, so a quiet week is not a reason to skip. Force a pass with pulse review. Requires the agent CLI on PATH and a configured notify channel - see configuration reference.
With [semantic] also enabled, an embed job runs 6-hourly to embed newly ingested events. Without it pulse embed is only a one-off backfill, and novelty detection goes blind to recent data - the events any discovery pass is actually about.
Cron uses host timezone; PULSE_TIMEZONE affects “today” inside jobs, not cron. Pull jobs only for enabled connectors.
Failures: set notify_on_job_failure = true (and at least one outbound channel: Telegram, ntfy, …) to receive rate-limited alerts when a scheduled job throws (per-job cooldown job_failure_alert_cooldown, default 6h). Category operations. Connector 401 / missing OAuth paths that used to return empty now raise ConnectorAuthError so the same path can alert on pull_<source> failures.
Recovery
pulse reset <source>- reset one connector cursor (full re-pull next time).pulse reset(no arg) - list all cursors, confirm, clear all.- Check
pulse logsbefore reset if you need timestamps/context.
Failure hints
| Symptom | Likely cause |
|---|---|
/health OK, empty logs | Connectors off, missing creds, or no pulls yet |
| Telegram webhook 400 | Missing or empty message text in payload |
publish-pypi fails with invalid-publisher | PyPI trusted publisher does not match the tag workflow - see pypi-trusted-publishing.md or the deployed copy. |