Add durable claimable ops_runs table, emit dual-write on TaskSpec, REST claim/lease/complete/fail API, ops status visibility, and consumer docs aligned with ACT-ADR-005. T07 railiance rollout remains deploy-side.
3.9 KiB
3.9 KiB
Ops run claim queue
Status: implemented (ACTIVITY-WP-0026 code path; railiance rollout = T07)
Architecture: ACT-ADR-005
Durable, claimable work instances for scheduled / automation runs. Not a workplan task file. Not an issue-core or Forgejo ticket.
Model
| Field | Type | Notes |
|---|---|---|
id |
UUID | Primary key (uuid4; UUIDv7 optional later) |
activity_definition_id |
UUID | FK → activity_definitions |
idempotency_key |
text | Unique; default {activity_id}:{source_id}:{triggering_event_id} |
target_repo |
text | From TaskSpec |
title |
text | |
description |
text | |
labels |
JSONB array | e.g. ["automated","research-brief"] |
priority |
text | low | medium | high |
state |
text | open | claimed | succeeded | failed | expired |
claim_owner |
text nullable | Worker identity |
lease_until |
timestamptz nullable | Claim lease deadline |
attempt |
int | Starts at 0; incremented on each claim |
source_type |
text | rule | instruction |
source_id |
text | Rule id |
triggering_event_id |
text | Event or workflow key |
approach_hint |
text nullable | Optional from rule |
result |
JSONB | Completion metadata |
created_at / updated_at |
timestamptz |
API (actcore-api)
| Method | Path | Role |
|---|---|---|
GET |
/ops-runs |
List/filter |
GET |
/ops-runs/{id} |
One row |
POST |
/ops-runs/claim |
Claim open runs (lease) |
POST |
/ops-runs/{id}/heartbeat |
Extend lease |
POST |
/ops-runs/{id}/complete |
succeeded |
POST |
/ops-runs/{id}/fail |
failed (+ optional reopen) |
POST |
/ops-runs/expire-leases |
Reopen or expire stale claims |
Claim body
{
"worker_id": "rein-aharness@railiance01",
"labels": ["automated"],
"labels_mode": "any",
"limit": 1,
"lease_seconds": 900
}
labels_mode:any(default) — run must contain at least one listed label;all— run must contain every listed label; omitlabelsto claim any open run.- Claim uses
FOR UPDATE SKIP LOCKEDfor concurrency safety. - Stale claims (
state=claimedandlease_until < now()) are reopened before select.
Complete / fail body
{ "result": { "path": "briefs/…", "ok": true }, "worker_id": "…" }
{ "error": "llm timeout", "worker_id": "…", "reopen": false }
If reopen: true and attempt < max_attempts (env OPS_RUN_MAX_ATTEMPTS, default 3),
state returns to open; else failed.
Emit path
On emit_tasks (when OPS_RUN_QUEUE_ENABLED is truthy, default true):
- Insert
ops_runwithstate=open(idempotent on unique key). - Dual-write existing IssueSink (
state-hubprogress by default). - Write
task_spawn_logaudit as today.
Never requires Forgejo or issue-core for the claim path.
Auth
- Worker:
ACTIVITY_CORE_WORKER_TOKENviaX-Worker-TokenorAuthorization: Bearer(same value accepted on claim/complete/fail/heartbeat). - Operator: existing ops SSO /
ACTIVITY_CORE_OPERATOR_TOKENfor list/status. - Local dev:
ACTIVITY_CORE_OPS_ALLOW_UNAUTH_MUTATIONS=1when no tokens set.
Env
| Variable | Default | Meaning |
|---|---|---|
OPS_RUN_QUEUE_ENABLED |
true |
Create ops_run on emit |
OPS_RUN_LEASE_SECONDS |
900 |
Default claim lease |
OPS_RUN_MAX_ATTEMPTS |
3 |
Fail permanently after N claims |
ACTIVITY_CORE_WORKER_TOKEN |
unset | Harness claim credential |
Consumer (rein-aharness)
See REIN-A-0002. Claim loop → approach table → execute → complete + domain
completion event (fi_daily_brief, etc.).
Not this queue
| Concern | Home |
|---|---|
| Multi-day engineering tasks | Workplan files + State Hub |
| External tracker tickets | issue-core → Forgejo (optional projection) |
| Schedule truth | Temporal + activity definitions |