Implement REIN-A-0002 ops_run claim loop and approach registry.
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.
This commit is contained in:
parent
9644202eb2
commit
8200a672ea
15 changed files with 1807 additions and 73 deletions
128
docs/ops-run-claim-loop.md
Normal file
128
docs/ops-run-claim-loop.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
# 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) + 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:
|
||||
|
||||
```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 `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
|
||||
|
||||
```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
|
||||
./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:
|
||||
|
||||
```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` |
|
||||
|
|
@ -1,70 +1,89 @@
|
|||
# Task intake (HARNESS-WP-0001-T03)
|
||||
# Task intake
|
||||
|
||||
activity-core emits tasks via IssueSink → `POST /issues/` on **issue-core**.
|
||||
rein-aharness **consumes** them by polling the same service:
|
||||
**Architecture:** ACT-ADR-005 · ACTIVITY-WP-0026 · REIN-A-0002
|
||||
|
||||
## Primary: activity-core `ops_run` (scheduled automation)
|
||||
|
||||
Internal fleet automation (FI daily brief, Binky rhythm, mail intake, …)
|
||||
emits a claimable **`ops_run`** in activity-core. rein-aharness claims that
|
||||
row — **not** issue-core and **not** Forgejo.
|
||||
|
||||
```
|
||||
activity-core (cron/rule)
|
||||
→ IssueCoreRestSink POST /issues/
|
||||
→ issue-core backend (sqlite / gitea)
|
||||
→ rein-aharness poll/claim GET+PATCH /issues/
|
||||
→ run_task (profile + budget + persona + session)
|
||||
→ PATCH close + hub progress + .kaizen/metrics
|
||||
activity-core (Temporal + rules)
|
||||
→ INSERT ops_run (open) + dual-write activity_task_spawn (state-hub)
|
||||
→ rein-aharness claim-loop
|
||||
POST /ops-runs/claim → approach registry → execute → complete/fail
|
||||
→ domain completion events (fi_daily_brief, binky_daily_brief, …)
|
||||
```
|
||||
|
||||
`TaskExecutorWorkflow` stays a stub (activity-core INTENT); execution lives here.
|
||||
Full guide: **`docs/ops-run-claim-loop.md`**.
|
||||
|
||||
## Mail path (server / Railiance)
|
||||
### CLI
|
||||
|
||||
```
|
||||
rein-aharness mail-scan # deterministic IMAP (AppRole)
|
||||
rein-aharness mail-triage # llm-connect HTTP → JSON → apply mail-log + commit
|
||||
```bash
|
||||
export ACTIVITY_CORE_URL=http://127.0.0.1:8010
|
||||
export ACTIVITY_CORE_WORKER_TOKEN=…
|
||||
export AGENT_HARNESS_REPO_MAP='{"freedom-intelligence":"~/freedom-intelligence","binky-control":"~/binky-control"}'
|
||||
|
||||
rein-aharness poll --source=ops-run --no-claim
|
||||
rein-aharness run --from-ops-run
|
||||
rein-aharness claim-loop
|
||||
```
|
||||
|
||||
Requires `LLM_CONNECT_URL` (e.g. in-cluster
|
||||
`http://llm-connect.activity-core.svc.cluster.local:8080`). Optional:
|
||||
`MAIL_TRIAGE_MODEL`, `MAIL_TRIAGE_MAX_TOKENS`, `MAIL_TRIAGE_MAX_ROWS`.
|
||||
**No Claude CLI** on the host.
|
||||
`TaskExecutorWorkflow` in activity-core stays a stub; execution lives here.
|
||||
|
||||
## issue-core worker API
|
||||
---
|
||||
|
||||
## Legacy / external: issue-core poll
|
||||
|
||||
issue-core remains for **external tracker tickets** and intentional
|
||||
`ISSUE_SINK_TYPE=rest` projections to **Forgejo** (self-hosted forge only —
|
||||
no Gitea product path).
|
||||
|
||||
```
|
||||
activity-core (optional rest sink)
|
||||
→ issue-core POST /issues/
|
||||
→ rein-aharness poll --source=issue-core
|
||||
→ run_task / close
|
||||
```
|
||||
|
||||
Do **not** use this path as the claim queue for FI/Binky ops under WP-0022.
|
||||
|
||||
### issue-core worker API
|
||||
|
||||
| Method | Path | Role |
|
||||
|--------|------|------|
|
||||
| POST | `/issues/` | Ingest (activity-core) |
|
||||
| POST | `/issues/` | Ingest (activity-core rest sink) |
|
||||
| GET | `/issues/?state=open&label=automated` | Poll queue |
|
||||
| GET | `/issues/{id}` | Fetch one |
|
||||
| PATCH | `/issues/{id}` | Claim (`in_progress` + assignee) or `closed` |
|
||||
|
||||
Auth: `Authorization: Bearer $ISSUE_CORE_API_KEY` or `X-API-Key`.
|
||||
|
||||
## CLI
|
||||
|
||||
```bash
|
||||
export ISSUE_CORE_URL=http://127.0.0.1:8765 # or in-cluster service
|
||||
export ISSUE_CORE_URL=http://127.0.0.1:8765
|
||||
export ISSUE_CORE_API_KEY=…
|
||||
export AGENT_HARNESS_REPO_MAP='{"binky-control":"/home/tegwick/binky-control"}'
|
||||
|
||||
# Peek / claim without executing
|
||||
rein-aharness poll
|
||||
rein-aharness poll --no-claim
|
||||
|
||||
# Claim → run → close (or reopen on failure)
|
||||
rein-aharness poll --source=issue-core
|
||||
rein-aharness run --from-issue-core
|
||||
|
||||
# Local dev (unchanged)
|
||||
rein-aharness run --task-file examples/task-hello-sandbox.json --no-hub
|
||||
```
|
||||
|
||||
## Label filter
|
||||
Default label filter: **`automated`** (`AGENT_HARNESS_INTAKE_LABELS`).
|
||||
|
||||
Default: issues must carry the **`automated`** label (matches activity-core
|
||||
binky definitions). Override:
|
||||
---
|
||||
|
||||
```bash
|
||||
export AGENT_HARNESS_INTAKE_LABELS=automated,harness # ALL required
|
||||
## Mail path (server / Railiance)
|
||||
|
||||
```
|
||||
rein-aharness mail-scan # deterministic IMAP (AppRole)
|
||||
rein-aharness mail-triage # llm-connect HTTP → JSON → apply mail-log + commit
|
||||
# or via claim-loop when ops_run labels include mail-intake
|
||||
```
|
||||
|
||||
## Agent + completion event mapping
|
||||
Requires `LLM_CONNECT_URL`. **No Claude CLI** required for mail/brief approaches.
|
||||
|
||||
---
|
||||
|
||||
## Agent + completion event mapping (issue-core / agent-session)
|
||||
|
||||
From `activity_definition_id` or labels:
|
||||
|
||||
|
|
@ -75,11 +94,12 @@ From `activity_definition_id` or labels:
|
|||
| `binky-weekly-review-prep` / `weekly-review` | `review-prep` | `binky_weekly_review` |
|
||||
| else | `coach` | `executor_run` |
|
||||
|
||||
Instance policy (`tool_profile`, `budget`, `lane`) still comes from the
|
||||
target repo's `.kaizen/schedule.yml`.
|
||||
Approach registry for ops_run (preferred): see `docs/ops-run-claim-loop.md`.
|
||||
|
||||
---
|
||||
|
||||
## Repo path resolution
|
||||
|
||||
1. Absolute/expanded path if it is already a git repo
|
||||
2. `AGENT_HARNESS_REPO_MAP` JSON
|
||||
3. Search `AGENT_HARNESS_REPO_ROOTS` (default `~:~/work`) for the slug
|
||||
3. Search `AGENT_HARNESS_REPO_ROOTS` (default `~:~/work`) for the slug
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue