diff --git a/activity-definitions/hourly-recently-on-scope.md b/activity-definitions/hourly-recently-on-scope.md new file mode 100644 index 0000000..ff80ccc --- /dev/null +++ b/activity-definitions/hourly-recently-on-scope.md @@ -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 diff --git a/docs/hourly-recently-on-scope-runbook.md b/docs/hourly-recently-on-scope-runbook.md new file mode 100644 index 0000000..e35a24c --- /dev/null +++ b/docs/hourly-recently-on-scope-runbook.md @@ -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/" +``` + +Default report directory: + +```text +~/state-hub/reports/recently-on-scope// +``` + +## 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. diff --git a/workplans/CUST-WP-0046-hourly-recently-on-scope-activity-core.md b/workplans/CUST-WP-0046-hourly-recently-on-scope-activity-core.md index 588800e..8b47ac8 100644 --- a/workplans/CUST-WP-0046-hourly-recently-on-scope-activity-core.md +++ b/workplans/CUST-WP-0046-hourly-recently-on-scope-activity-core.md @@ -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