The notifications that replace the status meeting. Get the volume wrong and users filter the whole product to a folder, after which every downstream metric is measuring a dataset nobody maintains.
Blocked-by: #1 (period engine), #3 (last_update_at must actually be stamped, and stamped correctly).
Files you own
src/flows/reminders.flow.ts (new), pushed into dulyFlows in src/flows/index.ts
test/reminders.test.ts (new)
Three flows, type: 'schedule', runAs: 'system'
1 · Lead-time reminder — to the owner.
Fires once when a task crosses visible_from, and once more 2 days before due_date. Two notifications per task, maximum, ever.
2 · Overdue escalation — to the owner, then the manager.
Day 1 past due_date + grace_days: the owner. Day 7: the owner's manager, as a digest of everything of theirs that is overdue, not one message per task. A manager with 30 late tasks under them must receive one mail, not 30.
3 · Stagnation alert — to the manager, weekly digest only.
Open tasks whose last_update_at is older than 14 days. Never to the owner: "you have not touched this" reads as surveillance, and the owner already sees it in their own list. This one is for the person who can actually unblock it.
Volume discipline — the acceptance criteria, not advice
- Digest by recipient, never fan out per record. Every manager-facing message is one message per recipient per run.
- Idempotent per task per stage. Re-running a flow, or a retry after a partial failure, must not re-notify. Record what was sent — a per-task marker or a notification-log row — and check it before sending.
- Nothing fires for
status in ('done', 'skipped', 'cancelled').
- Nothing fires for duties whose
form is standing — they have no tasks, so this should fall out for free; assert it anyway.
- Nothing fires outside a duty's
effective_from/effective_to window.
- A weekly digest with nothing in it is not sent. An empty status report every Monday is exactly the ritual this product exists to remove.
Do not
- add a daily digest of any kind
- notify anyone about
duly_log_entry
- include a count comparison between people in any digest
Acceptance
- a task crossing
visible_from produces exactly one owner notification; re-running the flow that day produces zero more
- a manager with 30 overdue tasks beneath them receives one digest listing 30, not 30 messages
- completing a task before its due date produces no further notifications of any kind
- the stagnation digest never addresses the task owner
- an empty digest window sends nothing
- flow conditions are all
record.<field>-qualified; pnpm validate passes
Gates
pnpm validate && pnpm typecheck && pnpm test && pnpm build.
The notifications that replace the status meeting. Get the volume wrong and users filter the whole product to a folder, after which every downstream metric is measuring a dataset nobody maintains.
Blocked-by: #1 (period engine), #3 (
last_update_atmust actually be stamped, and stamped correctly).Files you own
src/flows/reminders.flow.ts(new), pushed intodulyFlowsinsrc/flows/index.tstest/reminders.test.ts(new)Three flows,
type: 'schedule',runAs: 'system'1 · Lead-time reminder — to the owner.
Fires once when a task crosses
visible_from, and once more 2 days beforedue_date. Two notifications per task, maximum, ever.2 · Overdue escalation — to the owner, then the manager.
Day 1 past
due_date + grace_days: the owner. Day 7: the owner's manager, as a digest of everything of theirs that is overdue, not one message per task. A manager with 30 late tasks under them must receive one mail, not 30.3 · Stagnation alert — to the manager, weekly digest only.
Open tasks whose
last_update_atis older than 14 days. Never to the owner: "you have not touched this" reads as surveillance, and the owner already sees it in their own list. This one is for the person who can actually unblock it.Volume discipline — the acceptance criteria, not advice
status in ('done', 'skipped', 'cancelled').formisstanding— they have no tasks, so this should fall out for free; assert it anyway.effective_from/effective_towindow.Do not
duly_log_entryAcceptance
visible_fromproduces exactly one owner notification; re-running the flow that day produces zero morerecord.<field>-qualified;pnpm validatepassesGates
pnpm validate && pnpm typecheck && pnpm test && pnpm build.