activity-core/docs/recurring-automations-playbook.md
tegwick 747d63a993
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Document recurring automations playbook for activity-core as organizer.
Codify when/what/where vs rein-aharness execution vs domain instance state,
and the checklist to register cron definitions without workstation cron
bypasses.
2026-08-03 17:53:06 +02:00

7.1 KiB
Raw Blame History

Recurring automations playbook — activity-core as the organizer

Audience: operators and coding agents adding or fixing recurring work
Principle: activity-core answers when / what / where only. It does not execute.

This is the org standard. Prefer this path over workstation cron, ad-hoc shell timers, or “Ill remember to run it.”


The three layers (do not collapse them)

┌─────────────────────────────────────────────────────────────┐
│ 1. activity-core  — WHEN / WHAT / WHERE                     │
│    Temporal schedule · context resolvers · rules            │
│    → emits activity_task_spawn (state-hub sink by default)  │
└────────────────────────────┬────────────────────────────────┘
                             │
┌────────────────────────────▼────────────────────────────────┐
│ 2. rein-aharness (or domain executor) — DOES THE WORK       │
│    llm-connect · repo checkout · commit · completion event  │
│    Host timers on railiance are *interim* until poll/claim  │
│    of spawns is fully wired (state-hub sink is not claimable)│
└────────────────────────────┬────────────────────────────────┘
                             │
┌────────────────────────────▼────────────────────────────────┐
│ 3. domain repo — INSTANCE STATE                             │
│    activity-definitions/ · playbooks · briefs/ · catalogs   │
│    completion event types (fi_daily_brief, binky_daily_brief)│
└─────────────────────────────────────────────────────────────┘
Layer Owns Must not own
activity-core Triggers, due checks, task specs, audit of spawns Brief writing, git commits, LLM prompts for domain content
rein-aharness Execution session, credentials at runtime, hub completion Inventing schedules, domain policy
domain repo Definition markdown, playbook, artifacts Scattered crons that bypass activity-core

Anti-pattern: workstation crontab that “does the daily brief” while activity-core also schedules it — dual cadence and forgotten design.

Correct interim (Binky / FI): activity-core schedule is authority for when due; railiance user-systemd timer invokes rein-aharness a few minutes later as executor. Document both; never pretend the host timer is the scheduler.


How to add a recurring automation (checklist)

A. Domain definition (source of truth)

  1. Create {domain-repo}/activity-definitions/{slug}.md
    • trigger.type: cron + timezone + misfire_policy
    • context_sources with a due resolver when work is once-per-day
    • rule with target_repo, labels, description pointing at the playbook
    • Start with enabled: false until dry-run
  2. Implement completion event shape in domain playbook
    (e.g. fi_daily_brief with detail.repo + detail.date)
  3. If needed, add resolver in activity-core (context_resolvers/) + tests

B. Register with activity-core

Environment How
Dev ACTIVITY_DEFINITION_DIRS=/path/to/domain-repo + make sync-activity-definitions
Railiance Project definition into ConfigMap actcore-external-activity-definitions (and keep k8s/railiance/20-runtime.yaml in git)

Then:

# after ConfigMap / files update
kubectl -n activity-core exec deploy/actcore-api -- python3 -c \
  'import urllib.request as u; print(u.urlopen(u.Request(
    "http://localhost:8010/admin/sync?definitions=true&schedules=true",
    method="POST")).read().decode())'

Verify:

# definition enabled + cron
# Temporal schedule: activity-schedule-<definition-uuid> not paused
kubectl -n activity-core exec deploy/actcore-worker -- python3 -c '...'  # describe schedule

Ops UI: activity.coulomb.social → automations status / trigger (SSO).

C. Executor (rein-aharness)

  1. Prefer a named rein-aharness command for the domain work
    (e.g. brief-daily, fi-research-brief) using llm-connect, not Claude CLI on railiance01
  2. Install railiance user-systemd timer in the domain repo
    (scripts/railiance-rhythm/) that calls rein-aharness
  3. Timer should sit just after the activity-core cron (due check already enforced by completion events on re-run)
  4. On success, post the domain completion event so the resolver sets due=false

D. Prove the loop

  1. POST /activity-definitions/<id>/trigger (ops UI or API)
  2. Confirm activity_task_spawn progress event (when sink=state-hub)
  3. Run executor once (timer or manual rein-aharness)
  4. Confirm domain completion event → resolver due=false for that day
  5. Set enabled: true if still false; commit domain + activity-core CM projection

Where definitions live

Kind Location
Org-wide (SBOM, consistency, inventory) activity-core/activity-definitions/ and/or ConfigMap
Domain-specific (Binky, FI, …) {domain}/activity-definitions/ + ConfigMap projection

ADR-002: domain repos own domain automations; activity-core discovers them via ACTIVITY_DEFINITION_DIRS or the external ConfigMap mount.


Sinks (ACTIVITY-WP-0022)

ISSUE_SINK_TYPE Use
state-hub (default) Internal fleet work → activity_task_spawn progress
null Dry-run
rest Explicit external issue-core / Forgejo only

Do not flip production to rest globally.


Reference implementations

Domain Definition Executor
Binky binky-daily-rhythm in activity-core / binky rein-aharness brief-daily + binky-control/scripts/railiance-rhythm/
Freedom Intelligence fi-daily-research-brief rein-aharness fi-research-brief + freedom-intelligence/scripts/railiance-rhythm/

Operator daily habit

  1. Ops console: did automations run? (/ops/automations/status)
  2. State Hub: activity_task_spawn + domain completion events
  3. Domain repo: brief/artifact files + git history
  4. If something is missing, fix activity-core first (schedule paused? definition disabled? resolver due stuck? sink errors?) — do not invent a new cron

  • INTENT.md — when/what/where boundary
  • docs/task-emission-consumer-contract.md — spawn payload + consumer duties
  • docs/runbook.md — sync, trigger, ops UI
  • docs/adr/adr-002-definition-format.md — definition files