Split ops runs (claimable DB) from development work records (repo + State Hub), ban default Forgejo queueing for automation, and stack WP-0026 with rein-aharness and issue-core follow-ups. Forgejo-only forge language; no Gitea product path.
5.5 KiB
| id | type | title | domain | repo | status | owner | topic_slug | priority | created | updated | depends_on | related | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ACTIVITY-WP-0026 | workplan | Ops run claim queue — durable claimable work for scheduled automation | infotech | activity-core | ready | grok | activity-core | high | 2026-08-03 | 2026-08-03 |
|
ACTIVITY-WP-0026 — Ops run claim queue
Origin
ACT-ADR-005 (ops runs vs development work records). Closes G2 executor gap without reopening default Forgejo issue spam (ACTIVITY-WP-0022).
Goal
Make internal scheduled automation emit a claimable ops_run in activity-core
so rein-aharness (and peers) can claim, execute, complete, or fail with lease
semantics — while activity-core stays when/what/where only.
Non-goals: execute domain work in Temporal activities; use issue-core or Forgejo as the claim queue; invent Gitea support.
Architecture (target)
Temporal schedule / trigger
→ resolve context (e.g. fi_brief_status)
→ rules produce TaskSpec(s)
→ INSERT ops_run (open) + optional activity_task_spawn progress
→ rein-aharness claim loop
→ complete/fail + domain completion event (fi_daily_brief, …)
Tasks
T01 — Spec ops_run model and API
id: ACTIVITY-WP-0026-T01
status: todo
priority: high
Document in docs/ops-run-queue.md:
| Field | Notes |
|---|---|
id |
UUIDv7 |
activity_definition_id |
FK |
idempotency_key |
unique; e.g. {def}:{date} or hash of spawn key |
target_repo |
string |
title, description |
from TaskSpec |
labels |
JSON array |
priority |
|
state |
open | claimed | succeeded | failed | expired |
claim_owner |
worker identity |
lease_until |
timestamptz |
attempt |
int |
source_type, source_id, triggering_event_id |
audit |
approach_hint |
optional from definition/rule |
result |
JSON completion metadata |
created_at, updated_at |
API (REST on actcore-api):
POST /ops-runs/claimbody:{ worker_id, labels?, limit? }→ runsPOST /ops-runs/{id}/heartbeatextend leasePOST /ops-runs/{id}/complete/failGET /ops-runsfilter by state, definition, since
Auth: same operator/worker posture as existing admin APIs (document; prefer service credential for harness, SSO for humans later).
Done when: spec reviewed against ACT-ADR-005; OpenAPI-ready field list.
T02 — Schema migration + ORM
id: ACTIVITY-WP-0026-T02
status: todo
priority: high
Alembic migration for ops_runs (+ indexes on state, lease_until,
idempotency_key unique). SQLAlchemy model. Unit tests for constraints.
Done when: migrate up/down clean on dev; model tests green.
T03 — Emit path: create ops_run on TaskSpec emit
id: ACTIVITY-WP-0026-T03
status: todo
priority: high
On successful rule emit (internal fleet path):
- Upsert/insert
ops_runwith idempotency (duplicate key → no second open row). - Keep dual-write
activity_task_spawnprogress for transition period. - Still write
task_spawn_logaudit. - Never require Forgejo / issue-core rest for this path.
Default sink remains state-hub for progress; ops_run is additional
primary for claim.
Done when: schedule fire or /trigger produces open ops_run for FI and
Binky-style definitions; tests with mocked sink.
T04 — Claim / lease / expire worker helpers
id: ACTIVITY-WP-0026-T04
status: todo
priority: high
Implement claim with SELECT … FOR UPDATE SKIP LOCKED (or equivalent) and
lease TTL (config: e.g. 15m). Expire job or on-claim sweep: claimed past
lease_until → open (retry) or expired after max attempts.
Done when: concurrent claim tests; lease expiry documented.
T05 — Ops visibility: list + SLA signals
id: ACTIVITY-WP-0026-T05
status: todo
priority: medium
- Extend
/ops/automations/status(or sibling) with open/claimed/failed counts. - Signal: “spawned/open without complete by SLA” (config, default 1h for daily).
- Document in runbook.
Done when: operator can see stuck ops_runs without SQL.
T06 — Contract + consumer guide
id: ACTIVITY-WP-0026-T06
status: todo
priority: medium
Update:
docs/task-emission-consumer-contract.md— claim ops_run, not issue-coredocs/recurring-automations-playbook.md— reference ACT-ADR-005docs/issue-core-emission-boundary.md— ops_run is not issue-core- Use Forgejo naming only (no Gitea product references)
Done when: REIN-A-0002 can implement against the contract without guesswork.
T07 — Railiance rollout + dual-path flag
id: ACTIVITY-WP-0026-T07
status: todo
priority: medium
- Feature flag
OPS_RUN_QUEUE_ENABLED=trueon railiance. - Deploy migration + API.
- Smoke: trigger FI definition → open ops_run visible.
- Coordinate REIN-A-0002 cutover; keep host timers until harness claim proven.
Done when: prod smoke checklist green; flag documented.
Acceptance
- ACT-ADR-005 referenced in SCOPE gaps (G2 disposition → this WP)
- ops_run durable + claimable without Forgejo
- Emit dual-write progress for transition
- Docs use Forgejo-only language for self-hosted forge
- REIN-A-0002 unblocked
Out of scope
- rein-aharness claim loop (REIN-A-0002)
- State Hub full write path for claim (read projection = STATE-WP-0078)
- issue-core internal SQLite “fake queue”
- Gitea compatibility