Skip to content

Save a time left blank on the voting page as no - #46

Merged
rockfordlhotka merged 3 commits into
mainfrom
claude/pensive-darwin-g89d94
Nov 4, 2026
Merged

rockfordlhotka merged 3 commits into
mainfrom
claude/pensive-darwin-g89d94

Conversation

@rockfordlhotka

Copy link
Copy Markdown
Member

Closes #43.

People often marked the one time that worked and left the rest blank, meaning "not those". The blanks stayed pending, which held up "everyone has responded" and made the ranking less clear. Now any time left blank on the voting page is saved as No.

What changed

  • ISchedulingService.VoteAsync takes unansweredAsNo, the slots a form showed. Each one that isn't in votes and that the voter hasn't answered yet is saved as no. The rule lives in the service, per the project conventions.
    • An answer already saved (for example by the voter's agent after the page loaded) is kept.
    • A time the organizer adds after the page loaded wasn't on the form, so it stays unanswered.
    • A time withdrawn in the meantime is ignored.
    • A notice says how many blanks became no, and the vote.cast audit records the count (blankAsNo).
  • Voting page (Vote.razor):
    • Adds a hidden shown input for each time and passes those IDs to the service.
    • The hint now says "A time you leave blank is saved as No."
    • The success notice includes the count.
    • Saving with nothing chosen at all is still refused.
  • vote MCP tool: behavior is unchanged. An agent may update a single slot, so a slot it leaves out stays unanswered. The description now asks the agent to answer every slot.
  • Not changed: "No" isn't pre-checked on the radio buttons. A pre-checked "No" would look like an answer the voter never gave, and on a later visit it would hide which new times they haven't seen.
  • Knock-on effects: blanks saved as no count as answers, so "everyone has responded" can now fire. The "can't make any time" email goes out when the voter's one answer is No.
  • docs/design.md: updated the voting rules, the vote tool row, the voting page row and the audit description.

Tests

  • New Scheduler.Data.Tests cases:
    • blanks are saved as no, with the notice, responded status and audit count;
    • an answer saved since the page loaded is kept;
    • times added, withdrawn or unknown since the page loaded are handled correctly;
    • a No plus blanks sends "can't make any time";
    • an MCP-style vote that leaves slots out still leaves them unanswered.
  • Updated VotingPageTests, where the page now saves blanks as no.
  • dotnet test Scheduler.slnx: 124 Core, 175 Data and 93 Web tests, all passing.

Generated by Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZSHCijStZzTcMJSBYoY6t
People often marked the one time that worked and left the rest blank,
meaning "not those"; the blanks stayed pending and held up "everyone has
responded" and the ranking. The voting page now sends the slots it showed,
and VoteAsync (unansweredAsNo) records no for each one the voter hasn't
answered. An answer already saved is kept, a time added after the page
loaded stays unanswered, and a withdrawn one is ignored. The success notice
says how many blanks became no, and the audit records the count.

The vote tool is unchanged (an agent may update a single slot), but its
description now asks the agent to answer every slot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZSHCijStZzTcMJSBYoY6t

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A concurrent vote save can trigger a duplicate-key insert and an unhandled DbUpdateException, rolling back the entire form submission.

1 open issue
What changed in this PR

Addresses #43 by saving unanswered times shown on the voting page as No, helping polls reach complete responses while preserving partial updates through the MCP tool.

Changes:

  • Adds service-level blank-to-No handling, success notices, and audit counts.
  • Passes displayed slot IDs from the voting form while leaving MCP voting behavior unchanged.
  • Updates tests and design documentation, and bumps the version to 1.0.10.
File Description
tests/​Scheduler.Web.Tests/​VotingPageTests.cs Updates page and receipt expectations for blank answers.
tests/​Scheduler.Web.Tests/​OrganizerPageTests.cs Adapts the voting helper to the new parameter.
tests/​Scheduler.Data.Tests/​VotingTests.cs Covers blank conversion, saved answers, slot changes, and notifications.
tests/​Scheduler.Data.Tests/​Harness.cs Keeps test-helper votes as partial updates.
src/​Scheduler.Web/​Mcp/​SchedulingTools.cs Preserves partial voting and clarifies tool guidance.
src/​Scheduler.Web/​Components/​Pages/​Vote.razor Submits displayed slot IDs and explains blank handling.
src/​Scheduler.Data/​SchedulingService.cs Implements implicit No answers, notices, and auditing.
src/​Scheduler.Core/​Services/​ISchedulingService.cs Defines and documents the new voting parameter.
docs/​design.md Documents page-specific voting behavior and audit details.
Directory.Build.props Bumps the version to 1.0.10.

Review effort: Balanced

Comment thread src/Scheduler.Data/SchedulingService.cs Resolved
A double submit of the voting page, or the voter's agent voting while
the page saves, could both find a time unanswered and insert the same
vote, failing the second save on the votes primary key. Saving blanks as
no made this more likely. VoteAsync now locks the caller's participant
rows (as SuggestSlotsAsync already did, now a shared helper) and reads the
event again under the lock before deciding what to insert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZSHCijStZzTcMJSBYoY6t
@rockfordlhotka
rockfordlhotka merged commit d669d32 into main Nov 4, 2026
4 checks passed
@rockfordlhotka
rockfordlhotka deleted the claude/pensive-darwin-g89d94 branch November 4, 2026 01:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Warn on incomplete votes

3 participants