Implement ACTIVITY-WP-0026 ops_run claim queue (T01–T06).
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 52s

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.
This commit is contained in:
tegwick 2026-08-03 19:22:50 +02:00
parent a145cc4027
commit 15eb3a2066
15 changed files with 1294 additions and 27 deletions

View file

@ -2,12 +2,34 @@
**Audience:** agent-harness, per-repo Temporal workers, operators.
**Owners:** activity-core (producer), consumers (executors).
**Related:** ACTIVITY-WP-0022 (sink policy), ACTIVITY-WP-0023-T02 (executor gap).
**Related:** ACTIVITY-WP-0022 (sink policy), ACTIVITY-WP-0023-T02 (executor gap),
**ACT-ADR-005 / ACTIVITY-WP-0026** (ops_run claim queue).
activity-core answers **when / what / where**. It does **not** execute work.
Consumers must pick up emitted tasks and produce domain evidence.
## Sink matrix (ACTIVITY-WP-0022)
## Primary claim path: `ops_run` (ACTIVITY-WP-0026)
For **scheduled / automation** work (FI daily brief, Binky rhythm, etc.), the
authoritative claimable instance is an **`ops_run`** row in activity-core — not
issue-core and not a Forgejo ticket.
| Step | Call | Notes |
| ---- | ---- | ----- |
| List / poll | `GET /ops-runs?state=open` | Filter by labels via claim body |
| Claim | `POST /ops-runs/claim` | `{ worker_id, labels?, limit?, lease_seconds? }` |
| Heartbeat | `POST /ops-runs/{id}/heartbeat` | Extend lease during long runs |
| Complete | `POST /ops-runs/{id}/complete` | `{ worker_id, result }` |
| Fail | `POST /ops-runs/{id}/fail` | `{ worker_id, error, reopen? }` |
Full field list, auth, and env: **`docs/ops-run-queue.md`**.
Consumer implementation (rein-aharness): **REIN-A-0002**.
Emit dual-writes: `ops_run` (claim) + existing IssueSink progress (`state-hub`
by default) + `task_spawn_log` audit. Do **not** treat `activity_task_spawn`
progress as a claim queue — it is visibility only.
## Sink matrix (ACTIVITY-WP-0022) — dual-write / projection
| `ISSUE_SINK_TYPE` | Behaviour | When to use |
| --- | --- | --- |
@ -15,12 +37,13 @@ Consumers must pick up emitted tasks and produce domain evidence.
| **`null`** | Synthetic `null-*` refs in `task_spawn_log` only | Dry-run / contract review |
| **`rest`** | POST issue-core `/issues/` (may project to Forgejo) | **Explicit opt-in** only when external tracker issues are intended and backend is healthy |
Unset or unknown values fall back to **`state-hub`** (safe default).
Unset or unknown values fall back to **`state-hub`** (safe default).
Ops claim does **not** require `rest` or issue-core.
## Payload: `activity_task_spawn` (State Hub)
Produced by `StateHubProgressSink`. Consumers should treat `detail` as the
authoritative task spec.
**visibility** task spec; claim authority is `ops_run` when the queue is enabled.
```json
{
@ -75,4 +98,7 @@ and still post the progress event — spawn without completion leaves `due=true`
- Using `TaskExecutorWorkflow` in activity-core for real work (disabled by
default; ACTIVITY-WP-0023-T08).
- Global `ISSUE_SINK_TYPE=rest` for all definitions (reintroduces Forgejo spam).
- Treating `task_spawn_log` as task status authority.
- Treating `task_spawn_log` or State Hub `activity_task_spawn` as claim authority
(use `POST /ops-runs/claim` — ACT-ADR-005).
- Using issue-core or Forgejo as the ops automation claim queue.
- Product references to **Gitea** — self-hosted forge is **Forgejo** only.