Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02b6f-7db1-7222-918b-e813a6bda38d
157 lines
5.4 KiB
Markdown
157 lines
5.4 KiB
Markdown
# Ops run claim loop (REIN-A-0002)
|
|
|
|
**Primary intake** for activity-core scheduled automation.
|
|
**Architecture:** ACT-ADR-005 · activity-core [ops-run-queue.md](../../activity-core/docs/ops-run-queue.md)
|
|
|
|
Does **not** require issue-core or Forgejo for FI / Binky-style ops.
|
|
|
|
## Flow
|
|
|
|
```text
|
|
activity-core emit_tasks
|
|
→ INSERT ops_run (open, optional harness_profile_ref) + activity_task_spawn
|
|
│
|
|
▼
|
|
rein-aharness claim-loop
|
|
POST /ops-runs/claim
|
|
harness_profile_ref present? ─ yes → Glas ExecutionRequest → gateway
|
|
│ no
|
|
└─→ select_approach(labels, definition, hint) → legacy executor
|
|
POST complete | fail(+reopen)
|
|
```
|
|
|
|
`harness_profile_ref` is authoritative under ACT-ADR-006. A profiled row never
|
|
consults `approach_hint`, `select_approach`, or a legacy executor, including
|
|
after profile resolution refusal. The claim worker sends the complete
|
|
`GatewayResult` to Activity Core; Activity Core persists its allowlisted
|
|
`ExecutionEvidence` and drops direct tool output/error. Profile-absent rows keep
|
|
the legacy coexistence path until the migration flag is enabled upstream.
|
|
|
|
## 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:
|
|
|
|
```bash
|
|
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 `binky` + `weekly-review` or binky-weekly-review* | `brief-weekly` |
|
|
| labels `mail-intake` | `mail-scan` then `mail-triage` |
|
|
| labels `agent-session` | agentic `run` (TaskSpec) |
|
|
| none | fail ops_run (no silent drop) |
|
|
|
|
For a profile-absent legacy row, optional `approach_hint` overrides matching.
|
|
It has no effect when `harness_profile_ref` is present.
|
|
|
|
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
|
|
|
|
```bash
|
|
# 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):
|
|
|
|
```bash
|
|
rein-aharness poll --source=issue-core
|
|
rein-aharness run --from-issue-core
|
|
```
|
|
|
|
## Install claim-loop on railiance01 (user systemd)
|
|
|
|
```bash
|
|
# From rein-aharness checkout on railiance01
|
|
python3 -m venv .venv
|
|
.venv/bin/pip install -e . -e ../llm-connect -e ../sand-boxer -e ../glas-harness
|
|
./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
|
|
```
|
|
|
|
### Host access to cluster services (no port-forward)
|
|
|
|
On railiance01 (single-node k3s), set **k8s://** pseudo-URLs in
|
|
`claim-loop.env` (see `deploy/systemd/claim-loop.env.example`). The
|
|
`~/bin/rein-aharness-claim` wrapper resolves them to Service ClusterIPs at
|
|
start. Canon: activity-core `docs/llm-connect-host-access.md`.
|
|
|
|
```bash
|
|
# migrate existing env
|
|
./deploy/scripts/refresh-claim-loop-k8s-urls.sh
|
|
# reinstall wrapper
|
|
./deploy/scripts/install-claim-loop-user.sh
|
|
systemctl --user restart rein-aharness-claim-loop.service
|
|
```
|
|
|
|
**Deprecated:** long-lived `kubectl port-forward` to 127.0.0.1:8010 / :8080.
|
|
|
|
Legacy note (break-glass only) if ClusterIP routing is broken:
|
|
|
|
```bash
|
|
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:
|
|
|
|
1. claim-loop is running and healthy
|
|
2. **5 clean weekday cycles** (or 5 forced triggers) with open→claimed→succeeded
|
|
3. 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` |
|