Repository navigation
Let invitees suggest other times for the organizer to add - #44
Merged
Merged
Conversation
When none of the proposed times work, someone invited can suggest up to five others: suggest_slots over MCP, or a "None of these work?" form on the voting page. The organizer is emailed once per call that adds suggestions and decides: propose_more_slots with suggestionIds (or "Add to the poll" on the event page) adds them as a new round, which emails everyone invited as new times always did; dismiss_suggestions (or "Dismiss") emails no one, and the participant sees "not added" on their voting page. Suggestions are their own rows (SlotSuggestion), so like votes they don't move the organizer's version. Only the organizer and the person who suggested a time see it. Retrying is safe: a time already proposed or already suggested isn't suggested again, and a dismissed one can't be re-suggested. At most five can wait per participant, which also bounds the email one person can cause. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZSHCijStZzTcMJSBYoY6t
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved concurrency, slot-resolution, status-visibility, and email-length defects can create duplicate suggestions, fail or mis-time slot additions, hide organizer decisions, and roll back submissions.
6 open issues
Bound notification subjects to the outbox limit · New Serialize suggestion checks and inserts to prevent concurrent duplicates · New Resolve stored suggestions consistently after time-zone updates · New Preserve seconds when converting suggestions to slots · New Deduplicate selected slots by instant before adding suggestions · New Show existing suggestions when voting is closed · New
1 file not reviewed
src/Scheduler.Data/Migrations/20261103210630_SlotSuggestions.Designer.cs: Generated file
What changed in this PR
Adds the invitee-suggestion workflow from #38 across the scheduling service, MCP tools, and web UI. Invitees can suggest alternative times; organizers receive an email and can add those times to the poll or dismiss them.
Changes:
- Adds persisted suggestions, participant-specific visibility, limits, and organizer decisions.
- Connects suggestions to voting and organizer pages, MCP tools, and plain-text/HTML notifications.
- Adds workflow tests and documents the behavior.
| File | Description |
|---|---|
| tests/Scheduler.Web.Tests/VotingPageTests.cs | Tests submitting suggestions through the voting page. |
| tests/Scheduler.Web.Tests/SchedulerApp.cs | Supports posting a specific named form. |
| tests/Scheduler.Web.Tests/OrganizerPageTests.cs | Tests organizer add and dismiss actions. |
| tests/Scheduler.Data.Tests/VotingTests.cs | Updates proposal calls for suggestion IDs. |
| tests/Scheduler.Data.Tests/SuggestionTests.cs | Covers suggestion permissions, limits, decisions, notifications, and purge. |
| tests/Scheduler.Data.Tests/SchedulingJobsTests.cs | Updates proposal calls for the extended API. |
| tests/Scheduler.Data.Tests/OrganizerTests.cs | Updates organizer tests for suggestion IDs. |
| tests/Scheduler.Data.Tests/OrganizerLimitTests.cs | Adapts email-limit tests to the extended API. |
| tests/Scheduler.Core.Tests/EmailComposerTests.cs | Tests suggested-time email wording and time zones. |
| src/Scheduler.Web/wwwroot/app.js | Defaults suggestion inputs to the viewer’s zone. |
| src/Scheduler.Web/Mcp/SchedulingTools.cs | Exposes suggestion and dismissal tools; extends proposals. |
| src/Scheduler.Web/Mcp/SchedulingPrompts.cs | Adds suggestions to the participant workflow. |
| src/Scheduler.Web/Mcp/SchedulerMcpOptions.cs | Explains suggestion handling to agents. |
| src/Scheduler.Web/Email/Templates/EventEmail.razor | Renders suggested times in HTML emails. |
| src/Scheduler.Web/Email/HtmlEmailComposer.cs | Composes organizer suggestion notifications. |
| src/Scheduler.Web/Components/Pages/Vote.razor | Adds suggestion submission and status display. |
| src/Scheduler.Web/Components/Pages/Events.razor | Displays pending suggestion counts. |
| src/Scheduler.Web/Components/Pages/EventDetails.razor | Adds organizer controls for suggested times. |
| src/Scheduler.Data/SchedulingService.cs | Implements suggesting, dismissing, adopting, and visibility. |
| src/Scheduler.Data/SchedulingJobs.cs | Recomputes pending suggestions after time-zone updates. |
| src/Scheduler.Data/SchedulerDbContext.cs | Maps suggestion rows, indexes, and relationships. |
| src/Scheduler.Data/Migrations/SchedulerDbContextModelSnapshot.cs | Records the updated persistence model. |
| src/Scheduler.Data/Migrations/20261103210630_SlotSuggestions.Designer.cs | Defines the migration’s target model. |
| src/Scheduler.Data/Migrations/20261103210630_SlotSuggestions.cs | Creates the suggestions table and indexes. |
| src/Scheduler.Core/Services/ISchedulingService.cs | Defines suggestion operations and extended proposals. |
| src/Scheduler.Core/Services/Contracts.cs | Adds suggestion views and pending counts. |
| src/Scheduler.Core/Model/SlotSuggestion.cs | Defines the persisted suggestion entity. |
| src/Scheduler.Core/Model/SchedulingEvent.cs | Adds the event’s suggestion collection. |
| src/Scheduler.Core/Model/Enums.cs | Defines suggestion decision states. |
| src/Scheduler.Core/FieldLimits.cs | Adds the pending-suggestion limit. |
| src/Scheduler.Core/Email/PlainTextEmailComposer.cs | Adds suggestion notification text and shared wording. |
| src/Scheduler.Core/Email/IEmailComposer.cs | Adds the suggestion notification contract. |
| docs/design.md | Documents the workflow and its system integration. |
Review effort: Balanced
- Email subjects are cut to the outbox's 256 characters. A 100-character name and a 120-character title could overflow it and fail the whole change that queued the email; this was also true of the invitation and "can't make any time" subjects. - One person's suggest calls run one at a time, under a lock on their participant rows (not the event's, so the version doesn't move), so a double submit can't save duplicates, pass the waiting limit, or email twice. - Adding a suggestion builds the slot from its stored local time and zone, resolved leniently like the tzdb job (new SlotTimeResolver.ResolveStored, which the job now uses too). It keeps seconds, and a time new rules skip moves forward instead of being refused. - A suggested time already in the round (the organizer's own, or the same moment from two people) is proposed once, and every matching suggestion is marked added, so "Add all" no longer fails. - The voting page keeps showing a person's suggestions and what the organizer decided after voting closes. Also updates a test from #37 for the new ProposeMoreSlotsAsync parameter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZSHCijStZzTcMJSBYoY6t
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Closes #38.
When none of the proposed times work, someone invited can suggest others. The organizer gets an email and decides whether to add each time to the poll or dismiss it.
What changes
suggest_slotsMCP tool, and a "None of these work?" form on the voting page.propose_more_slotstakes a newsuggestionIdsparameter, andslotsis now optional. On the event page this is "Add to the poll" / "Add all".SlotTimeResolver.ResolveStored, which the job now uses too).dismiss_suggestionstool, and a "Dismiss" button on the event page./eventsdashboard shows how many are waiting. A participant sees only their own suggestions, with their status.SlotSuggestionentity and theSlotSuggestionsmigration. Suggestions are their own rows, so, like votes, they don't change the event's version. They are deleted with their event.handle_scheduling_requestsprompt now cover suggestions.docs/design.md, plus updates to the data model, tools, email, web UI, jobs and audit sections.Choices worth a look
Testing
dotnet test Scheduler.slnx: Core 124, Data 170 and Web 93 tests pass, after mergingmain.New tests:
SuggestionTests: suggesting, visibility, retries, concurrent requests, limits, adding (including duplicate instants, seconds and times the time-zone rules now skip), dismissing, reopening an expired event, purge.SchedulerApp.Browser.SubmitFormAsynccan now post a specific form, because the voting page has two.🤖 Generated with Claude Code
https://claude.ai/code/session_01NZSHCijStZzTcMJSBYoY6t