Add hourly RecentlyOnScope activity definition

This commit is contained in:
2026-05-22 16:14:10 +02:00
parent d10ee0938d
commit 56d7fcb2d4
3 changed files with 289 additions and 8 deletions

View File

@@ -0,0 +1,85 @@
---
id: "d104348c-d792-4377-943c-70a31e81a9bc"
name: "Hourly RecentlyOnScope Reports"
type: activity-definition
version: "1.0"
enabled: false
owner: custodian
governance: custodian
status: draft
created: "2026-05-22"
trigger:
type: cron
cron_expression: "0 * * * *"
timezone: Europe/Berlin
misfire_policy: skip
context_sources:
- type: state-hub
query: recently_on_scope_hourly
required: true
params:
range: "1h"
active_only: true
include_attention: false
bind_to: context.recently_on_scope_hourly
---
# ActivityDefinition: Hourly RecentlyOnScope Reports
## Purpose
This definition is the activity-core handoff point for
`CUST-WP-0046 - Activity-Core Hourly RecentlyOnScope Reports`.
It schedules a deterministic State Hub batch run that generates
RecentlyOnScope reports for every active domain with qualifying activity in the
last hour. State Hub owns active-domain selection and report rendering;
activity-core owns the hourly schedule and ActivityRun audit trail.
## Runner Status
This definition is intentionally `enabled: false` until the manual canary
passes.
Cutover boundary:
- Codex app automation remains a fallback until `CUST-WP-0046-T06`.
- This activity-core definition becomes the primary hourly reporting substrate
only after one manual run and one scheduled run leave expected evidence.
- Do not run a Codex fallback and this activity-core hourly routine as parallel
primary runners.
## Trigger
Hourly at minute 0 in `Europe/Berlin`, with `misfire_policy: skip`.
If the activity-core host is offline at the top of the hour, this routine
skips the missed run rather than replaying a burst of stale reports after the
host returns.
## Deterministic State Hub Invocation
The `recently_on_scope_hourly` State Hub context resolver issues:
- `POST /recently-on-scope/hourly`
- payload: `{"range": "1h", "active_only": true, "include_attention": false}`
The context source is marked `required: true`. A failed State Hub call fails
the activity-core workflow visibly instead of silently binding an empty
context. On success, the response is stored in the ActivityRun
`context_snapshot` under `recently_on_scope_hourly`.
State Hub also records a compact progress event with event type
`recently_on_scope_hourly`, including generated, skipped, and failed domain
metadata.
## Output Contract
The run should produce:
- one State Hub progress event with `event_type: recently_on_scope_hourly`
- one report file per active domain with qualifying activity
- no report for inactive or quiet domains unless State Hub is explicitly
configured otherwise
- one activity-core ActivityRun containing the batch response metadata
- no LLM call and no direct workplan or canon edits

View File

@@ -0,0 +1,137 @@
# Hourly RecentlyOnScope Runbook
## Purpose
This runbook answers whether the hourly RecentlyOnScope routine ran without
opening Codex Desktop.
The intended steady state is:
- activity-core owns the hourly schedule and ActivityRun audit trail.
- State Hub owns active-domain selection, report generation, report storage,
and the `recently_on_scope_hourly` progress event.
- Codex app automation is not part of the primary hourly reporting path after
`CUST-WP-0046-T06`.
## Schedule Check
From the activity-core host, confirm the definition is synced and the Temporal
schedule exists:
```bash
cd ~/activity-core
ACTIVITY_DEFINITION_DIRS=/home/worsch/the-custodian make sync-activity-definitions
make sync-schedules
```
Expected definition:
- name: `Hourly RecentlyOnScope Reports`
- trigger: `0 * * * *`
- timezone: `Europe/Berlin`
- misfire policy: `skip`
- enabled: `false` until manual canary passes, then `true`
## Temporal Check
Use the Temporal UI or CLI on the activity-core host to inspect schedules and
recent workflows.
Look for:
- a schedule for `Hourly RecentlyOnScope Reports`
- the most recent `RunActivityWorkflow`
- a successful workflow result with `tasks_spawned: 0`
A failure in the required State Hub context source should fail the workflow
visibly rather than recording an empty context.
## ActivityRun Check
Query the activity-core database for the most recent run of the hourly
definition:
```sql
select
run_id,
fired_at,
scheduled_for,
context_snapshot->'recently_on_scope_hourly' as batch_result
from activity_runs
where activity_id = 'd104348c-d792-4377-943c-70a31e81a9bc'
order by fired_at desc
limit 5;
```
The `batch_result` should include `generated`, `skipped`, `failed`, and
`progress_event_id`.
## State Hub Progress Check
Ask State Hub for the latest batch progress events:
```bash
curl -s "http://127.0.0.1:8000/progress/?event_type=recently_on_scope_hourly&limit=5" \
| python3 -m json.tool
```
Expected:
- `event_type`: `recently_on_scope_hourly`
- `author`: `state-hub`
- `detail.generated`: domains with qualifying activity
- `detail.skipped`: quiet active domains
- `detail.failed`: empty in the healthy case
## Report Check
List reports for a domain:
```bash
curl -s "http://127.0.0.1:8000/domains/custodian/recently-on-scope/" \
| python3 -m json.tool
```
Read a report:
```bash
curl -s "http://127.0.0.1:8000/domains/custodian/recently-on-scope/<report_id>"
```
Default report directory:
```text
~/state-hub/reports/recently-on-scope/<domain_slug>/
```
## Manual Batch Canary
Before enabling the hourly schedule, run:
```bash
curl -s -X POST "http://127.0.0.1:8000/recently-on-scope/hourly" \
-H "Content-Type: application/json" \
-d '{"range":"1h","active_only":true,"include_attention":false}' \
| python3 -m json.tool
```
Then trigger the activity-core path with the same payload and confirm an
ActivityRun captures the batch response under `recently_on_scope_hourly`.
## Offline Behavior
The schedule uses `misfire_policy: skip`.
If the activity-core host is offline at the top of the hour, that hourly run is
missed. When the host returns, activity-core should resume with the next hourly
slot rather than replaying stale runs in a burst.
## Retention
State Hub currently writes one Markdown report per domain and report id. Report
ids are deterministic for exact windows and are replaced on rerun. The current
implementation does not delete old reports automatically.
Until a retention job exists, operators should treat the report directory as an
append-only operational record and prune only after confirming that no audit or
handoff references point at the target files.

View File

@@ -4,7 +4,7 @@ type: workplan
title: "Activity-Core Hourly RecentlyOnScope Reports"
domain: custodian
repo: the-custodian
status: ready
status: active
owner: codex
topic_slug: custodian
planning_priority: high
@@ -105,7 +105,7 @@ Preferred path:
```task
id: CUST-WP-0046-T01
status: todo
status: in_progress
priority: high
state_hub_task_id: "99e16a50-9775-4520-b343-f52fda0b67ec"
```
@@ -130,7 +130,7 @@ paused/deleted.
```task
id: CUST-WP-0046-T02
status: todo
status: done
priority: high
depends_on: [CUST-WP-0046-T01]
state_hub_task_id: "c5004c0b-a261-407c-9376-a33883e054bf"
@@ -163,7 +163,7 @@ behavior, report idempotency, partial failures, and report metadata response.
```task
id: CUST-WP-0046-T03
status: todo
status: done
priority: high
depends_on: [CUST-WP-0046-T02]
state_hub_task_id: "a33b379f-56ba-47d0-b73c-3e724b1c5d45"
@@ -188,7 +188,7 @@ endpoint and record the result under test.
```task
id: CUST-WP-0046-T04
status: todo
status: in_progress
priority: high
depends_on: [CUST-WP-0046-T03]
state_hub_task_id: "dcb20f5a-c446-48d6-b810-84de365c22fd"
@@ -215,7 +215,7 @@ paused Temporal schedule while disabled.
```task
id: CUST-WP-0046-T05
status: todo
status: in_progress
priority: high
depends_on: [CUST-WP-0046-T04]
state_hub_task_id: "f5c0cf64-a8e9-4d8c-bd86-ca58cbf132c2"
@@ -245,10 +245,11 @@ Done when both manual and scheduled canaries leave complete evidence.
```task
id: CUST-WP-0046-T06
status: todo
status: blocked
priority: high
depends_on: [CUST-WP-0046-T05]
state_hub_task_id: "2a46a6c8-4d3e-4064-a935-c90ca0c76a6d"
blocking_reason: "Waiting for manual and scheduled activity-core canaries before retiring the Codex app fallback."
```
Remove the Codex app automation fallback from the operating path.
@@ -270,7 +271,7 @@ the owned activity-core schedule has verified evidence.
```task
id: CUST-WP-0046-T07
status: todo
status: done
priority: medium
depends_on: [CUST-WP-0046-T05]
state_hub_task_id: "01066ff8-f591-43f6-99e6-d2f61654e590"
@@ -292,6 +293,64 @@ Runbook should include:
Done when the operator can verify hourly report health from State Hub and
activity-core telemetry alone.
## Implementation Evidence - 2026-05-22
Implemented pieces:
- State Hub now exposes `POST /recently-on-scope/hourly`.
- State Hub batch generation reuses the existing RecentlyOnScope collector,
renderer, report id, and report directory.
- The batch endpoint selects domains by qualifying activity in the requested
window: progress events, decisions, updated workstreams, or updated tasks.
- Domains with only registered repositories are skipped; domains with open
human-intervention items can be included by setting `include_attention: true`.
- The batch endpoint records one `recently_on_scope_hourly` progress event with
generated, skipped, and failed domain metadata.
- activity-core has a reusable State Hub resolver query
`recently_on_scope_hourly` that POSTs to the batch endpoint.
- activity-core context sources can now be marked `required: true`; required
resolver failures fail the workflow instead of silently binding `{}`.
- Custodian now owns
`activity-definitions/hourly-recently-on-scope.md`, disabled until canary.
- Operator verification notes live in
`docs/hourly-recently-on-scope-runbook.md`.
Verification:
- State Hub:
`/home/worsch/.local/bin/uv run pytest tests/test_recently_on_scope.py`
passed with 11 tests.
- State Hub:
`/home/worsch/.local/bin/uv run pytest tests/test_recently_on_scope.py tests/test_mcp_smoke.py::TestAddProgressEvent`
passed with 14 tests.
- activity-core:
`/home/worsch/.local/bin/uv run pytest tests/test_state_hub_context_resolver.py tests/test_sync_activity_definitions.py tests/test_schedule_lifecycle.py`
passed with 19 tests.
- activity-core parser scan with
`ACTIVITY_DEFINITION_DIRS=/home/worsch/the-custodian` found
`Hourly RecentlyOnScope Reports`.
Local canary evidence:
- Direct State Hub batch canary generated reports for `custodian` and
`markitect`, skipped 9 quiet active domains, and had no failed domains.
Progress event: `ff1e845f-df02-476e-a3f3-fb912e4f32a8`.
- Direct activity-core resolver canary invoked the same State Hub batch endpoint
and generated reports for `custodian` and `markitect`, skipped 9 domains, and
had no failed domains.
Progress event: `1ff091c3-227c-4a85-b5e2-172ba45a2676`.
Remaining gates:
- T01 remains in progress until the deployed activity-core API/worker/Temporal
schedule path is checked from the operator host.
- T04 remains in progress until the definition is synced into the live
activity-core DB and appears as a disabled/paused Temporal schedule.
- T05 remains in progress until a real `RunActivityWorkflow` produces an
ActivityRun and one scheduled hourly canary completes.
- T06 is blocked until T05 passes; the Codex app fallback should not be paused
or deleted before then.
## Acceptance Criteria
- Hourly RecentlyOnScope reports are generated by activity-core, not Codex app