Skip to content

Commit e9fbd81

Browse files
jeremymanningclaude
andcommitted
Switch to production mode and update notes
- Survey posts to #general (was DM test mode) - Announcement posts to survey channel / #general (was DM test mode) - Falls back to DM if #general channel lookup fails - Updated scheduling-bot-plan.md to reflect completed status Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4256c2e commit e9fbd81

2 files changed

Lines changed: 38 additions & 87 deletions

File tree

cdl_bot/handlers/schedule.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,11 +466,9 @@ def handle_create_survey(ack, body, client: WebClient, action):
466466
]
467467

468468
try:
469-
# TODO: Change back to #general for production
470-
# channel_id = _find_channel(client, "general")
471-
channel_id = session.dm_channel # TEST MODE: post to DM instead of #general
469+
channel_id = _find_channel(client, "general")
472470
if not channel_id:
473-
channel_id = session.dm_channel
471+
channel_id = session.dm_channel # Fallback to DM if #general not found
474472

475473
result = client.chat_postMessage(
476474
channel=channel_id,
@@ -837,9 +835,7 @@ def handle_approve_schedule(ack, body, client: WebClient, action):
837835
session.groups, session.project_emojis, session.term,
838836
)
839837

840-
# TODO: Change back to survey_channel for production
841-
# channel = session.survey_channel or session.dm_channel
842-
channel = session.dm_channel # TEST MODE
838+
channel = session.survey_channel or _find_channel(client, "general") or session.dm_channel
843839
try:
844840
result = client.chat_postMessage(
845841
channel=channel,

notes/scheduling-bot-plan.md

Lines changed: 35 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,54 @@
11
# CDL Scheduling Bot Implementation Plan
22

3-
## Status: Implementation in progress
3+
## Status: Complete
44

5-
## Source Material
6-
- Notebook: `cdl_bot/CDL_scheduler.ipynb`
7-
- Key functions: `parse_when2meet(url)` and `find_best_meeting_times()`
8-
- Example Slack messages below
5+
All spec items implemented. See `cdl_bot/README.md` for full documentation.
96

10-
## Algorithm Summary
11-
- `parse_when2meet(url)` → DataFrame with (Day, Time) MultiIndex, 1 col per respondent (0/1), 15-min slots
12-
- `find_best_meeting_times(availability, PI, senior, external, groups, preferred_durations)`:
13-
- Attendance maximization with priority weighting (seniors 3x, PI required)
14-
- Biweekly support (duration ending in .5 means biweekly)
15-
- Optimizes for: PI unencumbered time, day concentration, meeting contiguity
16-
- Schedules larger groups first, lab meeting first
17-
- Returns (scheduled_dict, schedule_df)
7+
## Implemented Features
188

19-
## Architecture Decisions
20-
- **Availability**: Use when2meet for everyone (create surveys programmatically via POST)
21-
- **Name matching**: Fuzzy match when2meet names to Slack users, director confirms via dropdown
22-
- **Calendar events**: Google Apps Script web app (serverless, free)
23-
- **Credentials**: GitHub Secrets preferred, or gitignored local file
24-
- **Scheduling algorithm**: Extract from notebook into `cdl_bot/services/scheduling_service.py`
25-
26-
## Flow
27-
1. `/cdl-schedule` → project config modal (names, durations, emojis — NO members)
9+
### Core Flow
10+
1. `/cdl-schedule` → project config modal (names, durations, emojis)
2811
2. Create When2Meet survey → post to #general with emoji reaction instructions
29-
3. "Collect Responses" → scrape When2Meet respondent names
12+
3. "Collect Responses" → scrape When2Meet, auto-populate assignments from emoji reactions
3013
4. Assignment modal: director assigns respondents to projects + marks senior/external
3114
5. Algorithm runs → director reviews proposed schedule
32-
6. Approve → post announcement to #general
33-
34-
## Default Projects & Emojis
35-
Pre-populated from previous terms. Baseline defaults:
36-
37-
| Project | Duration (blocks) | Emoji |
38-
|-|-|-|
39-
| Lab Meeting | 4 | :raising_hand: |
40-
| Kraken | 4 | :octopus: |
41-
| Efficient Learning | 2 | :teacher: |
42-
| StockProphet | 2 | :chart_with_upwards_trend: |
43-
| Brain Dynamics | 2 | :spider_web: |
44-
| Memory Dynamics | 2 | :brain: |
45-
| Asymmetries | 2 | :scales: |
46-
| Jeremy Office Hours | 6 | |
15+
6. Approve → post announcement to #general + create Google Calendar events
16+
17+
### Auto-population
18+
- Project assignments from emoji reactions on survey message
19+
- Senior members from #senior-lab-stuff channel membership
20+
- Term dates scraped from Dartmouth registrar (fallback to approximations)
21+
- Project database pre-populates config modal each term
22+
23+
### Individual Meetings
24+
- :zoom: reaction on survey → director reviews accept/deny + duration
25+
- Accepted meetings join the scheduling algorithm as one-on-one events
26+
- Calendar events created in Moore 349 (vs Moore 416 for group meetings)
27+
28+
### Calendar Integration
29+
- Recurring Google Calendar events with RRULE (weekly/biweekly)
30+
- Term start/end dates define recurrence bounds
31+
- Gracefully skips if GOOGLE_CREDENTIALS_FILE not configured
32+
33+
### Survey Message
34+
- Conversational tone matching spec example
35+
- Deadline computed as Friday before term start (actual date)
36+
- Hybrid meeting details (Moore 416 / Moore 349, Zoom link)
37+
- Lab policy paragraph encouraging exploration
38+
39+
### Announcement Format
40+
- Grouped by day with headers (Monday:, Tuesday:, etc.)
41+
- Indented time entries with (Weekly)/(Biweekly)
42+
- One-on-one meetings displayed as "Individual Meeting (Name)"
4743

4844
## Key Data Structures
4945
- `groups`: dict of meeting_name -> list of member names
5046
- `preferred_durations`: dict of meeting_name -> 15-min blocks (e.g., 4=60min, 2.5=biweekly 30min)
5147
- `PI`, `senior`, `external`: lists for priority weighting
5248
- Project emojis: dict of meeting_name -> emoji
49+
- `zoom_requests`: list of {user_id, name, accepted, duration_blocks}
5350

5451
## Calendar Event Details
5552
- Project meetings: Moore 416, Zoom: https://dartmouth.zoom.us/my/contextlab
5653
- 1:1 meetings: Moore 349, same Zoom link
5754
- Recurring events with term start/end dates
58-
59-
## Example: Survey Request Message (posted to #general)
60-
61-
Hey @channel, happy first day of winter, happy holidays, and happy new year!! :snowflake: :snowman: :new-year: :holidayspirit:
62-
63-
I'd like to nail down our meeting times for the upcoming (Winter 2026) term! To that end, please fill out your availability for weekly meetings (lab meetings + project meetings). Here's a when2meet survey: https://www.when2meet.com/?34050837-QFUDh
64-
65-
Regular meetings will start up again on Monday, January 5 (i.e., on the first day of the term).
66-
67-
Here's the list of our weekly meetings for this term:
68-
69-
Lab meeting (full group): :raising_hand:
70-
Optimizing learning meeting (#mooc-learning + #khan-academy-eeg + #course-shapes + #exploratorium-dartmouth-collab + #efficientlearning): :teacher:
71-
StockProphet/Network Dynamics meeting (#stockprophet + #timecorr): :chart_with_upwards_trend:
72-
Brain dynamics (#directedforgetting + #timecorr + #giblet-decoding + #niinja): :spider_web:
73-
LLMs (#kraken): :octopus:
74-
Memory Dynamics (#memory-dynamics): :brain:
75-
Temporal asymmetries in memory (#prediction-retrodiction + #memory-cueing + #memory-entropy): :scales:
76-
77-
If you would like to have additional individual meetings with me, we can schedule those on an as-needed basis, or you can respond here (or via DM) if you'd like to have a recurring meeting with me (and please specify your desired frequency + duration of those meetings, in addition to filling out your availability on the when2meet survey so that I can match it up with my schedule).
78-
79-
In addition to filling out your availability, please tag this message with the appropriate emoji(s) corresponding to meetings you want to attend (note: everyone should be at the full-lab meetings if at all possible; adding your reaction helps me to gauge who is active in the lab this term). I'll use your responses to figure out times for each of these that accommodate as many people as possible. Everything will go on the CDL calendar, and anyone is welcome at any of the project meetings if you're interested in learning more, even if it's not for your primary project(s). Also feel free to join any channels you're interested in; lurking and/or chiming in sporadically is totally fine/encouraged, as is more regular participation by anyone who is interested. The lab's policy is: anyone can work on any project they are interested in. So if you're new to the group, feel free to explore!
80-
81-
All group meetings will be hybrid: they will occur both in person (either our main lab space/Moore 416, or in the 4th floor library if we can reserve it), and via zoom (https://dartmouth.zoom.us/my/contextlab) if you are feeling sick and/or if you're off campus, etc.. All individual meetings will happen in my office (Moore 349) or via zoom (same link) if one of us is sick and/or off campus.
82-
83-
Please respond by filling out your availability for the winter term in when2meet + adding your emoji reactions to this message by the end of the work day (5pm) on January 4. 2026. That evening, I'll run my script for scheduling our meeting times, and then I'll post the times here. (If you don't fill out your availability by then, your needs/preferences won't be taken into account for scheduling.)
84-
85-
## Example: Schedule Announcement (posted to #general)
86-
87-
Hi @channel! Here's the schedule for this term's meetings:
88-
89-
Monday:
90-
11:30 - 12:00: StockProphet (Weekly)
91-
13:00 - 13:30: Asymmetries (Weekly)
92-
13:30 - 14:00: Individual Meeting (Claudia) (Weekly)
93-
15:00 - 16:00: Kraken (Weekly)
94-
16:00 - 17:00: Lab Meeting (Weekly)
95-
96-
Friday:
97-
11:30 - 12:00: Memory Dynamics (Weekly)
98-
13:30 - 15:00: Jeremy Office Hours (Weekly)
99-
15:00 - 15:30: Efficient Learning (Weekly)

0 commit comments

Comments
 (0)