risk-nexus/activity-definitions/hourly-register-inbox-watch.md
tegwick 2ebdc133bc Drop dedupe_key_strategy from the inbox watch and say what actually happens
activity-core corrected us: it governs Temporal schedule overlap, not
per-message suppression, and there is no dedupe at the sink — so an
unread message re-emits hourly until read. Removed the field rather than
leave it implying a guarantee it does not give, and kept the repetition
deliberately: an hourly line in the progress log is a cheap price for the
failure this exists to prevent, and it stops when somebody reads.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 12:02:14 +02:00

99 lines
3.6 KiB
Markdown

---
id: hourly-register-inbox-watch
name: Hourly Register Inbox Watch
type: activity-definition
version: "1.0"
enabled: true
owner: risk-nexus
governance: custodian
status: active
created: "2026-08-20"
updated: "2026-08-20"
trigger:
type: cron
cron_expression: "5 * * * *"
timezone: Europe/Berlin
misfire_policy: skip
context_sources:
- type: state-hub
query: hub_inbox
required: true
params:
to_agent: risk-nexus
unread_only: true
bind_to: context.inbox
report_sinks:
- type: state-hub-progress
event_type: risk_register_inbox
author: activity-core
---
# Hourly Register Inbox Watch
Runs hourly at :05 Berlin time. Fires only when something is actually waiting.
## Why hourly, and why the inbox specifically
`docs/method/review.md` sets an adaptive cadence whose shortest rung is one
hour, so hourly is the finest granularity the register can act on. Anything
faster would report work that cannot yet be due.
The inbox is the trigger rather than the clock because of what happened on
2026-08-19: this register graded `RISK-F-0001` `critical` and prepared an
escalation while two messages sat unread — one narrowing the exposure, one
reporting the fix. Both changed the grade. Reading the inbox is now question
zero of every check (`docs/method/check-procedure.md`), and this activity is
the mechanism that stops it depending on somebody remembering.
An unread message addressed to `risk-nexus` is, by construction, a claim that
something in the register may have moved.
## It will repeat, and that is the deliberate choice
`activity-core` corrected us on 2026-08-20: `dedupe_key_strategy` governs
Temporal schedule overlap, not per-message suppression, and cron workflow ids
include `scheduled_for` — so an unread message re-emits an instruction **every
hour until it is read**. There is no dedupe at the sink either.
We removed the field rather than leave it there implying a guarantee it does
not give.
The repetition is kept, on purpose. An unread message addressed to this
register is a claim that something in it may have moved, and the failure this
activity exists to prevent — grading `RISK-F-0001` `critical` while its fix
notice sat unread — cost a wrong grade and a nearly-sent escalation. An hourly
line in the progress log is a cheap price for that, and it stops the moment
somebody reads the message.
**Reading a message includes marking it read.** That is what clears the nag,
and it is part of question zero rather than a courtesy.
If this ever becomes real noise — an unattended weekend, a message nobody can
action — the fix `activity-core` named is a stable completion key gating the
rule, not a longer interval. A longer interval would trade a visible cost for
an invisible one.
## What it does not do
It does not grade, close, publish or escalate anything. Severity, disclosure
and escalation are judgements this repo makes with a human or an agent session
doing the reading — never a cron. This activity's entire job is to make sure
somebody looks.
```rule
id: inbox-has-spoken
for_each: context.inbox
bind_as: message
condition: 'context.message.read_at == None'
action:
task_template: 'risk-nexus: read {context.message.from_agent} before checking'
description: >-
Unread message to risk-nexus from {context.message.from_agent}:
"{context.message.subject}". Read it before any check or grading — this is
question zero in docs/method/check-procedure.md. Then run `make due` in
risk-nexus and work the list, recording each outcome with
`make checked ARGS="<finding-id> clean|moved"`.
target_repo: risk-nexus
priority: high
labels: ["risk-register", "inbox", "question-zero"]
```