79 lines
3.2 KiB
Markdown
79 lines
3.2 KiB
Markdown
|
|
# Task emission consumer contract
|
||
|
|
|
||
|
|
**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).
|
||
|
|
|
||
|
|
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)
|
||
|
|
|
||
|
|
| `ISSUE_SINK_TYPE` | Behaviour | When to use |
|
||
|
|
| --- | --- | --- |
|
||
|
|
| **`state-hub` (default)** | POST State Hub `/progress/` with `event_type=activity_task_spawn` (override via `STATE_HUB_TASK_EVENT_TYPE`) | Internal fleet findings; no Forgejo issues |
|
||
|
|
| **`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).
|
||
|
|
|
||
|
|
## Payload: `activity_task_spawn` (State Hub)
|
||
|
|
|
||
|
|
Produced by `StateHubProgressSink`. Consumers should treat `detail` as the
|
||
|
|
authoritative task spec.
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"event_type": "activity_task_spawn",
|
||
|
|
"author": "activity-core",
|
||
|
|
"summary": "<task title, max ~240 chars>",
|
||
|
|
"detail": {
|
||
|
|
"task_ref": "sh-<uuid>",
|
||
|
|
"title": "Run Binky daily rhythm (daily_brief) for 2026-07-21",
|
||
|
|
"description": "...",
|
||
|
|
"target_repo": "binky-control",
|
||
|
|
"priority": "medium",
|
||
|
|
"labels": ["binky", "rhythm", "automated"],
|
||
|
|
"source_type": "rule",
|
||
|
|
"source_id": "emit-daily-rhythm-task",
|
||
|
|
"triggering_event_id": "manual-… or scheduled",
|
||
|
|
"activity_definition_id": "<activity uuid>",
|
||
|
|
"backend": "state-hub-progress"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Required consumer behaviour
|
||
|
|
|
||
|
|
1. **Idempotency:** key on `detail.task_ref` or
|
||
|
|
`(activity_definition_id, triggering_event_id, source_id, title)`.
|
||
|
|
2. **Routing:** use `target_repo` (and labels) to select checkout / lane.
|
||
|
|
3. **Completion evidence:** post a domain progress event when work finishes
|
||
|
|
(e.g. Binky: `event_type=binky_daily_brief` with `detail.repo=binky-control`
|
||
|
|
and date), so rhythm resolvers can set `due=false`.
|
||
|
|
4. **Do not** re-implement task lifecycle in activity-core.
|
||
|
|
|
||
|
|
## Payload: issue-core REST (`ISSUE_SINK_TYPE=rest`)
|
||
|
|
|
||
|
|
See `docs/issue-core-emission-boundary.md`. `task_spawn_log.task_ref` is the
|
||
|
|
issue-core `issue_id`. Prefer this only for intentional external projection.
|
||
|
|
|
||
|
|
## Binky daily brief path (reference)
|
||
|
|
|
||
|
|
1. Schedule / one-shot: `Binky Daily Operating Rhythm`.
|
||
|
|
2. Context: `binky_rhythm_status` → `due=true` for `daily_brief`.
|
||
|
|
3. Rule emit → sink (`state-hub` recommended).
|
||
|
|
4. **Consumer (out of repo):** agent-harness or operator session runs
|
||
|
|
`binky-control` OperatingRhythm / brief scripts.
|
||
|
|
5. Completion: post `binky_daily_brief` progress so the next fire is not due.
|
||
|
|
|
||
|
|
Until a harness consumer is wired, operators may complete the brief manually
|
||
|
|
and still post the progress event — spawn without completion leaves `due=true`.
|
||
|
|
|
||
|
|
## Anti-patterns
|
||
|
|
|
||
|
|
- 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.
|