Add activity-core ops_run client, approach selection (FI/Binky/mail/agent), claim-loop worker with lease heartbeat, CLI run --from-ops-run and claim-loop, install units, and docs demoting issue-core to legacy external tickets. T05 timer cutover remains operator after five clean cycles.
4.1 KiB
Ops run claim loop (REIN-A-0002)
Primary intake for activity-core scheduled automation.
Architecture: ACT-ADR-005 · activity-core ops-run-queue.md
Does not require issue-core or Forgejo for FI / Binky-style ops.
Flow
activity-core emit_tasks
→ INSERT ops_run (open) + dual-write activity_task_spawn
│
▼
rein-aharness claim-loop
POST /ops-runs/claim
select_approach(labels, definition, hint)
execute (fi-research-brief | brief-daily | mail-* | agent-session)
POST complete | fail(+reopen)
Environment
| Variable | Default | Meaning |
|---|---|---|
ACTIVITY_CORE_URL |
http://127.0.0.1:8010 |
actcore-api base |
ACTIVITY_CORE_WORKER_TOKEN |
unset | X-Worker-Token / Bearer |
AGENT_HARNESS_WORKER_ID |
rein-aharness@hostname |
claim owner |
AGENT_HARNESS_OPS_LABELS |
automated |
claim label filter |
AGENT_HARNESS_OPS_LABELS_MODE |
any |
any or all |
AGENT_HARNESS_OPS_LEASE_SECONDS |
900 |
claim lease |
AGENT_HARNESS_CLAIM_INTERVAL |
30 |
empty-queue poll interval |
AGENT_HARNESS_REPO_MAP |
{} |
JSON slug→checkout path |
AGENT_HARNESS_REPO_ROOTS |
~:~/work |
slug search roots |
Example map on railiance01:
export AGENT_HARNESS_REPO_MAP='{
"freedom-intelligence":"/home/tegwick/freedom-intelligence",
"binky-control":"/home/tegwick/binky-control"
}'
export ACTIVITY_CORE_URL=http://127.0.0.1:8010 # or ClusterIP via tunnel
export ACTIVITY_CORE_WORKER_TOKEN=… # from actcore-runtime-secret
Approach registry
| Match | Approach |
|---|---|
labels research-brief / freedom-intelligence or fi-daily* |
fi-research-brief |
labels rhythm / binky-daily or binky-daily* |
brief-daily |
labels mail-intake |
mail-scan then mail-triage |
labels agent-session |
agentic run (TaskSpec) |
| none | fail ops_run (no silent drop) |
Optional approach_hint on the ops_run overrides matching.
Add a row: edit rein_aharness/approaches.py (APPROACH_RULES + execute_approach)
and tests in tests/test_approaches.py. Prefer cheapest correct path
(structured llm-connect before open-ended agent session).
CLI
# Peek open ops_runs + selected approach
rein-aharness poll --source=ops-run --no-claim
# Claim one, execute approach, complete/fail
rein-aharness run --from-ops-run
# or
rein-aharness poll --source=ops-run
# Continuous worker (systemd)
rein-aharness claim-loop
rein-aharness claim-loop --once --verbose
# Dry-run: claim then fail+reopen without domain work
rein-aharness poll --source=ops-run --dry-run
Legacy issue-core (external tickets only):
rein-aharness poll --source=issue-core
rein-aharness run --from-issue-core
Install claim-loop on railiance01 (user systemd)
# From rein-aharness checkout on railiance01
./deploy/scripts/install-claim-loop-user.sh
# Or manually:
mkdir -p ~/.config/systemd/user
cp deploy/systemd/rein-aharness-claim-loop.service ~/.config/systemd/user/
# Edit Environment= paths / token in the unit or env file
systemctl --user daemon-reload
systemctl --user enable --now rein-aharness-claim-loop.service
journalctl --user -u rein-aharness-claim-loop -f
Port-forward if claim-loop runs on host and API is ClusterIP-only:
kubectl -n activity-core port-forward svc/actcore-api 8010:8010
export ACTIVITY_CORE_URL=http://127.0.0.1:8010
Cutover from host timers (T05)
Host oneshot timers (FI 07:35, Binky rhythm) remain break-glass until:
- claim-loop is running and healthy
- 5 clean weekday cycles (or 5 forced triggers) with open→claimed→succeeded
- Then disable or demote timers — see
deploy/docs/timer-cutover.md
Until then dual-path is intentional: schedule truth is activity-core; timers are a safety net if claim-loop is down.
Labels required on definitions
| Domain | Labels (min) |
|---|---|
| Freedom Intelligence | automated, research-brief (already on FI rule) |
| Binky daily | automated, rhythm |
| Binky mail | automated, mail-intake |