mirror of
https://github.com/Sea-Haven-Industries/afterhours-shift-manager.git
synced 2026-10-03 22:33:12 +00:00
The Monday rollover deleted last week's schedule message and posted a fresh one every week, which re-notified the channel, changed the permalink, and dropped any thread/reactions. Roll the two-week window forward by editing the stored message in place (the same chat_update path in-week shift changes already use), falling back to a fresh, pinned post on first run or when the edit fails. A native pin keeps it reachable from the channel header now that it no longer rises on the weekly repost. Records the evaluation behind this in docs/sticky-schedule-post.md. Refs: #135
114 lines
5.4 KiB
Markdown
114 lines
5.4 KiB
Markdown
# Evaluation: sticky / reused weekly schedule post
|
|
|
|
_Spike for issue #135 — decide how the Monday two-week schedule post should
|
|
behave across weeks. This document records the decision and the rationale; the
|
|
recommended option (a) is implemented in the same PR._
|
|
|
|
## Background
|
|
|
|
`src/weekly-post/app.py` (the Monday 7am ET Lambda) currently, every week:
|
|
|
|
1. `chat_delete` the previous week's schedule post (stored `ts` from
|
|
`get_schedule_post`),
|
|
2. `chat_postMessage` a brand-new two-week schedule message, and
|
|
3. `save_schedule_post(channel_id, new_ts, …)`.
|
|
|
|
So every Monday the post gets a new `ts` (new permalink), re-notifies the
|
|
channel, and loses any thread/reactions. During the week it steadily sinks as
|
|
people chat.
|
|
|
|
The infrastructure to edit in place **already exists**: in-week shift changes
|
|
(`pick` / `drop` / `swap` / `admin`) call `_refresh_schedule_post()`
|
|
(`src/slack-bot/app.py`), which does a `chat_update` against the stored `ts`.
|
|
The weekly rollover is the *only* place that creates a fresh message.
|
|
|
|
## Options considered
|
|
|
|
### (a) Reuse the same post across weeks — **recommended**
|
|
|
|
On Monday, `chat_update` the existing message to roll the two-week window
|
|
forward instead of delete + repost.
|
|
|
|
- **Pros:** stable permalink; no weekly re-notification; keeps any
|
|
thread/reactions; trivial change (reuses the `_refresh_schedule_post`
|
|
`chat_update` pattern already in the codebase).
|
|
- **Cons:** the message stays where it was first posted — it does **not** rise
|
|
to the bottom as the channel gets new activity.
|
|
|
|
### (b) True stickybot behavior — keep it pinned to the bottom
|
|
|
|
Slack has no native "sticky" message. Stickybot-style bots subscribe to channel
|
|
message events and **delete + repost** the bot message whenever someone else
|
|
posts, so it is always last.
|
|
|
|
- **Pros:** always visible at the bottom of the channel.
|
|
- **Cons:** directly conflicts with (a)'s stable permalink (every repost = new
|
|
`ts`); requires a new event subscription (`message.channels`) and the
|
|
`channels:history` scope (a reinstall); needs dedupe/debounce plus Slack
|
|
rate-limit handling; constant repost churn; many more moving parts and a new
|
|
always-on event path to operate. The benefit (bottom-of-channel visibility)
|
|
is marginal for a low-traffic on-call channel.
|
|
|
|
### (c) Status quo — delete + repost weekly
|
|
|
|
- **Pros:** the weekly repost bumps the post to the bottom once a week.
|
|
- **Cons:** new permalink every week; a weekly re-notification; loses
|
|
thread/reactions; the post still sinks for the rest of the week.
|
|
|
|
## Decision
|
|
|
|
Adopt **(a) reuse-in-place**, complemented by a **native Slack pin** so the post
|
|
stays reachable from the channel header even as the channel fills with chatter.
|
|
Reject **(b)** — its only advantage over a pin is keeping the post at the literal
|
|
bottom, which is not worth a new event subscription, an extra scope, and
|
|
rate-limit/debounce machinery for this channel. The pin recovers most of the
|
|
discoverability that the weekly bump used to provide, at the cost of one extra
|
|
API call and one extra scope (`pins:write`), with no new event path to operate.
|
|
|
|
## What changes (option a)
|
|
|
|
In `src/weekly-post/app.py`, on the Monday rollover:
|
|
|
|
- **Drop the unconditional `chat_delete`.** There is no previous message to
|
|
remove when we reuse the same one.
|
|
- **`chat_update` the stored post** to roll the two-week window forward, keeping
|
|
the same `ts` (stable permalink, no re-notification).
|
|
- **First-run / recovery fallback:** when there is no stored post, or the
|
|
`chat_update` fails (e.g. the message was deleted manually), fall back to
|
|
`chat_postMessage` and **pin** the new message.
|
|
- **Keep `save_schedule_post` / `get_schedule_post`.** Still needed — they hold
|
|
the `ts` that both the weekly rollover and `_refresh_schedule_post` edit. On
|
|
reuse the stored `ts` is unchanged; on a fresh post it is updated to the new
|
|
`ts` and the new `week_start`.
|
|
|
|
### Interaction with `_refresh_schedule_post`
|
|
|
|
No change needed. Both paths now converge on a single long-lived message keyed
|
|
by the stored `ts`: the weekly Lambda rolls the window forward each Monday, and
|
|
in-week shift changes keep editing the same message. They never fight because
|
|
neither creates a new `ts` while one already exists.
|
|
|
|
### The "ever-growing edited message" / retention question
|
|
|
|
A `chat_update` does not grow channel history — it rewrites one message in place
|
|
rather than appending. Slack keeps the message's original post time, so an
|
|
edited-forever post sorts by where it was first posted (hence the pin). There is
|
|
no retention or history-size concern from editing the same message indefinitely.
|
|
|
|
## Scope / manifest impact
|
|
|
|
- `pins:write` is added to `slack-app-manifest.yaml` for the native pin. This is
|
|
a new OAuth scope, so the app must be **reinstalled** once for the pin to take
|
|
effect. The pin call is best-effort: until the reinstall happens (or if the
|
|
bot lacks the scope) it logs and is skipped, and the reuse-in-place behavior
|
|
still works without it.
|
|
- No new event subscriptions. Option (b)'s `message.channels` event and
|
|
`channels:history` scope are **not** added.
|
|
|
|
## Follow-ups (not in this PR)
|
|
|
|
- After deploy, reinstall the Slack app so `pins:write` takes effect, then
|
|
confirm the first rolled-forward post gets pinned.
|
|
- Optional: a one-line threaded note on the rolled-forward post if we later
|
|
decide we still want a light weekly nudge (kept out here on purpose — the whole
|
|
point of (a) is to stop the weekly re-notification).
|