Scheduling software

TimeMeld

Fair Meetings, Every Time

TimeMeld is a lightweight scheduling assistant that eliminates timezone friction for product managers, engineers, and ops leaders at remote‑first startups by proposing timezone‑weighted, ergonomic meeting windows, automating calendar invites, and displaying a shared equity scoreboard that rotates meeting ownership—cutting scheduling time, preventing repeated inconvenient slots, and improving attendance.

Subscribe to get amazing product ideas like this one delivered daily to your inbox!

TimeMeld

Product Details

Explore this AI-generated product idea in detail. Each aspect has been thoughtfully created to inspire your next venture.

Vision & Mission

Vision
Empower global remote teams to schedule equitably so every member's time is respected and meetings drive impact.
Long Term Goal
Within 3 years, eliminate 1 million hours of scheduling friction annually for 5,000 remote teams and reduce repeated inconvenient meetings per person by 40%
Impact
For product managers, engineers, and ops at remote-first startups, TimeMeld cuts scheduling time by up to 60%, reduces repeated inconvenient meetings per person by 40%, and raises meeting attendance 10–20% within three months by proposing timezone‑fair windows and rotating meeting ownership.

Problem & Solution

Problem Statement
Product managers, engineers, and ops at remote-first startups endure repeated inconvenient meetings across time zones because calendars ignore fairness; existing tools force manual timezone math, fail to balance burden, and let the same people lose sleep.
Solution Overview
TimeMeld computes timezone-weighted inconvenience scores to propose fair, ergonomic meeting windows and shows a shared equity scoreboard that rotates meeting ownership—eliminating timezone math and preventing the same teammates from repeatedly taking inconvenient slots.

Details & Audience

Description
TimeMeld is a lightweight scheduling assistant that removes timezone friction by proposing fair, ergonomic meeting windows and automating calendar invites. It serves product managers, engineers, and ops leaders at remote-first startups. TimeMeld cuts scheduling time and reduces repeated inconvenient meetings by suggesting optimal slots. Its shared equity scoreboard transparently scores inconvenience and rotates meeting ownership to balance burden across locations.
Target Audience
Product managers (25–45) at remote-first startups seeking fair schedules and prioritizing async workflows.
Inspiration
At 3 a.m. a bleary-eyed product manager in Berlin answered a Slack ping for a recurring all‑hands scheduled for San Francisco time. The same engineer—again—had sacrificed sleep to attend. While sketching timezone offsets and inconvenience scores in a messy spreadsheet, I realized a simple algorithm could rotate burden and propose fair windows. That sketch became TimeMeld: automatic, humane scheduling that protects teammates' nights.

User Personas

Detailed profiles of the target users who would benefit most from this product.

I

Interview Orchestrator Ivy

- Senior Recruiting Coordinator at 120-person remote SaaS; owns panel scheduling globally. - Based in Austin (CST), collaborates across AMER/EMEA/APAC. - 6 years recruiting ops; SHRM-CP; Greenhouse/Lever power user. - Compensation $95k base + bonus; budget owner for tooling.

Background

Cut her teeth coordinating campus tours, then scaled to global panels at a unicorn. After burning weeks on timezone math and no-shows, she championed automation to protect candidate experience.

Needs & Pain Points

Needs

1) Auto-propose candidate-friendly windows across regions. 2) Rotate interviewers; show clear ownership history. 3) Push invites and updates from ATS.

Pain Points

1) Timezone math for panels wastes hours. 2) Repeat late slots hurt interviewer morale. 3) Double entry between ATS and calendar.

Psychographics

- Obsessed with candidate experience and fairness. - Seeks calm, predictable scheduling workflows. - Data-driven, tracks time-to-hire relentlessly, transparently. - Values tools that just disappear.

Channels

1) Slack DMs 2) Greenhouse tasks 3) Google Calendar alerts 4) Gmail threads 5) LinkedIn messages

P

Postmortem Marshal Max

- Incident Response Manager at 200-person infra startup; coordinates postmortems. - Based in Berlin (CET); spans AMER/EMEA/APAC timezones nightly. - 8 years SRE/DevOps; PagerDuty, Jira, Google Workspace expert. - Compensation €115k; on-call stipend; tool procurement influence.

Background

After firefights at a CDN, he formalized retros but lost hours scheduling across rotations. A failed 3 a.m. postmortem pushed him to standardize humane, rotating slots.

Needs & Pain Points

Needs

1) Propose postmortem windows within 48 hours, fair. 2) Rotate facilitator and scribe automatically. 3) Sync attendees from PagerDuty/Jira incidents.

Pain Points

1) APAC shoulders repeated late-night reviews. 2) Manual invites delay learning after incidents. 3) Tracking attendance is tedious.

Psychographics

- Champion of blameless, punctual collaboration. - Fairness across timezones over convenience. - Prefers automation during high-pressure periods. - Measures outcomes, not activity obsessively.

Channels

1) Slack incident channel 2) PagerDuty incidents 3) Jira tickets 4) Google Calendar alerts 5) Zoom meetings

S

Sprint Workshop Wrangler Sanaa

- Design Operations Lead at 80-person product startup; runs sprints/rituals. - Toronto-based (ET); teams in London and Bangalore. - 7 years design facilitation; Figma, Miro, Notion, Zoom native. - Compensation $120k; influences tooling and process.

Background

Facilitated week-long sprints that fizzled from 10 p.m. starts. After learning to defend maker hours, she rebuilt rituals around humane windows and predictable cadence.

Needs & Pain Points

Needs

1) Plan multi-day windows that respect maker hours. 2) Automate recurring invites and prep tasks. 3) Rotate critique leadership across regions.

Pain Points

1) Late-night sessions drain creative energy. 2) Manual reschedules derail multi-day plans. 3) Same team leads every critique.

Psychographics

- Protects flow; hates context switching. - Inclusive by default; invites diverse timezones. - Prioritizes clarity over ceremony always. - Loves lightweight, reliable tools most.

Channels

1) Slack #design 2) Google Calendar notifications 3) Notion wiki 4) Figma comments 5) Zoom meetings

E

Enablement Cadence Coach Casey

- Revenue Enablement Manager at 150-person SaaS; owns training calendar. - Chicago-based (CT), supports global AEs/CSMs. - 9 years enablement; Salesforce, Gong, Zoom, Google Workspace. - Compensation $130k + bonus; adoption KPIs.

Background

After APAC attendance cratered from midnight trainings, Casey rebuilt cadences with rotating times and data-driven follow-ups to lift completion rates.

Needs & Pain Points

Needs

1) Generate staggered regional training slots automatically. 2) Track attendance and completion per cohort. 3) Template recurring enablement cadences.

Pain Points

1) APAC skips midnight trainings. 2) Manual invites miss last-minute hires. 3) Region fatigue from fixed times.

Psychographics

- Participation over perfection; learning by doing. - Data-obsessed; chases completion rates relentlessly. - Fairness beats convenience culture everywhere.

Channels

1) Slack #sales 2) Google Calendar invites 3) Salesforce events 4) Zoom webinars 5) Gong libraries

C

Community Demo Director Diego

- Developer Relations Manager at OSS startup; community 20k members. - Mexico City-based (CT); community in EMEA/APAC/AMER. - 6 years DevRel; Discord, GitHub, YouTube, X, Zoom. - Compensation $110k; owns event metrics.

Background

After repeated AMER-centric events alienated APAC, he instituted rotating demo times and tighter workflows to lift live participation.

Needs & Pain Points

Needs

1) Rotate demo times across timezones transparently. 2) Send clean external invites with ICS. 3) Remind registrants contextually to reduce no-shows.

Pain Points

1) APAC attendance lags due to late times. 2) External invites break or hit spam. 3) Manual reminders don’t scale.

Psychographics

- Community-first; inclusivity over vanity metrics. - Transparent scheduling; communicates tradeoffs openly. - Prefers simple, public-friendly flows always.

Channels

1) Discord announcements 2) X posts 3) Google Calendar public 4) YouTube Live 5) Slack #devrel

B

Board Briefing Booker Isha

- Chief of Staff at 40-person startup; coordinates board/advisor meetings. - San Francisco-based (PT); investors across London, Tel Aviv, Singapore. - 10 years EA/ops; Google Workspace, Zoom, DocSend, Superhuman. - Compensation $170k; gatekeeper to CEO’s calendar.

Background

Former executive assistant turned operator, scarred by midnight board preps. She now enforces equitable meeting ownership and insists on tools that respect everyone’s time.

Needs & Pain Points

Needs

1) Find tight overlaps among conflicting C-suite calendars. 2) Rotate ownership and note-taking duties. 3) One-click reschedules that retain context.

Pain Points

1) Investors’ last-minute changes cascade chaos. 2) Same exec absorbs early/late burdens. 3) Email threads hide final decisions.

Psychographics

- Polish and reliability over flash. - Protects executive energy ruthlessly daily. - Values transparent fairness in scheduling.

Channels

1) Gmail threads 2) Google Calendar invites 3) Slack executive-channel 4) WhatsApp confirmations 5) Zoom links

Product Features

Key capabilities that make this product valuable to its target users.

LinkLock

Recipient‑bound magic links that verify the invited email at join time with a lightweight OTP. If a link is forwarded, the recipient can request access in one click for organizer approval—preventing gate‑crashers without forcing account creation. Hosts get cleaner attendance, guests get instant, secure entry.

Requirements

Recipient-Bound Magic Link Issuance
"As an invited guest, I want a secure, personal link that just works without creating an account so that I can join quickly and confidently."
Description

Generate a signed, recipient-specific magic link for each invitee that encodes meeting ID, recipient email hash, expiration, and one-time claim token. Embed the link into the TimeMeld calendar invite and reminder emails. Links must be usable without account creation and scoped to the intended email address only. Implement HMAC signing, short TTLs, and revocation support. On issuance, update the meeting’s attendee roster and surface link state in the organizer view for transparency and troubleshooting.

Acceptance Criteria
Issuance and Email Embedding
Given a scheduled meeting with multiple invitees and the organizer sends invitations When recipient-bound magic links are generated Then the system creates a unique, signed magic link per invitee encoding meetingId, recipientEmailHash, expiration, and oneTimeClaimToken And the URL contains no raw email address or other PII And the link is embedded in the invite email body and the attached calendar (ICS) description for that invitee And reminder emails for that meeting include the same recipient-specific link And the attendee roster is updated with an entry per invitee marked "Link Issued" including linkId and expiration timestamp
HMAC Signature and Payload Integrity
Given a generated magic link token Then its signature verifies using the server-managed HMAC secret and the payload exactly matches the signed claims When any claim (meetingId, recipientEmailHash, expiration, oneTimeClaimToken) is modified Then signature verification fails and access is denied When the signature is missing or malformed Then access is denied and no OTP is sent
Email Binding and OTP Verification Without Account Creation
Given a recipient opens their magic link Then the system prompts for a one-time passcode sent to the invited email address and does not require account creation or password setup When the recipient enters the correct OTP within its validity window Then the recipient is authenticated as the invited email and may join the meeting When the visitor cannot receive the OTP at the invited email or attempts to supply a different email Then claiming is denied and the link remains unclaimed
One-Time Claim and Reuse Prevention
Given a magic link has not been claimed When the invited recipient completes OTP verification Then the oneTimeClaimToken is marked claimed and meeting access is granted When the same link is used again after being claimed Then access is denied and no new OTP is sent
Expiration TTL Enforcement and Revocation
Given a magic link with an expiration timestamp in the future Then it can be claimed and used until that timestamp is reached When the current time exceeds the expiration timestamp Then access is denied and no OTP is sent When the organizer revokes an invitee’s link before expiration Then subsequent access attempts are denied, and the attendee roster state changes to "Revoked" with a revocation timestamp
Organizer View Link State Visibility
Given the organizer opens the meeting’s attendee panel Then each invitee shows link state as one of "Issued", "Claimed", "Revoked", or "Expired" along with the expiration timestamp When a link is issued, claimed, revoked, or expires Then the state displayed to the organizer reflects the change and is visible upon page refresh And the link URL shown to the organizer does not expose the recipient’s raw email address
Lightweight OTP Email Verification
"As an invitee, I want to confirm my identity with a quick code sent to my email so that I can enter securely without a full signup."
Description

Upon link click, require a brief OTP challenge sent to the invited email to confirm identity. Support 6-digit codes, 5-minute TTL, limited attempts, resend with rate limiting, and auto-fill via magic deep-link where supported. Provide an accessible UI with clear error states and localization hooks. Integrate with the existing email provider, log verification outcomes, and gracefully route mismatches to the forwarded-link request flow. Store only minimal necessary data and comply with privacy policies.

Acceptance Criteria
OTP Generation, Delivery, and 5‑Minute Validity
Given an invitee clicks a valid LinkLock meeting link When the OTP challenge screen loads Then the system issues a single-use 6-digit numeric OTP bound to the invitee email and session And sends the OTP via the existing email provider within 60 seconds And the OTP expires 5 minutes after issuance And only the most recently issued OTP for the active session is accepted And expired or superseded OTPs return the error message "Code expired — request a new code"
Limited Verification Attempts and Lockout
Given an active OTP is issued When the user submits an incorrect code Then the attempt count increments And after 5 incorrect attempts within the OTP validity window, the challenge is locked for 10 minutes or until a new OTP is issued And further submissions during lockout are blocked with the error "Too many attempts — try again later" And a lockout event is logged with invite ID and timestamp (no PII)
Resend OTP with Rate Limiting and Anti‑Abuse Controls
Given the OTP challenge is displayed When the user taps "Resend code" Then the system enforces a 30-second cooldown before the button re-enables And no more than 3 resends are allowed within 15 minutes per invite And each resend generates a new OTP and invalidates the previous OTP And email send failures surface the message "We couldn't send the code — please try again" without revealing account status And a resend event is logged with outcome
Deep‑Link Auto‑Fill and Submission
Given the user opens the verification deep-link from the OTP email on a supported device When the app or browser receives the deep-link Then the 6-digit code auto-fills and submits the verification form And on failure to auto-submit, the code remains populated for manual submit And if the deep-link references a different invite than the current session, the code is rejected and the user is prompted to refresh the session
Accessible, Localized OTP UI and Clear Error States
Rule: The OTP screen meets WCAG 2.1 AA (keyboard-only navigation, visible focus, 4.5:1 contrast, screen reader labels) Rule: Inline error messages (invalid code, expired code, too many attempts, send failure) are text, mapped to localization keys, and announced via ARIA live regions Rule: The 6-digit inputs accept paste, restrict to numeric, and expose a polite countdown timer with accessible announcements Rule: On successful verification, focus moves to a confirmation region with a success message that is screen-reader readable
Forwarded Link Mismatch and Request‑Access Routing
Given a verification attempt fails due to invite mismatch or the user indicates they cannot access the invited inbox When the user selects "Request access" Then a one-click request is sent to the organizer with meeting ID, invite ID, and requester email (entered in form or taken from session) And the user sees confirmation "Access request sent" And no account creation is required to submit the request And the original invite remains unverified until organizer approval
Event Logging, Data Minimization, and Privacy Compliance
Rule: The system logs otp_issued, email_send_success/failure, otp_verified_success, otp_invalid, otp_expired, attempts_limit_reached, resend_requested, resend_rate_limited, deep_link_used, forwarded_request_initiated Rule: Logs include only non-PII identifiers (invite_id, meeting_id, session_id), timestamps, and outcome; full emails and OTP values are never logged Rule: OTPs are stored as salted hashes with TTL = 5 minutes and are purged on verification or expiry Rule: Audit logs are retained for 30 days in accordance with privacy policy Rule: CI checks include PII scanning for log statements in this module
Forwarded Link Access Request Flow
"As someone who received a forwarded invite, I want to request access in one click so that the host can approve me without friction."
Description

Detect forwarded link scenarios (email mismatch or undeliverable OTP) and present a one-click Request Access form capturing name and email. Submit requests to the meeting organizer with context (meeting, original recipient, device, timestamp). Provide a clear waiting state for the requester and automatic updates on approval/denial. On approval, issue a new recipient-bound link and update the attendee roster; on denial, present organizer-provided guidance. Ensure minimal friction while preventing unauthorized entry.

Acceptance Criteria
Email Mismatch Triggers Access Request
Given a visitor opens a recipient-bound magic link for invited_email And enters a different email (requester_email ≠ invited_email) to request OTP When the mismatch is detected before sending OTP Then the OTP is not sent And the Request Access form is displayed with fields: Name (required) and Email prefilled with requester_email (required) And there is a single primary CTA labeled "Request access" And no account creation or password setup is required And the UI does not display invited_email anywhere
Undeliverable OTP Triggers Access Request
Given a visitor opens a recipient-bound magic link and enters an email When the OTP email hard-bounces or is undeliverable within 30 seconds Then the Request Access form is displayed with fields: Name (required) and Email prefilled (required) And a non-blocking explanation is shown: "We couldn't reach that email" And no further OTP attempts are sent to that email for this link session
Access Request Submission and Organizer Notification
Given the Request Access form is displayed When the visitor submits valid Name and Email Then a request record is created including meeting_id, original_invited_email, requester_name, requester_email, device_info (OS, browser), timezone, IP_hash, and UTC timestamp And duplicate submissions from the same requester_email for the same meeting within 60 seconds are de-duplicated (single request stored) And the meeting organizer receives an actionable notification (in-app and email) within 60 seconds containing meeting details, original_invited_email (masked), requester_name/email, device_info, and approve/deny controls
Requester Waiting State and Live Decision Updates
Given a request has been submitted When the requester remains on the waiting screen Then the screen clearly indicates "Awaiting organizer approval" with the submitted email And the client polls or receives push updates at least every 10 seconds And upon organizer approval or denial, the screen updates within 5 seconds to the corresponding state without manual refresh
Approval Flow Issues New Link and Updates Roster
Given the organizer approves a request Then a new magic link is generated bound to requester_email with a 30-minute validity window for first use and standard expiry thereafter And the link is emailed to requester_email immediately and surfaced on the waiting screen as a Continue button And the meeting attendee roster is updated to include requester_email with status "Approved via access request" And an audit log entry records approver_id, requester_email, timestamp, device_info, and link_id And the original magic link remains valid only for invited_email and cannot be used by requester_email
Denial Flow Presents Organizer Guidance
Given the organizer denies a request with optional guidance text Then the requester sees a denial state with the organizer-provided guidance (if any) and a privacy-safe explanation And an email notification is sent to requester_email within 60 seconds with the same guidance And no meeting access or new link is issued And an audit log entry records denier_id, requester_email, timestamp, and reason code/text
Privacy and Abuse Safeguards
Given any forwarded-link access request scenario Then the UI never exposes the original invited_email or full name to the requester And rate-limits prevent more than 5 access requests per requester_email per meeting per hour, returning a friendly error on excess And all organizer notifications mask original_invited_email (e.g., a****@example.com) And stored device and network identifiers are hashed or truncated per policy
Host Approval Console and Notifications
"As a meeting organizer, I want an approval queue with instant notifications so that I can control who joins and keep attendance clean."
Description

Provide organizers with a dedicated console to review, approve, or deny access requests. Include request details, quick actions, SLA indicators, and bulk operations. Send real-time notifications via email and Slack on new requests and decisions. On approval, automatically generate and deliver a fresh recipient-bound link, update calendar invite participants when applicable, and sync attendance state with TimeMeld’s dashboard. Preserve an audit record of all actions for compliance and support.

Acceptance Criteria
Triage Pending Access Requests with SLA Indicators
Given I am a host with events receiving access requests When I open the Host Approval Console Then I see a paginated list of requests with columns: Requester Email, Event Title, Event Time, Timezone, Reason (if provided), Source (Forwarded/Direct), Request Age, Current Status, SLA Remaining And each row provides quick actions: Approve, Deny, View Details And SLA Remaining displays color codes: green (>30m), amber (10–30m), red (<10m) and updates at least every 60s without full page refresh And I can filter by Status (Pending/Approved/Denied/Expired), Event, and SLA band (green/amber/red), and sort by Request Age and SLA Remaining And the list view loads within 2s for up to 100 pending requests And selecting View Details reveals the full request data including invitee email, forwarder email (if applicable), and request note (if provided)
Approve Request Generates Recipient-Bound Link and Updates Calendar & Dashboard
Given a pending access request is selected When I click Approve Then the system generates a new recipient-bound magic link tied to the requester’s email and sends it via email within 60s And the request status changes to Approved and is reflected on the console within 5s And if the event has calendar sync enabled, the requester is added as an attendee on the calendar event within 60s; otherwise, no calendar change is attempted And the attendee’s state is updated in TimeMeld’s dashboard to Approved within 15s And the approval action is idempotent; repeated Approve actions do not create additional links or duplicate calendar attendees
Deny Request with Reason and No-Link Guarantee
Given a pending access request is selected When I click Deny and optionally enter a reason Then the request status changes to Denied and is reflected within 5s And no magic link is generated or sent And the requester receives a denial email containing the reason (if provided) within 60s And subsequent attempts by the requester to use previously forwarded links are blocked with a message to request access And the denial action is idempotent
Bulk Approve/Deny with Per-Item Outcomes
Given I multiselect between 2 and 100 pending requests When I choose Approve or Deny and confirm Then the system executes the action per request and displays per-item success/failure and overall progress And the bulk operation completes within 10s for 100 requests under normal load And notifications, link generation, calendar updates, and dashboard sync occur per item as in single-item flows And partial failures do not block successful items; failed items are retriable individually
Real-Time Email and Slack Notifications for New Requests and Decisions
Given I am an organizer subscribed to notifications for an event When a new access request is submitted Then I receive a Slack message to the configured channel and an email including: requester email, event title/time, request reason (if any), request age, and a deep link to the console within 60s And when a request is approved or denied, the requester receives an email with the decision (and reason if denied) within 60s, and organizers receive a Slack update summarizing the decision And duplicate notifications for the same request are suppressed within a 5-minute window And notifications respect per-user preferences for Slack and email
Comprehensive Audit Trail for Requests and Actions
Given any lifecycle event occurs on an access request (create, approve, deny, bulk action, notification attempt, calendar sync, dashboard sync) When I view the audit log for that request Then I see an append-only timeline with entries containing: timestamp (UTC), actor (user id or system), action type, request id, event id, previous state, new state, reason (if any), notification channels attempted and outcomes, calendar sync result, dashboard sync result, and correlation id And audit entries are immutable and cannot be edited or deleted by end users And I can export the audit log for a selected time range to CSV, and it downloads within 30s for up to 10,000 entries
Resilience and Fallbacks for Notification and Calendar Failures
Given a transient failure occurs when sending Slack or email notifications When a request is created or a decision is made Then the system retries up to 3 times over 5 minutes with exponential backoff and logs each attempt in the audit trail And if Slack delivery fails after retries, an email notification is sent as a fallback (if enabled), and vice versa And if calendar attendee update fails, the approval remains recorded, the dashboard is updated, the host is alerted in-console with a retriable error banner, and a background retry is scheduled; no duplicate attendees are created upon eventual success And guests do not see internal errors; if their link delivery is delayed, they receive a clear message to check email again
Session Binding and Re-entry Window
"As an invitee, I want to rejoin from the same device without repeating verification so that I can recover from connection issues during the meeting."
Description

After successful OTP, bind the authenticated attendee to a device/session for the meeting window to allow seamless re-entry without repeated verification. Support configurable policies (single-device vs. multi-device), organizer-initiated revocation, and automatic expiry at meeting end plus grace period. Securely store session tokens, respect timezone-aware meeting windows, and handle edge cases like overlapping meetings or rescheduled times. Reflect active sessions in the organizer view for visibility.

Acceptance Criteria
Seamless Re-entry Within Meeting Window
Given an attendee completes OTP for a meeting, When the attendee reconnects from the same device/session during the meeting window, Then access is granted without re-verification. Given an attendee has an active bound session, When the attendee refreshes the page or reopens the join link during the window, Then the attendee bypasses OTP and is admitted. Given the meeting window has ended and the grace period has elapsed, When the attendee attempts re-entry, Then the session is invalid and OTP is required or access is denied according to policy. Given the grace period is configured (e.g., 15 minutes), When the attendee reconnects within the grace window after scheduled end, Then access is granted without re-verification.
Policy Enforcement: Single-device vs Multi-device
Given policy = single-device, When the same attendee attempts to start a second session on a different device/browser, Then the second session is blocked and the attendee is shown a one-click access request to the organizer. Given policy = single-device and the organizer approves a device switch, When the second device is admitted, Then the first device session is immediately revoked and cannot rejoin without re-approval. Given policy = multi-device with limit N, When the attendee starts sessions on up to N distinct devices, Then all N sessions are admitted; When a (N+1)th device attempts to join, Then it is blocked and may request access. Given policy changes from multi-device to single-device during the meeting, When more than one active session exists, Then only the most recent or organizer-selected session remains active and others are revoked with an inline notice.
Organizer-Initiated Session Revocation
Given an organizer opens the meeting’s attendee/session panel, When the organizer clicks Revoke on a specific attendee or device, Then the corresponding session token(s) become invalid within 5 seconds and the attendee is removed from the meeting. Given a revoked attendee attempts to rejoin during the meeting window, When they click the link again, Then they are shown a Request Access option and cannot re-enter without organizer approval or re-verification as configured. Given an organizer performs a bulk revoke (All sessions for attendee), When executed, Then all devices for that attendee are invalidated and reflected in the organizer view with status = Revoked. Given a revocation occurs, When viewing audit logs, Then an entry exists with timestamp, actor (organizer), target (attendee/device), and outcome (success/failure).
Expiry at Meeting End with Timezone Awareness and Grace Period
Given a meeting is scheduled from 10:00 to 11:00 in the organizer’s timezone, When an attendee in a different timezone joins and obtains a bound session, Then the session validity ends at 11:00 organizer timezone plus configured grace period regardless of attendee local time. Given the scheduled end time passes, When the grace period elapses, Then all active session tokens are server-invalidated and attendees must re-verify for any subsequent meetings. Given the grace period is set to 0, When the meeting end time occurs, Then sessions expire immediately at the scheduled end. Given a meeting is extended by the organizer to a later end time, When the extension is saved, Then existing active sessions inherit the new end time plus grace without requiring re-verification.
Overlapping and Rescheduled Meetings Handling
Given an attendee is invited to two overlapping meetings A and B, When the attendee has an active bound session for A, Then the session cannot be used to join B; a separate session must be created via OTP for B. Given a meeting is rescheduled (same meeting ID) to a new start/end time, When the change is saved, Then existing session validity windows update to the new times and continue to allow seamless re-entry. Given a meeting is duplicated or recreated with a new meeting ID, When the attendee uses the old session token, Then access is denied and the attendee is prompted to verify for the new meeting. Given overlapping meetings share the same attendee and device, When switching between A and B, Then session cookies/tokens remain scoped by meeting ID and do not leak across meetings.
Secure Session Token Storage and Rotation
Given a session is created after successful OTP, When the token is issued to the client, Then it is stored in an HttpOnly, Secure, SameSite=Lax cookie and is not accessible via JavaScript. Given the server persists session state, When storing token references, Then only a hashed (e.g., SHA-256/HMAC) token identifier is stored at rest; the raw token is never persisted. Given tokens are generated, When evaluating entropy, Then each token contains at least 128 bits of cryptographic randomness and includes an embedded or associated expiry no later than meeting end plus grace. Given key rotation occurs, When a signing/encryption key is rotated, Then newly minted tokens use the new key and existing tokens continue to validate until their natural expiry or are invalidated on rotation according to policy. Given a token is revoked or expired, When the client presents it, Then the server responds 401/440 and requires re-verification; the token cannot be refreshed beyond the meeting window.
Organizer View of Active Sessions
Given the organizer opens the meeting’s session dashboard, When viewing attendees, Then each attendee row shows count of active sessions, device type/browser, approximate location (country/region), last activity timestamp, and status (Active/Revoked/Expired). Given a session state changes (join, revoke, expire), When the organizer view is open, Then the list updates within 10 seconds to reflect the new state. Given the organizer selects an attendee/device in the dashboard, When clicking Revoke, Then the target session is terminated and the UI confirms success; the attendee is removed from the meeting. Given multiple active sessions for an attendee under multi-device policy, When the organizer selects Revoke All, Then all sessions for that attendee terminate and the counts update accordingly.
Audit Trails and Attendance Integrity
"As an organizer, I want clear audit logs and attendance reporting so that I can verify who joined and maintain compliance."
Description

Capture immutable event logs for link issuance, opens, OTP sends/verifications, access requests, approvals/denials, and session lifecycle. Surface anomalies (multiple attempts, mismatched domains, repeated denials) and provide export (CSV/API) for compliance. Integrate with TimeMeld’s attendance view to show verified participants, prevented gate-crashers, and reasons for denials. Apply data retention policies, redaction on request, and ensure PII minimization while enabling effective operational support.

Acceptance Criteria
End-to-End Immutable Audit Logging
- The system records an append-only event entry for each of: link_issued, link_opened, otp_sent, otp_verified, access_requested, access_approved, access_denied, session_started, session_ended. - Each entry includes: event_id (UUIDv4), event_type, occurred_at (UTC ISO-8601 ms), meeting_id, invite_id, actor_id (nullable), actor_email_hash (SHA-256 + salt), ip_anonymized, user_agent_hash, outcome (success|failure), attempt_number (where applicable). - OTP plaintext is never persisted in any log; only a salted, non-reversible hash may be stored for verification traceability. - Event writes are durable and queryable within 5 seconds of occurrence for 99% of events; 100% within 60 seconds. - Tamper-evidence: each entry contains prev_hash to form a hash chain; the verification endpoint returns chain_status=valid for unmodified logs. - Idempotency: submitting the same idempotency_key yields a single log entry; duplicates are rejected with 409 and not persisted.
Anomaly Detection and Surfacing
- Default thresholds: OTP attempts >5 within 10 minutes per invite -> OTP_RATE_LIMIT; opens from >3 countries within 24 hours -> GEO_SUSPICION; requester domain != invited domain -> DOMAIN_MISMATCH; >2 denials for the same requester within 24 hours -> REPEATED_DENIAL; >4 distinct device fingerprints within 24 hours -> DEVICE_ROTATION. - Anomalies are computed within 60 seconds of the triggering event and displayed on the meeting’s LinkLock panel with a badge and reason_code. - Each anomaly includes contributing event references and aggregate counts used for detection. - Hosts can acknowledge anomalies; acknowledged=true is persisted and included in API/CSV exports. - All anomalies are written to the audit log with anomaly=true and the appropriate reason_code.
Export via CSV and API
- CSV export supports filters: date_range (UTC), meeting_id, invite_id, event_type, anomaly_flag, reason_code; output includes a header row with deterministic column order and schema_version. - CSV export of up to 100,000 rows completes within 30 seconds; larger datasets stream with pagination and do not exceed memory limits. - API endpoint /v1/audit-events supports OAuth2, cursor-based pagination, rate limiting at 600 requests/min, and returns next_cursor when more data is available. - Timestamps are UTC ISO-8601 with milliseconds; CSV formatting follows RFC 4180 (proper escaping, quoting, and line breaks). - Exported record counts match the audit store for the same filter (0 record discrepancy in verification).
Attendance View Integration
- Attendance view displays for each attendee: verification_status (Verified|Unverified|Denied), join_method (LinkLock|Manual), verified_at (if applicable), and reason_code for Denied. - A “Prevented gate-crashers” section lists denied attempts with masked requester email, timestamp, and reason_code; the badge count equals the number of denials in the audit log for the meeting. - Clicking an attendee opens a side panel showing their audit trail filtered by invite_id. - Counts and statuses in the attendance view exactly match the audit log for the meeting (no tolerance). - If no audit records exist, the view renders a non-error empty state message: "No verification activity."
Data Retention and Legal Hold
- Workspace-level retention period is configurable between 30–730 days (default 180); events older than the period are purged daily at 02:00 UTC. - Applying a legal_hold to a meeting or invite prevents purge of associated records until the hold is removed. - Purge removes PII fields from aged records and sets redacted=true, preserving event_type, occurred_at, meeting_id, invite_id, and reason_code. - Purge and legal hold changes are themselves audit-logged with actor and timestamp. - A metrics endpoint exposes last_purge_time, records_purged, and errors; failures trigger an alert to on-call.
PII Minimization and Sensitive Data Handling
- Audit events store only: actor_email_hash (SHA-256 with workspace-specific salt), ip_anonymized (/24 IPv4, /48 IPv6), coarse_geo (country, region), user_agent_hash, device_fingerprint_hash; raw emails and full IPs are not stored in event rows. - OTP secrets are never logged; only a salted hash and a boolean outcome are recorded. - Access to any mapping service that can resolve email -> email_hash is limited to Support_Admin with break-glass approval; all lookups are audit-logged. - All audit data is encrypted at rest (AES-256) and in transit (TLS 1.2+); encryption keys are rotated at least every 90 days. - CI enforcement: automated tests fail the build if disallowed fields (e.g., raw_email, full_ip, otp_plaintext) are detected in event schemas or fixtures.
User-Initiated Redaction and Support Tooling
- Organizer or data subject can submit a redaction request via UI or /v1/redactions API specifying meeting_id and/or invite_id; the request is authenticated and audit-logged. - Upon workspace-admin approval, the system redacts PII fields for matching events within 24 hours, sets redacted=true, and records redacted_at and redaction_reason. - Redaction preserves non-PII fields necessary for compliance and analytics (event_type, occurred_at, reason_code) and breaks linkage to personal identifiers. - Support console enables authorized users to search by meeting_id, invite_id, or email_hash; view anomalies; and export scoped logs; every action is permission-checked and audit-logged. - A nightly verification job confirms all approved redactions are applied; any failures create an alert and are visible in the metrics endpoint.

Auto‑Localize

Detects a guest’s timezone and language to present the meeting date, time, and details in their locale—handling DST shifts, 12/24‑hour formats, and travel changes automatically. Eliminates confusion and missed calls caused by manual time conversions.

Requirements

Automatic Timezone Detection & Verification
"As a meeting guest, I want my timezone detected automatically so that invites and reminders show the correct local time without me converting it manually."
Description

Detect each guest’s timezone automatically using multiple signals (calendar metadata, email headers, browser Intl API, and privacy‑respecting IP geolocation as a last resort). Cross‑validate signals to compute a confidence score, cache per contact, and auto‑refresh until meeting start to capture changes. Persist detection results with timestamps and source for auditability. Expose a lightweight detection service used by scheduling flows, invite generation, and reminder systems across TimeMeld. Trigger re‑localization of invites and reminders on timezone change with minimal disruption, and surface a non‑blocking confirmation UI when confidence is low.

Acceptance Criteria
Multi‑Signal Timezone Detection with Confidence Scoring
Given calendar metadata and browser Intl API report the same IANA timezone When detection runs Then the resolved timezone equals that IANA ID and confidence >= 90 and sources include calendar and browser Given email headers and browser Intl API conflict and no calendar metadata exists When detection runs Then the resolved timezone matches the highest‑weighted signal, confidence is between 60 and 79, and conflicts are recorded per source Given only IP geolocation is available When detection runs Then the resolved timezone is derived from IP, confidence <= 50, and source is marked last_resort=true
Low‑Confidence Confirmation Prompt
Given a detected timezone with confidence < 60 When the guest opens the RSVP or scheduling page Then a non‑blocking confirmation prompt displays the suggested timezone with up to two alternatives and accepting sets confidence to 95, dismissing logs status=unconfirmed and allows the flow to continue Given the confirmation prompt is shown When the guest proceeds without acting Then the flow is not blocked and a silent recheck is scheduled within 10 minutes Given the guest explicitly confirms a timezone When subsequent detections find a conflict within 12 hours Then the confirmed value is not overridden without explicit user change
Auto‑Refresh Timezone Tracking Pre‑Meeting
Given a meeting is scheduled more than 24 hours away When initial detection completes Then auto‑refresh is scheduled at T‑24h, T‑6h, T‑1h, and T‑10m and on calendar/device change webhooks Given a refresh detects a different IANA timezone or UTC offset with confidence >= 80 When the change is recorded Then the cached timezone is updated immediately and change_detected=true is set Given no new signals are available at a refresh time When the cached value was last seen within 7 days Then reuse the cached timezone and decay confidence by 0 if <=7 days else by 10 points per additional week
Minimal‑Disruption Re‑localization on Timezone Change
Given a confirmed timezone change for a guest and meeting UTC time is unchanged When local wall time differs for that guest Then regenerate localized invite and reminders for that guest only, send at most one updated invite per guest per 12 hours, and within 30 minutes of start update reminders only without resending the invite Given multiple timezone changes occur within 3 hours When re‑localization would trigger multiple updates Then coalesce updates into a single message reflecting the latest timezone Given a timezone change with confidence between 60 and 79 When preparing reminders Then include a one‑click "Confirm your timezone" link in the reminder content
Persisted Detection Records with Audit Trail
Given any detection run completes When persisting results Then store contact_id, meeting_id (nullable), resolved_tz (IANA), confidence (0‑100), sources_used with per‑source tz and timestamps, decided_at, evaluator_version, last_resort_ip_used (bool) Given a persisted detection record exists When queried via the audit API Then it is returned within 1 second p95 and is immutable; corrections create a new version linked by previous_version_id Given an org admin exports meeting detection results When the export completes Then the CSV contains one row per guest with first_detected_at, last_detected_at, changes_count, and last_change_reason
Detection Service Integration in Scheduling, Invites, and Reminders
Given the scheduling UI and a participant email is entered When the UI calls the detection service Then a response is returned within 300 ms p95 containing timezone, confidence, sources[], cache_age_ms; on failure a cached value is returned with stale=true Given invite generation runs for recipients When localization is performed Then the detection service is called for each unique contact and the ICS uses the returned timezone; transient failures retry up to 3 times with exponential backoff Given the reminder system builds messages When a cached detection is <= 6 hours old Then it is reused; otherwise a refresh is triggered and the last known value is used if the refresh exceeds 500 ms
Privacy‑Respecting IP Fallback and Opt‑Out
Given no non‑IP signals are available or signals conflict with confidence < 60 When IP fallback is enabled Then IP is mapped to timezone at city level or coarser, raw IP is not stored beyond 24 hours, only derived timezone and country are persisted, and last_resort_ip_used=true is recorded Given a contact or organization has opted out of IP lookup When detection runs Then IP geolocation is not invoked and confidence reflects available signals only Given guests are located in GDPR/CCPA regions When IP data is processed Then lawful basis is recorded and a link to the privacy notice is included in the confirmation prompt
Locale‑Aware Date/Time & Language Formatting
"As an attendee, I want meeting details presented in my language and familiar date/time format so that I can instantly understand when the meeting occurs."
Description

Render meeting dates, times, and contextual text using the guest’s locale, including 12/24‑hour preference, local date order, week start day, numerals, and timezone display names/abbreviations. Use CLDR/ICU for formatting and pluralization, and provide translated templates for system messages (subject lines, RSVP buttons, reminder copy). Support right‑to‑left languages and regional nuances. Provide a single formatting utility consumed by email, in‑app views, Slack notifications, and ICS generation to ensure consistency.

Acceptance Criteria
Consistent Locale Formatting Across Email, In‑App, Slack, and ICS
Given a meeting start instant 2025-03-21T19:30:00Z and guest A with locale=en-US, tz=America/New_York When rendering the time string via the shared formatting utility for email subject, in‑app card, Slack notification, and ICS SUMMARY Then each surface displays exactly: "Fri, Mar 21, 2025, 3:30 PM EDT" and no surface deviates in punctuation, order, or hour-cycle And the ICS contains DTSTART;TZID=America/New_York:20250321T153000 and includes a VTIMEZONE for America/New_York Given the same instant and guest B with locale=en-GB, tz=Europe/London When rendering across all surfaces Then each surface displays exactly: "Fri, 21 Mar 2025, 19:30 GMT" And the ICS contains DTSTART;TZID=Europe/London:20250321T193000 and a VTIMEZONE for Europe/London Given the same instant and guest C with locale=de-DE, tz=Europe/Berlin When rendering across all surfaces Then each surface displays exactly: "Fr., 21.03.2025, 20:30 MEZ" And the ICS contains DTSTART;TZID=Europe/Berlin:20250321T203000 and a VTIMEZONE for Europe/Berlin Given the same instant and guest D with locale=ja-JP, tz=Asia/Tokyo When rendering across all surfaces Then each surface displays exactly: "2025/03/22 04:30 JST" And the ICS contains DTSTART;TZID=Asia/Tokyo:20250322T043000 and a VTIMEZONE for Asia/Tokyo
Auto‑Relocalize on Guest Timezone Change (Travel)
Given a meeting start instant 2025-06-10T15:00:00Z and guest with initial locale=en-IN, tz=Asia/Kolkata And an email invite and ICS have already been sent When the guest’s device timezone is detected as Europe/London ≥24 hours before the event Then all subsequent renders (reminders, in‑app, Slack) show: "Tue, 10 Jun 2025, 16:00 BST" for locale=en-GB hour-cycle and date order And a regenerated ICS for that guest contains DTSTART;TZID=Europe/London:20250610T160000 and VTIMEZONE for Europe/London And no stale communications are sent showing Asia/Kolkata after the timezone change Given the guest reverts to America/New_York before T‑1h When the T‑1h reminder is sent Then it displays: "Tue, Jun 10, 2025, 11:00 AM EDT" and the ICS DTSTART uses America/New_York And the event instant remains 2025-06-10T15:00:00Z across all conversions
DST Transition Handling and Ambiguity Resolution
Given instant 2025-03-09T09:30:00Z and guest tz=America/Los_Angeles (spring forward day) When formatting the local time Then it displays "Sun, Mar 9, 2025, 1:30 AM PST" and offset is UTC−8 Given instant 2025-03-09T10:30:00Z and the same tz When formatting the local time Then it displays "Sun, Mar 9, 2025, 3:30 AM PDT" (note hour 2:00 AM is skipped) and offset is UTC−7 Given instant 2025-11-02T08:30:00Z and guest tz=America/New_York (fall back day) When formatting the local time Then it displays "Sun, Nov 2, 2025, 4:30 AM EDT" and offset is UTC−4 Given instant 2025-11-02T09:30:00Z and the same tz When formatting the local time Then it displays "Sun, Nov 2, 2025, 4:30 AM EST" and offset is UTC−5 Given an invalid local wall time such as 2025-03-09 02:15 at tz=America/Los_Angeles When the utility is asked to format this wall time Then it either throws error code NONEXISTENT_LOCAL_TIME or, if configured with resolve=nextValid, returns "Sun, Mar 9, 2025, 3:15 AM PDT"; the behavior is controlled by an explicit configuration flag and covered by automated tests And ICS VTIMEZONE blocks for America/Los_Angeles and America/New_York include both standard and daylight rules covering 2025 transitions
Right‑to‑Left (RTL) Rendering and Numerals
Given locale=ar-SA and tz=Asia/Riyadh with instant 2025-03-21T19:30:00Z When rendering email subject and in‑app title Then the string begins with an RTL mark (U+200F) and all digits are Arabic‑Indic (e.g., time shows "٢٢:٣٠") And punctuation and spacing are placed according to UAX#9 (no mirrored commas around Latin segments) And RSVP buttons are labeled in Arabic and ordered and aligned right‑to‑left (e.g., [نعم] then [لا]) And Slack messages include bidi isolation around interpolated LTR segments (e.g., email addresses) using U+2068/U+2069 or equivalent Given locale=he-IL and tz=Asia/Jerusalem When rendering the same event Then the primary paragraph direction is RTL, numbers remain locale‑appropriate, and no mixed‑direction garbling occurs in subject, buttons, or Slack text
ICU Templates, Variables, and Pluralization
Given ICU message key reminder.minutes with pattern for en: "Reminder in {minutes, plural, one {# minute} other {# minutes}}" When minutes=1 Then the rendered string is "Reminder in 1 minute" When minutes=2 Then the rendered string is "Reminder in 2 minutes" Given ICU message key for ru: "Напоминание через {minutes, plural, one {# минуту} few {# минуты} many {# минут} other {# минуты}}" When minutes=1 Then the rendered string is "Напоминание через 1 минуту" When minutes=2 Then the rendered string is "Напоминание через 2 минуты" When minutes=5 Then the rendered string is "Напоминание через 5 минут" Given a template with placeholders: "{organizer} scheduled {title}" When organizer="Ana" and title="Sprint Review" Then the rendered string is "Ana scheduled Sprint Review" in the guest’s language, with placeholders safely escaped Given a missing translation for locale=pt-BR When rendering any key Then the system falls back to locale=pt, otherwise to en, while preserving number/date formatting for pt-BR And telemetry records the missing key once per release/channel
Single Formatting Utility Enforcement and Consistency
Given the codebase is scanned with a lint rule forbidding direct Date/Number formatting outside the shared utility When running CI Then there are 0 violations of disallowed APIs (e.g., Date.toLocaleString, Intl.DateTimeFormat) outside the utility package Given the shared utility version is updated When rendering the same instant for a test guest across email, in‑app, Slack, and ICS in an end‑to‑end test Then all four surfaces produce identical normalized tokens for date/time, timezone label, numerals, and language And a golden snapshot diff shows no divergence between surfaces Given a locale override feature flag When toggled from en-US to en-GB in a test session Then all surfaces switch to 24‑hour format and day‑month order consistently with no surface lagging by more than one render cycle
Week Start Day and Calendar Grid Localization
Given the in‑app calendar grid and locale=en-US When rendering a week view Then the first column is Sunday and weekday headers are "Sun, Mon, Tue, Wed, Thu, Fri, Sat" Given locale=en-GB When rendering the same view Then the first column is Monday and headers are localized ("Mon, Tue, Wed, Thu, Fri, Sat, Sun") Given locale=ar-SA When rendering the same view Then the first column is Saturday, headers are RTL‑localized, and digits use Arabic‑Indic Given a live locale switch in the UI from en-US to en-GB When the user switches locales Then the grid re‑renders with the correct first day of week within one frame without requiring a page reload
DST‑Safe Scheduling Engine
"As a scheduler, I want meeting times to account for DST shifts at the event date so that no one misses a call due to clock changes."
Description

Compute attendee‑specific meeting times using IANA tzdb rules at the event’s future date, correctly handling daylight saving time transitions, historical changes, and ambiguous/non‑existent local times. Auto‑update tzdb data regularly. Detect when a proposed slot falls within a DST change window and provide alternative suggestions or add clear annotations. Ensure ICS invites include correct TZID and DTSTART/DTEND with VTIMEZONE to render properly across Google, Outlook, and Apple Calendar.

Acceptance Criteria
Non‑Existent Local Time Handling (Spring Forward)
Given an attendee’s timezone has a DST spring‑forward on the event date where local times between 02:00 and 02:59 do not exist When the scheduling engine evaluates a candidate slot that maps to a non‑existent local time (e.g., 02:30) Then the engine must reject that slot for that attendee And it must propose at least 2 alternative valid local times within ±90 minutes that respect the attendee’s working hours and ergonomic constraints And the UI must display an annotation containing the words “DST” and “time skipped” for the affected attendee And the confirmed ICS must include DTSTART/DTEND with a TZID and VTIMEZONE such that the time resolves to a valid single UTC instant in that locale And no “floating” times (no DTSTART/DTEND without TZID and no trailing Z) are present
Ambiguous Local Time Handling (Fall Back)
Given an attendee’s timezone has a DST fall‑back on the event date where a local wall time (e.g., 01:30) occurs twice When the scheduling engine offers or confirms a slot at the ambiguous local time Then the UI must disambiguate the occurrence by indicating the UTC offset (e.g., UTC−04 vs UTC−05) or labels “before fallback”/“after fallback,” and display an annotation containing the word “DST” And the ICS must include TZID with a VTIMEZONE whose STANDARD/DAYLIGHT definitions make DTSTART unambiguously map to the intended UTC instant across Google, Outlook, and Apple Calendar imports And the engine must additionally suggest at least 1 alternative slot outside the ambiguous window
ICS Invite TZ Fidelity Across Major Calendars
Given a meeting is confirmed with attendees across at least three distinct IANA timezones When the system generates the ICS invite Then the VCALENDAR must include a VTIMEZONE component for each unique TZID referenced And DTSTART and DTEND must include TZID parameters using valid IANA tzdb names (e.g., America/Los_Angeles) and must not be floating times And importing the ICS into Google Calendar, Microsoft Outlook (desktop/web), and Apple Calendar must display identical local wall times per attendee and resolve to the same UTC instants And automated validation must confirm no warnings for unknown TZID and that the DTSTART/DTEND are not suffixed with Z when TZID is present
TZDB Auto‑Update, Versioning, and Rollback
Given IANA tzdb publishes a new release When the update service runs Then the system must detect, download, verify checksum/signature, and activate the new tzdb within 24 hours And if verification fails, the system must keep the previous tzdb active and log an alert with severity ERROR And each scheduled event must persist the tzdbVersion used for its time computations And updating tzdb must not mutate the UTC instants of already‑scheduled events; only newly scheduled or re‑computed proposals may change And an admin/status endpoint must expose current tzdbVersion and lastUpdatedAt And an integration test simulating a jurisdictional rule change must show different proposal outputs before vs. after update while existing event UTC instants remain unchanged
Attendee Timezone Change Prior to Event
Given an attendee accepts an invite while in Timezone A and later their detected/declared timezone changes to Timezone B before the event When the attendee views the event details or receives reminders Then the displayed local time must reflect Timezone B while the event’s UTC instant remains unchanged And no duplicate invites are generated; the original ICS remains valid and renders correctly in the attendee’s calendar And ergonomic weighting for new proposal computations must use Timezone B for that attendee from the time of change forward And a single non‑blocking notification informs the attendee that times were localized to the new timezone
Cross‑Region Proposal Generation Over DST Boundary
Given a team with attendees in regions that transition DST on different dates (e.g., US and EU) and a target week that spans differing DST states When the engine generates candidate meeting windows Then it must produce at least 3 viable proposals that respect each attendee’s working hours and ergonomic constraints And none of the proposals may fall into non‑existent or ambiguous local times for any attendee And proposals within ±24 hours of any attendee’s DST switch must include a visible “DST” annotation explaining the shift And the scoring must avoid repeating the same attendee’s least‑ergonomic slot across consecutive weeks when a DST boundary is involved
Travel‑Aware Participant Updates
"As a traveling engineer, I want my meeting details to automatically re‑localize when my timezone changes so that I don’t have to reschedule or manually convert times."
Description

Monitor participant timezone changes near the event by listening for OS/browser timezone shifts, optional calendar signals, or explicit self‑reported travel windows from a secure link. When a change is detected, re‑localize all participant‑visible times, regenerate ICS as needed, and send minimal, localized update notifications without altering the canonical UTC event time. Provide guardrails to avoid notification spam and a summary banner indicating that times were adjusted due to travel.

Acceptance Criteria
OS Timezone Shift Re-localization Without UTC Change
Given a confirmed participant with browser timezone sharing enabled and an event starting in ≤72 hours And the participant’s OS/browser timezone offset changes and remains stable for ≥10 minutes When the system detects the change Then the participant-visible event time is recalculated in the new timezone using correct DST rules and locale-specific 12/24-hour format And the event’s canonical UTC start and end times remain unchanged And a single localized, minimal update notification is sent to the participant And the event view shows a localized banner indicating times were adjusted due to travel/DST for that participant
Self-Reported Travel Window Overrides Locale
Given a participant opens a time-bound, tokenized secure link for the specific event When they submit a travel window with start/end timestamps and a destination timezone Then the system stores the window and applies the specified timezone to all participant-visible times during that window And the system automatically reverts to the prior detected/home timezone after the window ends And at most one localized notification is sent at window start (and at window end) only if the local clock time representation changes And no notification is sent if the local clock time remains unchanged And the secure link requires a valid token, expires after 7 days or upon save, and is scoped only to that event’s travel settings
Calendar Signal Heuristic With Conflict Resolution
Given the participant has granted optional calendar access and an event occurs within the next 7 days And a calendar item indicates travel whose location/timezone overlaps the event time with a different offset And the inferred timezone remains consistent for ≥10 minutes When the system ingests the signal Then participant-visible times use the inferred timezone for the overlap period And precedence for conflicts is: self-reported > OS/browser > calendar And no more than one notification per event per participant is sent in any 24-hour period And no notification is sent if the local clock time representation does not change
ICS Regeneration Preserves UTC With Incremented Sequence
Given a participant’s effective timezone changes and affects their localized representation When an updated ICS is generated for that participant Then the ICS retains the same UID as the original invite And the SEQUENCE value is incremented by at least 1 from the previous ICS And DTSTART and DTEND remain in UTC and equal to the canonical event times And SUMMARY and DESCRIPTION fields are localized to the participant’s language where available And the ICS validates against RFC 5545 And the updated ICS is attached to the notification And no ICS is regenerated if there is no change to participant-visible representation
Localized Minimal Notification With Rate Limits
Given the participant’s language and locale are known or inferred from Accept-Language When a timezone change requires notifying the participant Then the notification content is localized to the participant’s language And it displays the unchanged UTC time and the new local time formatted per locale And it excludes nonessential details beyond the change summary and relevant action links And at most one notification per event per participant is sent within any 24-hour window And duplicate notifications within 60 minutes are suppressed And notifications respect user opt-out preferences
Travel Adjustment Summary Banners
Given a participant views the event page or invite When their displayed time has been adjusted due to travel or DST within the last 72 hours Then a localized banner is shown indicating times were adjusted and showing the last updated timestamp And the banner does not reveal other participants’ personal travel details And the host’s event dashboard shows a non-identifying banner that one or more participants had time adjustments
Multi‑Channel Localized Invitations & Updates
"As a guest, I want localized invites and updates across email, calendar, and Slack so that I see the same correct time everywhere I check."
Description

Generate consistent, localized content across channels: email (HTML/text), calendar invites (ICS with correct timezone blocks), Slack DMs, and in‑app views. Ensure that all channels display the same localized time and copy, and that updates or reschedules propagate atomically. Provide deep links like “View in my time zone” and “Change language” that respect per‑guest preferences and device locale.

Acceptance Criteria
Localized New Invite Consistency Across Channels
Given a meeting is created by a host in America/Los_Angeles with title "Sprint Sync" and two guests: Guest A (de-DE, Europe/Berlin) and Guest B (ja-JP, Asia/Tokyo) When TimeMeld generates and sends invitations via email (HTML and plain text), Slack DM, in-app view, and attached .ics files Then each channel displays the meeting date and time in the guest’s local timezone with correct DST application for that date And each channel formats time according to locale conventions (e.g., de-DE and ja-JP use 24-hour format; no AM/PM) And the email Content-Language header matches the guest locale, and HTML and plain text bodies contain identical date/time strings And the Slack DM and in-app view display the same localized date/time and copy as the email for that guest And the .ics includes a single VEVENT with a consistent UID across channels and DTSTART/DTEND specified (with TZID or UTC) such that the event renders at the same instant as other channels in the guest’s calendar, including across DST And when all channel times are normalized to UTC, they are equal for a given guest
Atomic Reschedule Propagation Across Channels
Given an existing meeting invite has been delivered across email, Slack DM, in-app, and .ics with SEQUENCE N When the host reschedules the meeting to a new time Then updated email (HTML/plain), Slack DM, in-app view, and .ics are delivered and visible within 60 seconds And no channel shows the old time after 60 seconds; all channels display the new time and updated copy And the .ics update uses the same UID with SEQUENCE N+1 and an appropriate METHOD (REQUEST/PUBLISH) so calendar clients replace the prior instance And the Slack DM updates the original message (or posts a threaded update) reflecting the new time without creating a duplicate invite message And the in-app view reflects the new time without requiring a hard refresh And a single event version identifier is recorded so all channel payloads reference the same version
Deep Link — View in My Time Zone
Given a guest has a stored preference timezone of Europe/London and their current device timezone is Asia/Kolkata When they click the "View in my time zone" link in any channel Then the landing view renders the meeting time in Asia/Kolkata with the correct GMT offset and DST for the event date And the view clearly indicates the timezone used for rendering And the guest’s stored preference timezone remains unchanged on the server And the deep link is signed; invalid or expired tokens return 401 without revealing event details
Deep Link — Change Language Preference
Given a guest’s language is set to English (en-US) When they click "Change language" and select Spanish (es-ES) Then the confirmation UI displays in Spanish and future email, Slack DM, in-app views, and .ics text fields (SUMMARY/DESCRIPTION) use Spanish And outgoing emails include Content-Language: es-ES and web views respect Accept-Language for es-ES And previously sent messages are not edited retroactively unless a resend is explicitly triggered And if the selected language is unsupported, the system falls back to English per string and records the fallback with the requested language code
Guest Travel — Automatic Timezone Update
Given a guest originally viewed the invite in America/New_York and travels to Europe/Paris before the event When they open the in-app view or receive a Slack reminder within 24 hours of the event Then the displayed meeting time reflects Europe/Paris local time with correct DST for the event date And the calendar entry from the original .ics (same UID) renders at the correct instant after the device timezone change And no duplicate calendar events are created due to the timezone change And the guest’s effective rendering timezone is updated for display without changing the stored preference unless explicitly saved by the guest
Cross-Channel Consistency and Formatting Validation
Given an invite is generated for a guest with locale fr-FR and timezone Europe/Paris When content is produced for email (HTML/text), Slack DM, in-app, and .ics Then date formatting follows fr-FR conventions (e.g., mardi 14 octobre 2025, 14:30) and 24-hour time And all channels include the same canonical event title and description text in French And when normalized to ISO-8601 UTC, the start and end instants are identical across all channels And the plain-text email contains no HTML tags and matches the human-readable date/time string used in HTML, Slack, and in-app And there are no placeholders or untranslated strings; any missing translation falls back to English with a logged warning
User Overrides, Preferences & Privacy Compliance
"As an attendee, I want to control my timezone and language settings and what detection methods are used so that I’m comfortable with privacy and always see accurate details."
Description

Allow guests to override detected timezone and language, set persistence scope (this event vs. all future TimeMeld invites), and manage consent for geolocation signals. Store only minimal necessary data with retention limits, and provide export/delete options to meet GDPR/CCPA. Offer admin policies to restrict detection methods by region and to set default fallbacks. Log detection sources and consent decisions for compliance audits.

Acceptance Criteria
Guest Overrides Timezone
Given a guest sees meeting times in a detected timezone When the guest clicks "Change Timezone" and selects a different timezone Then all displayed times update to the selected timezone within 500 ms And a visible label "Timezone: {Selected}" appears and remains on the page And the override persists according to the selected persistence scope And the change is recorded in the audit log with timestamp and source="user"
Guest Overrides Language
Given a detected language is applied When the guest selects a different language from the language switcher Then UI strings and date/time formats update to the selected language within 500 ms without a full page reload And the confirmation email for this invite is generated in the selected language And RTL languages render with correct direction and layout where applicable And the change is recorded in the audit log
Preference Persistence Scope
- The scope control offers "This Event Only" and "All TimeMeld Invites" whenever a guest overrides timezone or language - Selecting "This Event Only" stores the preference client-side scoped to the invite token and expires at event end or 30 days, whichever is sooner; no server-side profile is created - Selecting "All TimeMeld Invites" stores only timezone and language server-side keyed to a verified email and applies to future TimeMeld invites; it expires after 12 months of inactivity or upon guest revocation - The selected scope is displayed and can be changed before leaving the page; changes take effect immediately - If the guest email is unverified, the "All TimeMeld Invites" option is disabled with an explanatory message
Consent for Geolocation Signals
- A consent prompt lists each detection method (IP geolocation, browser language, device timezone, travel detection) with individual toggles - Detection methods do not execute until consent is captured, except those marked as strictly necessary by current admin policy; non-consented methods remain disabled - Declining consent triggers use of admin-configured fallback timezone and language; no IP or precise location is stored - Consent records include method toggles, timestamp, region code, policy ID, and (if provided) guest email; retention is 13 months or until revoked - Guests can revisit and modify consent at any time; updates take effect immediately and are logged
Data Export and Deletion (GDPR/CCPA)
- A self-serve portal allows guests to request data export or deletion after email verification - Exports include timezone/lang preferences, consent history, detection-source logs, applied policy IDs, and timestamps; delivered within 5 minutes as downloadable JSON and CSV - Deletion requests remove stored preferences and consent records within 7 days; audit logs are pseudonymized by removing direct identifiers - A confirmation of export or deletion is emailed to the requester; subsequent invites use defaults with no auto-filled overrides - Rate limiting is enforced: maximum 3 privacy requests per 24 hours per email
Admin Regional Policies and Fallbacks
- Admins can define region-based policies specifying allowed detection methods and default fallback timezone/language; precedence is region > org > system - Disallowed methods are not executed and are hidden or disabled in the guest consent UI for affected regions - Policy changes propagate and are enforced within 5 minutes across invite pages and APIs - When region cannot be reliably determined pre-consent, the org default policy is applied; no geolocation lookup results are stored - All policy changes are captured in an audit log with actor, timestamp, and change summary
Audit Logging of Detection Sources and Decisions
- For each invite session, an immutable log entry is created for detection sources used, consent state, overrides applied, persistence scope, effective policy ID, region code, and timestamps - Logs do not store raw IP addresses or precise coordinates; region/country code is stored; guest email is hashed with an org-scoped salt - Log retention is 24 months; access is restricted to Compliance Admins; export is available in CSV and JSON - Log writes succeed within 200 ms of the triggering event and are resilient to client refreshes via server-side logging with idempotency keys
Fallback & Error Resilience
"As a guest, I want clear fallbacks and conversion options when my locale can’t be determined so that I can still confirm the correct meeting time."
Description

When detection confidence is low or signals conflict, default to a safe presentation that includes UTC, host’s timezone, and a prominent “Convert to my time” link that opens a localized viewer. Provide clear error states in invites, resilient parsing of malformed locales, and automatic retries for external dependencies. Capture telemetry on failures, confidence levels, and overrides to guide continuous improvement.

Acceptance Criteria
Low-Confidence Detection Fallback Display
Given detection_confidence < 0.7 OR locale_timezone is null When rendering meeting details for a guest Then display meeting time in UTC (ISO 8601 with Z) and host timezone (IANA name and localized time) And display a prominent "Convert to my time" link above the fold with role="button" And do not display an auto-localized date/time string And emit telemetry event fallback_used with fields: reason="low_confidence", confidence, guest_id_hash, meeting_id
Conflicting Signals Resolution Policy
Given signals from Accept-Language, IP geolocation, and calendar timezone differ by two or more distinct timezones When determining the guest timezone Then set detection_confidence <= 0.6 and use fallback presentation And display UTC and host timezone times and the "Convert to my time" link And emit telemetry event conflict_detected with sources[], chosen_policy="fallback", and confidence
"Convert to my time" Localized Viewer
Given a guest clicks the "Convert to my time" link When the localized viewer opens Then detect the device timezone via Intl/ECMAScript APIs and format date/time in the device locale (12/24h per locale) And account for DST at the scheduled datetime using the IANA timezone database And render the viewer within 1000 ms TTFB on a 3G connection And display the timezone name and offset (e.g., "Europe/Berlin (UTC+02:00)") And if the device timezone changes while open, update the display within 5 seconds
Clear Error States in Invites
Given a failure occurs during localization (e.g., formatter throws, template missing, service unreachable) When generating the invite content in HTML and plain-text Then render a clear error banner "We couldn't localize your time" without technical details And include UTC and host timezone times and the "Convert to my time" link And ensure accessibility: banner role="alert" and contrast ratio >= 4.5:1 And emit telemetry error_state_rendered with error_code, stack_hash, meeting_id
Resilient Parsing of Malformed Locales
Given malformed locale inputs such as "en_US", "pt-PT-utf8", empty strings, or deprecated/alias timezone IDs like "US/Eastern" When parsing headers or profile fields Then normalize to a best-effort standard (e.g., "en-US", "pt-PT", "America/New_York") or set to null without throwing And maintain a normalization map for at least 50 common malformed cases And unit tests cover at least 20 malformed inputs with 100% pass rate And emit telemetry locale_parse_normalized with original and normalized values (hashed as applicable)
Automatic Retries and Circuit Breaking
Given an external dependency (timezone/geo lookup or localization service) returns 5xx or times out When making the request Then retry up to 3 times with exponential backoff starting at 200 ms with +/-50% jitter And total added wait time does not exceed 2 seconds And open a circuit breaker after 5 consecutive failures for 60 seconds And on final failure, present fallback (UTC + host time + "Convert to my time" link) and emit telemetry external_retry_exhausted with attempt_count and durations
Telemetry Coverage and Privacy Safeguards
Given any fallback, conflict, override, parsing normalization, or external failure occurs When recording telemetry Then capture at minimum: event_name, meeting_id, tenant_id, timestamp, reason_code, detection_confidence (0..1), tz_sources[], selected_tz, user_agent_hash And exclude raw IP, email, or full user agent; hash or tokenize identifiers with salt rotation every 30 days And batch and send within 10 seconds or on app close, with at-least-once delivery And validate against schema "autolocalize_v1"; events failing validation are dropped with local debug log only

Easy Rebook

Lets external guests propose or pick from organizer‑approved alternate slots directly from the invite page. One tap updates everyone’s calendars, preserves conferencing details, and respects fairness rules—cutting email back‑and‑forth while staying humane across timezones.

Requirements

Guest Rebook Widget
"As an external guest, I want to rebook directly from the invite page by choosing an organizer-approved slot so that I can avoid email back-and-forth and pick a time that fits my timezone."
Description

Embeddable, mobile-responsive widget on the invite page that lets external guests pick from organizer-approved alternate slots or propose within allowed windows. Automatically localizes times to the guest’s timezone, displays meeting context (title, participants, duration), and enforces basic constraints (buffers, working hours, slot caps). Includes accessibility compliance, inline validation, and instant feedback on slot availability. Instrumented for analytics and supports deep links with preselected options.

Acceptance Criteria
One‑Tap Rebook from Organizer‑Approved Slot (Desktop & Mobile)
Given an external guest opens the invite page containing the Guest Rebook Widget on a supported desktop or mobile browser And at least one organizer‑approved alternate slot is displayed When the guest selects an available slot and taps Confirm Then the widget verifies availability in real time and locks the slot within 500 ms And the meeting is rescheduled for all participants, preserving conferencing details and description And updated calendar invites are delivered to all attendees within 10 seconds And the original slot is released and the new slot is shown as booked on refresh And the guest sees a success state with localized date/time and an Add to Calendar action And no duplicate events or overlapping holds are created
Guest Proposes Times Within Organizer‑Allowed Windows
Given proposals are enabled with configured allowed windows, lead time, and number of proposals (1–3) When the guest enters a proposal outside the allowed windows or lead time Then the Confirm action remains disabled and an inline error explains the violation When the guest submits proposals within the allowed windows Then the proposals are accepted, participants are notified, and any temporary holds respect configured buffers And the guest can modify or withdraw proposals until an organizer accepts, with status visibly updated within 2 seconds of change And proposals that would exceed daily slot caps are blocked with an inline reason
Automatic Timezone Detection and Localization with Guest Override
Given the widget loads and can read the browser Intl API timezone or a tz parameter in the URL When rendering available slots and meeting details Then all times display in the detected/param timezone with correct DST handling When the guest changes the timezone via the control Then all displayed times update within 300 ms and the selection persists for the session And any Add to Calendar output encodes the correct timezone/offset so the event lands at the intended local time
Inline Validation and Constraint Enforcement (Buffers, Working Hours, Slot Caps, Fairness)
Given organizational constraints are configured (minimum buffers before/after, participant working hours, per‑day slot caps, and fairness limits) When a slot violates any constraint Then the slot is disabled and a reason is shown via tooltip or inline helper text When the guest attempts to confirm a slot that became non‑compliant due to a recent change Then submission is blocked with a clear message and refreshed, compliant alternatives are presented within 1 second When fairness limits would be exceeded (e.g., too many early/late meetings for a participant in the current week) Then the slot is either hidden or marked unavailable with a fairness reason code
Accessibility Compliance for the Guest Rebook Widget (WCAG 2.2 AA)
Given a keyboard‑only user navigates the widget Then all interactive elements are reachable in logical order with a visible focus indicator and no focus traps And screen readers announce labels, state, and dynamic updates (via aria‑live) for slot changes, errors, and confirmations And color contrast for text and interactive elements meets ≥ 4.5:1; controls have touch targets ≥ 44×44 dp; content reflows at 320 px width without loss of function And the widget yields 0 critical/serious issues in automated audits (axe‑core, Lighthouse) across Chrome/Firefox/Safari desktop and iOS/Android mobile
Deep Link with Preselected Options and Secure Token Handling
Given a guest opens a deep link containing a signed token with meeting identifier and optional preselected slot and timezone When the token is valid and unexpired (≤ 72 hours) Then the widget loads with the slot preselected and timezone applied; the guest can confirm in one tap When the token is invalid, expired, or the slot is no longer available Then the widget loads safely without PII, shows an explanatory message, and surfaces the next best compliant options And no querystring or token reveals PII; signature validation prevents tampering
Analytics and Telemetry Instrumentation for Rebook Interactions
Given the widget is rendered Then analytics events are fired for widget_viewed, slots_shown, slot_selected, propose_started, propose_submitted, rebook_confirmed, validation_error, and a11y_navigation And each event includes meeting_id, anonymous_guest_id (hashed), slot_id (if applicable), timezone, device_type, duration, outcome, and reason_code (for errors) And events are queued and delivered within the session with ≤ 1% loss; offline retries back off and cap at 24 hours And events exclude PII by design and honor Do Not Track and org privacy settings
Organizer-Approved Slots Management
"As an organizer, I want to pre-approve alternate slots with my constraints so that guests can safely rebook without needing my manual review each time."
Description

Controls for organizers to pre-approve or curate alternate windows generated by TimeMeld, including duration, working-hour bounds, buffer rules, blackout dates, per-day caps, and series-level preferences. Supports quick add/remove of slots from within the calendar event, auto-refreshes suggestions as calendars change, and allows default templates per team. Integrates with fairness and ergonomics settings so only compliant slots are exposed to guests.

Acceptance Criteria
Constraint-Governed Slot Generation
Given an organizer opens Manage Alternate Slots for an event with at least two attendees When they set Duration=30m, Working Hours per attendee=09:00–17:00 local, Min Buffer=15m before and after, add two Blackout Dates, and set Per-day Cap=2 per attendee, then click Generate Then the suggestions list contains only slots that satisfy all configured constraints And no slot overlaps any attendee's blackout dates And no slot violates the per-attendee working hours And no slot leaves less than 15 minutes buffer from existing events on the organizer's calendar And no attendee has more than 2 suggested slots on any single day And the UI displays the count of suggested slots
Inline Add/Remove of Approved Slots
Given the organizer views Suggested and Approved slot lists within the calendar event When they click Approve on a suggested slot and Save Then the slot appears in the Approved list and on the guest invite page within 10 seconds or upon page refresh And when they click Remove on an approved slot and Save Then the slot is removed from the guest invite page within 10 seconds or upon page refresh And if a guest attempts to book a removed slot from a stale page, the system blocks the booking and displays "Slot no longer available"
Auto-Refresh on Calendar Changes
Given a suggested slot exists for an event When any attendee creates a conflicting calendar event overlapping that time Then the slot is automatically marked unavailable and removed from suggestions within 2 minutes And if the conflicting event is deleted, the slot reappears within 2 minutes provided it still meets all constraints And the organizer receives a non-blocking in-app notification of the change
Series-Level Preferences and Overrides
Given a recurring meeting series with Easy Rebook enabled When the organizer sets series-level duration, working-hour bounds, buffer rules, blackout dates, and per-day caps and saves Then these preferences apply to all future occurrences by default And modifying constraints on a single occurrence creates an occurrence-level override And clearing an occurrence-level override reverts that occurrence to the series defaults And changing series defaults does not overwrite existing occurrence-level overrides
Team Template Application and Governance
Given a team with a default slots template is selected for the event When the organizer opens Manage Alternate Slots Then the panel pre-populates with the template's duration, working-hour bounds, buffer rules, blackout dates, and per-day caps And only team admins can create or edit team templates And updating a team template affects newly created events under that team but does not change existing saved settings on already-configured events
Fairness and Ergonomics Compliance Filter
Given team-level fairness rotation and ergonomics (quiet hours, earliest/latest boundaries, load balance) settings are enabled When slots are generated or an organizer attempts to approve a slot Then any slot that violates fairness or ergonomics rules is excluded from suggestions and cannot be approved And excluded slots display a reason code or tooltip explaining the violated rule And all approved slots are labeled as Compliant with reference to the active rule set
Zero-Compliant-Slots Fallback
Given the configured constraints and fairness rules yield zero compliant slots for an event When the organizer opens the Approved Slots view Then the system displays No compliant slots and highlights the most restrictive constraints to relax And the guest invite page hides reschedule options and presents a Request another time action instead
One-Tap Calendar Update
"As an organizer, I want rebooking to update everyone’s calendars and keep the same conferencing details so that the meeting continues seamlessly without new links or confusion."
Description

Atomic reschedule operation that updates all participants’ calendars when a guest selects a new slot, preserving conferencing details (meeting ID/link), agenda, attachments, and participant list. Supports Google and Microsoft 365 with ICS fallback, updates resource bookings (rooms), and sends updated invites and confirmations. Ensures idempotency, prevents duplicates, and maintains original meeting series linkage for recurring events.

Acceptance Criteria
Atomic Reschedule Across All Calendars
Given a scheduled meeting with multiple participants across Google Calendar and Microsoft 365 And at least one external attendee using a non-integrated calendar And the organizer has pre-approved alternate time slots When an external guest selects one approved slot and confirms rebook Then the system updates the meeting time for all participants atomically And the event UID remains the same and the SEQUENCE is incremented exactly once And the original time is released for all participants And if any participant update fails, all updates are rolled back to the original time And the initiator and organizer receive a failure notification detailing the failed provider(s) And no partial updates persist
Preserve Conferencing and Meeting Artifacts
Given an existing meeting with a conferencing link/meeting ID, agenda text, file attachments, and a defined participant list When the meeting is rescheduled via one-tap rebook Then the conferencing link/meeting ID remains unchanged And the agenda and all attachments remain attached once and only once (no duplicates) And the participant list remains unchanged (no unintended adds/removals) And any join instructions, passcodes, and dial-ins are preserved
Cross-Platform Updates with ICS Fallback
Given attendees include Google Calendar users, Microsoft 365 users, and non-integrated email attendees When the reschedule is committed Then Google attendees receive a native Calendar API update and see the new local time on the same event UID And Microsoft 365 attendees receive a Graph API update and see the new local time on the same event UID And non-integrated attendees receive an email with an ICS update (METHOD: REQUEST) containing the same UID and an incremented SEQUENCE And all attendees’ calendars reflect the same absolute UTC time window And conferencing details remain clickable and unchanged across all delivery paths
Resource Booking Reassignment on Reschedule
Given the meeting has an associated room/resource booking When the meeting is moved to a new time Then the original resource booking is released And the same room is booked for the new time if available And if the room is unavailable at the new time, the meeting is updated without a room and the organizer is notified immediately with a Room Unavailable alert And no double-booking is created for any resource And attendees’ calendar entries remain consistent with the resource state
Idempotent Reschedule Request Handling
Given the rebook confirmation may be clicked multiple times or retried by the network/webhook When identical reschedule requests (same event UID and target slot) are received within the idempotency window Then only one calendar update is applied And the system returns the same success response for subsequent duplicates And no duplicate calendar events are created And no duplicate notification emails are sent And the event SEQUENCE is incremented exactly once
Recurring Series Linkage Preservation
Given the meeting belongs to a recurring series When a single occurrence is rescheduled via one-tap Then that occurrence becomes an exception retaining the series UID and RECURRENCE-ID And the rest of the series remains unchanged When the entire series is rescheduled Then the series master is updated while preserving RRULE and attendees And Google and Microsoft 365 displays continue to show correct series linkage for all participants
Updated Invites and Confirmations Distribution
Given the reschedule succeeds When the update is committed Then all attendees receive exactly one updated invitation/notification reflecting the new time And the organizer and initiating guest receive a confirmation message And notifications include old and new times rendered in each recipient’s local timezone And ICS attachments are included for non-integrated recipients And delivery status is logged per recipient without exposing duplicate sends
Fairness Enforcement
"As a distributed team member, I want rebooking to respect fairness rules so that inconvenient times are shared equitably across participants."
Description

Application of timezone-weighted, ergonomic rules during rebooking to avoid repeated early/late times for the same participants. Evaluates guest and organizer local times, rotates inconvenience across a series, and blocks slots that violate configured thresholds. Surfaces "most fair" recommendations and writes outcomes to the equity scoreboard for transparency and reporting.

Acceptance Criteria
Block Unfair Rebook Slots by Threshold
Given organizer-approved alternate slots and configured fairness policy values: WorkdayStart, WorkdayEnd, WindowSizeOccurrences, MaxEarlyLatePerWindow When the guest views candidate rebook times Then any slot where any participant’s local start time is before WorkdayStart or after WorkdayEnd is labeled Unfair and disabled for selection And any slot that would increase any participant’s count of early/late occurrences in the last WindowSizeOccurrences beyond MaxEarlyLatePerWindow is labeled Unfair and disabled And the UI displays the affected participants and the violated rule for each disabled slot
Rotate Inconvenience Across Series
Given a recurring meeting series with recorded inconvenience counts per participant over the last WindowSizeOccurrences And configured policy values: WeightEarly, WeightLate, MaxShareDelta When fairness scores are computed for each candidate slot Then each candidate receives a total fairness score derived from per-participant inconvenience contributions weighted by WeightEarly and WeightLate And any candidate whose projected share delta for any participant exceeds MaxShareDelta is excluded from selection And among remaining candidates, the allowed set favors those that reduce the variance of inconvenience counts across participants
Surface Most-Fair Recommendations
Given at least one fair candidate slot exists after applying fairness exclusions When presenting options on the rebook page Then the top 3 candidates with the lowest fairness scores are labeled Most fair and sorted ascending by score And if feasible, at least one Most fair candidate does not assign inconvenience to the same participant as the last occurrence And selecting any Most fair candidate succeeds without triggering a fairness violation
Write Outcomes to Equity Scoreboard
Given a rebook action is confirmed to a fair slot When persisting the result Then the system records to the Equity Scoreboard: meetingId, seriesId, occurrenceTimestampUTC, selectedSlotTimestampUTC, perParticipant {participantId, timezone, localStart, inconvenienceType, severityWeight}, totalFairnessScore, rotationBalancesBeforeAfter, selectedBy, and reasonCodes And the scoreboard entry is visible in the UI and API within 5 seconds of confirmation And the entry is included in export/report endpoints for the meeting series
Handle DST and Timezone Changes
Given a participant’s timezone setting changes or a DST transition affects the occurrence date When evaluating and displaying candidate slots Then local start times are computed using the effective IANA timezone rules for the occurrence date for each participant And fairness decisions (block/allow, scoring, recommendations) use these computed local times And any cached fairness evaluations for the affected meeting occurrence are invalidated and recomputed within 2 seconds of the detected change
Fallback and Organizer Override When No Fair Slots
Given all organizer-approved alternates are blocked by fairness rules When the guest opens the rebook options Then the UI indicates No fair times available and offers Request new times And the system generates the next three fair windows within FallbackHorizonDays and includes them in the request to the organizer And if the organizer overrides fairness to select a blocked slot, an override note is required, the action is logged with override=true and reasonCode=OrganizerOverride, and the scoreboard reflects the override
Secure Tokenized Access
"As an organizer, I want only intended invitees to rebook securely without needing an account so that my meetings aren’t hijacked or exposed."
Description

Signed, expiring, single-use rebooking links scoped to the specific event and invitee, with optional email verification/OTP. Detects forwarded links, rate-limits attempts, and enforces CSRF protection. No account required for guests while still attributing the actor for audit logs. Compliant with data privacy requirements and configurable link lifetimes.

Acceptance Criteria
Single-Use, Event-and-Invitee-Scoped Token
Given a valid signed token bound to event E and invitee I, when the link is opened before expiry, then the rebook page renders only for event E and invitee I and no other events are accessible. Given the same token is used to successfully submit a rebooking for event E, when the token is used again (GET or POST), then the system returns HTTP 410 Gone, shows a "Link already used" message, and performs no state changes. Given a token with a modified or invalid signature, when the link is opened, then the system returns HTTP 401/403, shows an "Invalid link" message, and does not reveal any event or invitee metadata. Rule: The token present in the URL contains no plaintext PII (e.g., no email or names), and all request-scoped identifiers are enforced from the token rather than client-provided parameters.
Configurable Token Expiration and Enforcement
Given the organization sets token_lifetime_hours = X within the allowed range (1–168 hours), when a new token is issued, then its server-side expiry is now + X hours and is embedded/saved accordingly. Given a token is accessed after its expiry time, when the page is requested, then the system returns HTTP 410 Gone, shows a "Link expired" message with a CTA to request a new link, and does not reveal event details. Given token_lifetime_hours is changed by an admin, when new tokens are created, then they use the new lifetime, and previously issued tokens retain their original expiry.
Forwarded Link Detection and Safe Response
Given a token for invitee email i@example.com, when the guest enters an email that does not equal i@example.com to proceed, then access is denied or escalated to verification, and an audit event "forwarded_link_detected" is recorded. Given the same token is opened from more than 3 unique IPs or device fingerprints within 1 hour, when attempting to proceed, then the user is forced into verification (OTP) before continuing and subsequent attempts are rate-limited. Rule: Until verification passes for a suspected forwarded link, the page redacts meeting title, organizer names, and other sensitive details.
Optional Email Verification/OTP
Given require_guest_otp = true, when the invitee opens the link, then they are prompted to confirm i@example.com and a 6-digit OTP is sent to that address. Given an OTP has been sent, when the correct code is entered within 10 minutes and no more than 5 attempts, then verification succeeds and the user proceeds to rebook. Given incorrect OTP attempts exceed 5 or the OTP expires, when further attempts are made, then verification is locked for 15 minutes and an audit entry is recorded. Given require_guest_otp = false, when the link is opened, then no OTP step is shown and rebooking proceeds using token validation alone. Rule: OTP resend generates a new code, invalidates the previous code, and is limited to 3 resends per 15 minutes per token.
Rate Limiting and Lockouts
Rule: A maximum of 10 sensitive actions (OTP submit, OTP resend, rebook POST) per IP and per token are allowed within 5 minutes; further requests receive HTTP 429 with a Retry-After header and no state change. Rule: OTP resend is capped at 3 per 15 minutes per IP and per token; additional requests are blocked with HTTP 429 and explanatory UI text. Given multiple identical rebook submissions carry the same Idempotency-Key within 2 minutes, when they are received, then only the first is processed and subsequent ones return HTTP 409 Conflict with no duplicate changes.
CSRF Protection on Rebook Actions
Given a rebook POST request is submitted without a valid CSRF token bound to the current session cookie, then the server returns HTTP 403 and no state changes occur. Given the POST request Origin/Referer does not match the rebook page origin, then the server returns HTTP 403 and no state changes occur. Rule: Session cookies used in the flow are set with Secure and SameSite=Lax (or stricter) flags enabled.
Audit Logging and Actor Attribution (No Account)
Rule: For each action (token issued, link opened, OTP sent, OTP verified success/fail, forwarded_link_detected, rate_limited, rebook submitted success/fail, token expired/invalid), an immutable audit log entry is created capturing event_id, invitee_id, token_id, actor_email (from token or verified input), timestamp (UTC), IP, user_agent, action, and result. Given a rebooking is completed by a guest without an account, when the action is logged, then the actor is attributed as "guest:<invitee_email>" and includes token_id for traceability. Rule: Audit log entries are accessible only to authorized organizer/admin roles for the related event and are retained according to configured data retention policies.
Notifications & Activity Trail
"As an organizer, I want clear notifications and an audit trail of rebooking actions so that I stay informed and can track changes over time."
Description

Real-time notifications to organizers and attendees on rebook proposals, approvals, and confirmations via email and Slack, plus webhook callbacks for integrations. Provides an in-app activity timeline with before/after times, actor identity, timestamps, and reason codes. Supports notification preferences and digesting to reduce noise.

Acceptance Criteria
Real-Time Proposal Notification to Organizer and Internal Attendees
Given an external guest submits a rebook proposal from the invite page and the proposal is persisted When the event is recorded Then the organizer and all internal attendees receive notifications via Email and Slack within 10 seconds And each notification includes: meeting title, proposed slot in recipient local timezone and UTC, actor name and email, reason code (if provided), actionable links to Approve/Decline/View Proposal, and a unique notification_id And no duplicate notifications are sent to the same recipient within a 5-minute window for the same proposal_id And the proposing external guest receives a single email acknowledgment with a proposal tracking link And delivery outcomes are logged per recipient and channel with timestamp and message_id
Approval or Decline Notification and State Synchronization
Given an organizer approves or declines a rebook proposal When the decision is saved Then the proposing guest and all attendees receive notifications within 10 seconds (Email to all; Slack to internal attendees) And the notification states the decision, decision maker identity, optional reason code, and provides a link to the updated proposal status And pending proposal notifications are marked resolved in the activity timeline with a reference to the decision event_id And duplicate notifications for the same decision and recipient are prevented within a 5-minute window And delivery outcomes are logged per recipient and channel with timestamp and message_id
Rebook Confirmation Notification After Calendar Update
Given a proposal has been approved When calendar updates succeed for all required attendees Then send a confirmation notification via Email and Slack within 10 seconds to organizer and internal attendees, and Email to external guests And the confirmation includes before_start_at and after_start_at (recipient local timezone and UTC), preserved conferencing link, and an updated ICS attachment or calendar update link And if any attendee's calendar update fails after 3 retry attempts within 15 minutes, send a failure notification to the organizer including attendee identifier and error code, with a Retry action link And all confirmation and failure notifications are logged with outcome status, timestamp, and message_id
Webhook Callbacks: Delivery, Security, and Idempotency
Given webhook subscriptions are configured and enabled for the workspace When any of the following events occur: proposal.created, proposal.approved, proposal.declined, rebook.confirmed Then POST a JSON payload to the subscriber endpoint within 5 seconds containing: event_id, event_type, occurred_at (ISO 8601 UTC), meeting_id, actor {id, name, email}, before_start_at, after_start_at, reason_code (optional) And include headers X-TimeMeld-Signature (HMAC-SHA256 of raw body using shared secret) and X-TimeMeld-Timestamp And treat any non-2xx response or request timeout > 10 seconds as a failure; retry up to 12 attempts with exponential backoff and jitter (approx schedule: 30s, 1m, 2m, 4m, 8m, 16m, 32m, 1h, 2h, 4h, 8h, 16h), ceasing on HTTP 410 or when subscription is disabled And ensure idempotency by setting Idempotency-Key equal to event_id and not delivering duplicates to the same endpoint And record per-attempt delivery status and final Pass/Fail visible in the activity timeline with last response code
In-App Activity Timeline Fidelity and Auditability
Given a user views the meeting's activity timeline When rebook-related events have occurred Then entries for proposal, approval/decline, confirmation, and webhook delivery appear newest-first, paginated 50 per page, loading in under 1 second on a standard broadband connection And each entry displays: actor display name and email, event type, timestamp (relative plus ISO 8601 UTC on hover), before_start_at and after_start_at (with timezone abbreviation), reason code (if any), and a link to the related record And entries are immutable; corrections or system adjustments create a new entry that references the prior event_id And access control ensures only invitees and org admins see the full timeline; external guests see only events in which they are participants And times render in the viewer's local timezone while preserving UTC in metadata for copy/export
Notification Preferences, Quiet Hours, and Digesting
Given a user sets notification preferences When preferences specify per-channel (Email, Slack) and per-event-type (proposal, approval, confirmation) settings Then notifications respect these settings: disabled channels do not receive messages; enabled channels do, with no automatic fallback unless explicitly configured And users can define daily quiet hours in their local timezone; notifications generated during quiet hours are deferred into a digest unless marked critical by policy And a daily digest is sent at the user's chosen local time summarizing deferred notifications in the past 24 hours with counts and links; individual messages for those events are not sent And changes to preferences take effect within 1 minute and are logged as entries in the activity timeline indicating actor, fields changed, and timestamp And external guests may opt into Email and daily digest via invite-page preferences; Slack is unavailable to external guests
Conflict Handling & Concurrency
"As a guest, I want the system to handle conflicts and simultaneous changes gracefully so that my rebooking either succeeds cleanly or provides safe alternatives without confusion."
Description

Concurrency-safe booking flow with short-term slot holds, conflict detection against all participants and resources, and graceful fallbacks that suggest the next best fair slot. Implements locking, retries, and rollback to maintain consistency across calendars. Communicates clear errors to guests and preserves proposals when finalization fails.

Acceptance Criteria
Short-Term Slot Hold Prevents Double Booking
Given two guests attempt to book the same organizer-approved slot within the hold TTL When the first request places a hold on the slot Then the second request sees the slot as unavailable and cannot proceed to confirmation And the default hold TTL is 3 minutes (configurable 1–10 minutes) And the hold state is reflected to all viewers within 2 seconds And on successful confirmation the hold converts to a booking; on expiry or cancel the slot immediately becomes available to others
Conflict Detection Across All Participants and Resources
Given a proposed slot overlaps any busy event for required participants or required resources When a guest attempts to finalize the booking Then the system blocks confirmation and lists each conflict (participant/resource, event title if visible, start/end time) And conflicts consider all linked calendars marked as busy, working-hour constraints, and resource calendars And the system does not create partial bookings or tentative holds on conflict
Graceful Fallback Suggests Next Best Fair Slot
Given finalization fails due to a detected conflict or race condition When the guest requests alternatives Then the system returns at least 3 alternative slots within the next 7 days, ranked by TimeMeld fairness score and timezone ergonomics And each alternative respects organizer-approved windows and fairness rules (no repeated inconvenient windows for the same attendee within the last 3 occurrences) And selecting an alternative is one tap and preserves conferencing details and invitee list
Atomic Booking with Locking, Retry, and Rollback
Given multiple calendars must be updated to complete a booking When any calendar write fails or times out Then all previously written events are rolled back within 5 seconds and any holds are released And a per-slot, per-meeting lock prevents concurrent writes; the lock is released on success or failure And the system retries up to 2 times with exponential backoff (e.g., 200ms then 400ms) And operations are idempotent via a booking token so duplicates are not created
Idempotent Confirmation Handles Double-Submit
Given a guest double-clicks confirm or resubmits the request within 30 seconds When duplicate finalize requests with the same booking token reach the server Then exactly one booking is created And all responses return the same booking ID and start/end time And no duplicate emails or notifications are sent
Clear Errors and Proposal Preservation on Failure
Given finalization fails after a guest submits a slot When the error is surfaced to the UI Then the guest sees an actionable message within 2 seconds including reason category (conflict, permission, network) and next steps And the original proposal is saved in a pending state visible to both guest and organizer And the organizer receives a notification with the failure reason and proposed slot And an audit log entry with a correlation ID is recorded And all holds and partial changes are cleaned up
Hold Expiry and Abandonment Recovery
Given a guest has placed a hold by selecting a slot but does not confirm When the hold TTL elapses or the rebook page is closed Then the hold auto-expires and the slot is released And the slot’s availability updates for all viewers within 2 seconds And no calendar events or invites are created

Calendar Deeplink

One‑tap Add to Calendar for Google, Outlook, and Apple with ICS fallback. Injects the correct timezone, conferencing link, and updates that auto‑sync if the meeting moves—so guests never juggle stale links or wrong times.

Requirements

Provider-Specific Deeplink Generation
"As an invited attendee, I want a one-tap button that adds the meeting to my calendar provider so that I don’t have to manually copy details or worry about compatibility."
Description

Generate provider-specific one-tap Add to Calendar links for Google Calendar, Outlook (web/desktop), and Apple Calendar with a robust ICS fallback. Links must prefill title, description, organizer, attendees (optional), location with conferencing URL, reminders, and a stable event UID. Ensure proper URL encoding and support for mobile intents/deeplinks. Integrate with TimeMeld’s meeting object to pull canonical details and emit signed links usable across email, web, and Slack surfaces. Outcome: attendees add events in one tap without manual copy/paste, regardless of provider or device.

Acceptance Criteria
One-Tap Add to Google Calendar (Email/Mobile)
Given a signed Google Calendar deeplink generated from the TimeMeld meeting object When a recipient taps it in Gmail or a mobile browser with Google Calendar installed Then the Google Calendar app opens directly and shows an add-event sheet prefilled with: And Title equals meeting.title And Description contains meeting.description plus the conferencing URL And Organizer equals meeting.organizer.email And Attendees list equals meeting.attendees[*].email when provided; omitted when empty And Location equals conferencing URL host or meeting.location if provided And Start/End reflect meeting.start and meeting.end in meeting.timezone (no device timezone override) And A default reminder 10 minutes before is set And Event UID equals meeting.uid and matches the ICS UID And All characters are percent-encoded; non-ASCII renders correctly And If the composed URL exceeds 2000 chars, a shortlink is used that resolves to the same intent within 300 ms p95 And Tapping Save adds the event without additional edits
Outlook Web and Desktop Deeplink Resolution
Given a signed Outlook deeplink for the TimeMeld meeting When opened in Outlook Desktop (Windows/macOS) Then an ms-outlook:// deep link opens a prefilled event compose window with title, description (including conferencing URL), organizer, optional attendees, location, start/end in meeting.timezone, a 10-minute reminder, and a stable UID stored in iCalUId or custom ExtendedProperty When opened in Outlook Web (OWA) Then an https://outlook.office.com template opens with the same fields prefilled And If the deep link scheme is blocked, an HTTPS fallback path is used automatically And Open-to-compose latency is ≤ 1.5 seconds on a 4G connection p95 And All parameters are URL-encoded; special characters and emojis render correctly
Apple Calendar Add via webcal/ICS on iOS and macOS
Given a signed webcal:// or .ics link generated from the TimeMeld meeting When tapped in Mail/Safari on iOS or clicked in Safari/Mail on macOS Then the native Calendar prompts to add a single event prefilled with: And UID equals meeting.uid And DTSTART/DTEND include TZID=meeting.timezone And VTIMEZONE component is included for meeting.timezone And ORGANIZER and ATTENDEE lines are present per RFC 5545 when attendees provided And DESCRIPTION includes the conferencing URL and plain-text details And LOCATION equals conferencing URL host or meeting.location if provided And VALARM is set 10 minutes before And URL property points to the conferencing link And The ICS validates against RFC 5545 with zero errors and size ≤ 50 KB And Add requires ≤ 2 taps
ICS Fallback for Unknown/Blocked Providers and Slack
Given a recipient clicks the Add to Calendar link from Slack (desktop/mobile) or an unknown/unsupported client When provider detection fails or is blocked Then TimeMeld serves a signed webcal:// subscription by default, with an HTTPS .ics download fallback if webcal is unsupported And The ICS contains UID=meeting.uid, SEQUENCE=current sequence, METHOD:PUBLISH, and PRODID identifying TimeMeld And HTTP headers include Content-Type: text/calendar; charset=utf-8 and Cache-Control: no-store And The link functions on iOS, Android, Windows, and macOS default calendar apps And End-to-end add flow completes in ≤ 2 seconds on broadband p95
Reschedule Auto-Sync via Stable UID and SEQUENCE
Given attendees added the event via a webcal subscription or Apple Calendar using the provided ICS And the meeting is rescheduled in TimeMeld When the client next refreshes the subscription Then the ICS for UID=meeting.uid has SEQUENCE incremented and updated DTSTART/DTEND/TZID And Apple Calendar and Google Calendar (subscribed by URL) reflect the new time within 5 minutes p95 And Conferencing URL remains unchanged and valid And Attendees are not duplicated and reminders persist
Link Signing, Tamper Resistance, and Cross-Surface Usability
Given any provider-specific or ICS fallback link When the token is expired or modified Then the endpoint returns HTTP 410 (gone) for web or an in-app error page with a one-tap request-new-link action And Valid links use an HMAC-SHA256 signature over meetingId, provider, nonce, and expiration; expiration ≤ 30 days And No PII (attendee emails/names) is embedded in the URL; details are resolved server-side post-validation And The same signed URL functions from email, web pages, and Slack without exposing the token in link previews (via no-unfurl meta or redirect) And All redirects complete within 300 ms p95
Timezone Injection, URL Encoding, and DST Edge Cases
Given a meeting in a DST transition window or a half/quarter-hour timezone (e.g., Asia/Kathmandu, Australia/Adelaide) When generating Google, Outlook, Apple, and ICS links Then all links encode start/end using IANA TZID=meeting.timezone (not fixed UTC offsets) And ICS includes a correct VTIMEZONE with transitions covering at least the next 2 years And Device display after add matches the intended local time And No silent UTC conversion occurs without TZID/VTIMEZONE And Titles/descriptions with newlines, commas, ampersands, and emojis are correctly percent-encoded in URLs and UTF-8 in ICS And Automated tests cover ≥ 10 DST transitions and ≥ 5 rare-offset zones
Timezone-Accurate ICS with VTIMEZONE
"As an attendee in a different timezone, I want the event to appear at the correct local time so that I don’t join an hour early or late."
Description

Produce ICS files that include VTIMEZONE components and TZID on DTSTART/DTEND to preserve the organizer’s intended timezone across providers and daylight-saving transitions. Include UTC equivalents for cross-provider consistency and map IANA to Windows timezones for Outlook. Persist the canonical timezone from TimeMeld and convert appropriately for attendees’ local displays without altering the scheduled instant. Outcome: meetings consistently appear at the correct local time, eliminating early/late joins due to DST or parsing differences.

Acceptance Criteria
ICS Exports With VTIMEZONE And TZID
Given an event with organizer timezone set to an IANA zone (e.g., America/Los_Angeles) When an ICS file is generated for the event Then the ICS contains exactly one VTIMEZONE component whose TZID equals the organizer’s timezone And DTSTART and DTEND are expressed with TZID referencing that VTIMEZONE (no floating times) And DTSTAMP and LAST-MODIFIED are UTC values with a trailing Z And the ICS passes RFC 5545 validation with zero errors and zero warnings in the linter
Cross-Provider Time Consistency (Google, Outlook, Apple)
Given two test events scheduled at 2025-03-09 09:00 America/Los_Angeles and 2025-11-02 09:00 America/Los_Angeles When the ICS is imported into Google Calendar (web), Outlook for Windows, Outlook on the web, and Apple Calendar Then each provider displays the local start and end times that correspond to the same UTC instants (0-minute variance) And no provider shows an off-by-one-hour shift or duplicate entries
Windows Timezone Mapping for Outlook
Given an event whose organizer timezone is an IANA zone with a known Windows mapping (e.g., America/New_York → Eastern Standard Time) When generating an ICS intended for Outlook on Windows Then the ICS applies the correct Windows timezone mapping so Outlook displays the correct local time across DST And verification on Outlook for Windows shows the expected local time with 0-minute variance relative to the intended UTC instant
DST Transition Integrity (Spring Forward and Fall Back)
Given an event during the spring-forward gap (e.g., 2025-03-09 02:30 America/Los_Angeles) and an event during the fall-back overlap (e.g., 2025-11-02 01:30 America/Los_Angeles) When ICS files are generated and imported into Google, Outlook (Windows and web), and Apple Calendar Then the spring-forward event is encoded using a roll-forward policy to the next valid local time and displays consistently across providers And the fall-back event resolves to the first occurrence hour using TZID rules and displays consistently across providers And neither event is shifted by ±60 minutes relative to the intended instant
Update Sync via UID and SEQUENCE
Given an event initially distributed via ICS with METHOD:REQUEST and a stable UID When the meeting is rescheduled in TimeMeld Then a new ICS is produced with the same UID and SEQUENCE incremented by 1 And Google Calendar, Outlook (Windows and web), and Apple Calendar update the existing event in place within 2 minutes (no duplicates) And the conferencing link remains unchanged unless explicitly modified in the update And cancellations use METHOD:CANCEL and remove the existing event
Preserve Scheduled Instant With Local Display Conversion
Given attendees in multiple timezones different from the organizer’s timezone When they import the ICS Then each attendee sees the event at their local time that corresponds to the same UTC instant encoded in DTSTART/DTEND (0-minute variance) And the ICS retains the organizer’s canonical timezone via TZID/V.TIMEZONE And changing a device’s timezone after import re-renders the local time while preserving the same UTC instant
Auto-Sync Updates and Cancellations
"As an organizer, I want attendees’ calendars to update automatically when I reschedule or cancel so that no one follows a stale time or link."
Description

Ensure calendar entries stay in sync when meetings move or are canceled. Reuse a stable event UID and increment SEQUENCE in ICS updates; emit METHOD:REQUEST for updates and METHOD:CANCEL for cancellations. Provide a per-event webcal subscription URL to enable background refresh across providers; when connectors are authorized, push updates via Google and Microsoft APIs for faster propagation. Guarantee that conferencing links, times, and titles remain current without attendee action. Outcome: no stale entries or orphaned links on attendee calendars.

Acceptance Criteria
ICS Update: Stable UID and SEQUENCE Increment
Given an attendee added the event via the TimeMeld deeplink When the organizer changes the start time, title, or conferencing link Then TimeMeld issues an ICS update with the same UID And SEQUENCE is increased by exactly 1 relative to the last sent value And METHOD:REQUEST is set and DTSTAMP reflects the update time in UTC And attendees' calendars (Google, Outlook, Apple) show the updated time in their local timezone, updated title, and new conferencing link And no duplicate events are created
ICS Cancellation: METHOD:CANCEL Removes Event
Given attendees previously added the event via the TimeMeld deeplink or webcal subscription When the organizer cancels the meeting in TimeMeld Then TimeMeld emits an ICS with the same UID, incremented SEQUENCE, and METHOD:CANCEL And the VEVENT includes STATUS:CANCELLED And attendee calendars remove the event or mark it as canceled And any conferencing link is no longer accessible from the calendar entry
Webcal Subscription: Background Refresh Publishes Latest State
Given an attendee subscribes to the per-event webcal URL from the deeplink When the organizer changes the meeting details Then a GET on the webcal URL returns an ICS with the same UID and an increased SEQUENCE And the ICS reflects the latest start/end/timezone, title, and conferencing link And HTTP responses include ETag and Last-Modified headers And changes are present on the feed within 60 seconds of the organizer update
Push Connectors: Fast Propagation to Google and Microsoft
Given the host has authorized Google and Microsoft connectors in TimeMeld And attendees include at least one Google Calendar user and one Microsoft 365/Outlook user When the organizer updates or cancels the event Then TimeMeld calls the respective Calendar APIs to update or cancel the event by stable provider event ID And attendee calendars reflect the change within 2 minutes And no duplicate events are created in provider calendars
RSVP State Preserved Across Updates
Given attendees have responded (Accepted, Tentative, or Declined) When TimeMeld sends an update via ICS, webcal, or provider API Then attendee RSVP status remains unchanged on their calendar And only fields changed by the organizer are updated (time, title, conferencing link, description)
Timezone and DST Correctness After Move
Given the original event occurs before a DST transition for at least one attendee timezone When the organizer moves the meeting to after the DST transition Then the ICS includes appropriate VTIMEZONE components for referenced timezones And attendees view the meeting at the correct local wall time after the move And no duplicate all-day or off-by-one-hour artifacts appear
Idempotent Update Delivery
Given an update or cancellation is delivered multiple times due to retries When the same SEQUENCE is processed more than once Then TimeMeld does not create duplicates or regress event fields And only updates with a higher SEQUENCE mutate stored or published event state
Conferencing Link Fidelity
"As a participant, I want the calendar entry to contain a working join link so that I can enter the meeting without hunting for it."
Description

Embed the most current conferencing join details in provider-native fields and the event body. For Google API events, populate conferenceData/hangoutLink; for ICS, set LOCATION to the meeting name and include full join URL, passcodes, and dial-ins in DESCRIPTION. Maintain link integrity during reschedules through the auto-sync pipeline and sanitize content to avoid client stripping. Optimize for mobile deep links and ensure links remain clickable across email clients. Outcome: attendees can join directly from the calendar entry every time.

Acceptance Criteria
Google Calendar Event Uses Native Conferencing Fields
Given a meeting scheduled via TimeMeld into Google Calendar with conferencing details When the event is created through the Google Calendar API Then the event includes conferenceData.hangoutLink for Google Meet OR a primary conferenceData.entryPoints[].uri for the selected provider And events.get returns a non-null native join link And the event description also includes the same join URL, passcode (if any), and at least one E.164 dial-in number And the join link is clickable from Google Calendar on Web and Android/iOS And no duplicate or conflicting join links appear in the event
ICS File Carries Complete Join Details
Given a meeting exported as an ICS from TimeMeld When the ICS is opened in Apple Calendar, Outlook, and Google Calendar Then LOCATION equals the TimeMeld meeting name (<= 255 characters) And DESCRIPTION includes: a labeled primary join URL, passcode, and at least one E.164 dial-in number And DESCRIPTION is plaintext with RFC 5545-compliant line folding (no HTML) And the ICS validates with zero errors/warnings in an RFC 5545 validator And all links are clickable in the resulting calendar entry across those clients
Auto-Sync Maintains Link Fidelity on Reschedule
Given an existing meeting with conferencing details created by TimeMeld When the organizer reschedules the meeting via TimeMeld Then the Google event is updated in place (same event.id) and the ICS keeps the same UID And the primary join URL and passcode remain unchanged And invitees receive an updated invitation reflecting the new time And no additional/duplicate conferencing blocks are appended to DESCRIPTION And the update is published by TimeMeld within 30 seconds of the reschedule action
Mobile Deep Links Resolve to Native Apps
Given a device with the provider’s native app installed (e.g., Zoom, Google Meet, Teams) When the user taps the join link from the calendar entry in Apple Calendar, Google Calendar, or Outlook mobile on iOS 16+ or Android 11+ Then the OS opens the corresponding app and navigates directly to the meeting within 2 seconds And if the app is not installed, the link opens the provider’s HTTPS join page in the default browser And the same link works from the event description and any native join button the client renders
Links Remain Clickable Across Email and Calendar Clients
Given a calendar invitation or update with conferencing details generated by TimeMeld When the invite is viewed in Gmail Web, Outlook Desktop (Windows/macOS), Outlook Web, Apple Mail, and iOS Mail Then the primary join URL renders as a single clickable link (no broken wrapping) And dial-in numbers render as tap-to-dial tel: links on mobile clients And links remain clickable after SafeLinks/URL rewriting where applicable
Content Sanitization Prevents Client Stripping
Given conferencing details provided by an organizer or provider When TimeMeld injects these details into native fields and the event body Then HTML/scripts/unsupported markup are stripped; only plaintext and valid URLs remain And only whitelisted schemes are allowed (https, zoommtg, tel); others are removed And non-essential tracking parameters are removed while preserving join functionality And DESCRIPTION length <= 8,000 characters and LOCATION length <= 255 characters And Google, Outlook, and Apple clients display the join link without stripping or rewriting it
Secure Signed Deeplinks
"As a security-conscious admin, I want add-to-calendar links to be safe and non-shareable beyond the intended recipients so that sensitive meeting details are protected."
Description

Issue tamper-proof, expiring deeplinks that resolve to provider-specific links or ICS. Sign links with HMAC over event ID, attendee hash, and expiry; enforce HTTPS, short TTLs, and scope-limited tokens. Implement rate limiting, revoke on cancel, and avoid PII in query parameters. Log access for auditability and integrate with TimeMeld’s auth and event store. Outcome: only intended recipients can use the link, mitigating leakage and enumeration risks.

Acceptance Criteria
Recipient-Limited Access and Correct Resolution
Given a signed deeplink scoped to event_id E and attendee_hash H, When the intended recipient opens it over HTTPS before expiry, Then the system resolves to the correct provider-specific URL or serves an ICS file that contains the current event start/end time in the recipient’s timezone and the active conferencing link. Given the same deeplink, When opened by a user whose context does not match attendee_hash H (e.g., different authenticated identity or no proof token), Then the system responds 403 Forbidden with a generic error and no event metadata leakage (no title, time, organizer, or location in body or headers).
HMAC Signature Composition and Key Rotation
Given a deeplink, Then its signature is computed as HMAC-SHA256 over the canonical base64url string "event_id.attendee_hash.expiry_epoch" using the active signing key; the link includes parameters: sig (base64url) and kid (key id). When a request is received, Then signature verification is performed in constant time; if kid is unknown or sig invalid, respond 403 and do not redirect or serve ICS. And key rotation is supported by accepting previous keys for a grace period ≤ 48 hours from rotation time; after the grace period, links signed with old kid are rejected with 403.
Tamper Detection and Rejection
Given any modification to event_id, attendee_hash, expiry_epoch, kid, or sig, When the link is requested, Then the system responds 403 Forbidden with a generic message, and no redirect or ICS content is returned. And an audit_log entry is created with fields: event_id_hash, attendee_hash, token_id_hash (if present), outcome="tamper_detected", request_id, ip_hash, user_agent_hash, and timestamp.
Expiry Enforcement with Short TTL
Given a signed deeplink with TTL ≤ 24h (system default 6h), When it is requested after expiry_epoch, Then the system returns 410 Gone with a non-identifying message and no redirect or ICS content; audit outcome="expired" is recorded. When requested before expiry, Then the response includes Cache-Control: no-store and Pragma: no-cache, and the API does not reveal remaining TTL in body or headers beyond standard HTTP caching controls.
Revocation on Cancel and Correct Reschedule Behavior
Given an event E is cancelled in TimeMeld, When any previously issued deeplink for E is requested, Then respond 410 Gone; audit outcome="revoked", reason="cancelled" is recorded. Given an event E is rescheduled, When a previously issued valid deeplink for E is requested before its expiry, Then it resolves to the updated provider-specific URL or ICS reflecting the new time and conferencing details; the signature remains valid because it excludes mutable fields such as start time.
Rate Limiting and Enumeration Mitigation
Given repeated requests to the same deeplink token or enumeration attempts (varying sig/kid/event_id) from a single IP or /24, When thresholds exceed 10 requests per minute per token and 100 requests per hour per IP range, Then subsequent requests receive 429 Too Many Requests with a Retry-After header; no redirect or ICS content is served. And after 3 threshold breaches within 15 minutes, Then a temporary block of 15 minutes is applied to the token and IP range; audit outcome="rate_limited" with counters recorded; legitimate requests after cooldown succeed if otherwise valid.
Privacy-Preserving URLs, HTTPS-Only, and Allowlisted Redirects
Given any generated deeplink, Then the URL path and query parameters MUST NOT contain raw PII (e.g., email, name); only opaque identifiers and hashes using base64url without padding are permitted. And all accesses must occur over HTTPS; HSTS header max-age ≥ 6 months is set; HTTP requests are rejected or 301 to HTTPS before any verification occurs; no mixed-content redirects are allowed. And redirect destinations are restricted to an allowlist of provider domains (Google Calendar, Microsoft Outlook/Office, Apple Calendar endpoints); if the resolved destination is not on the allowlist, Then respond 400 Bad Request and do not redirect. And access and audit logs store only hashed identifiers and minimal metadata (timestamps, outcome, ip_hash, request_id); no raw IPs, emails, titles, or times are logged.
Device and Provider Auto-Detection UI
"As an attendee opening the invite on my phone, I want the right calendar option preselected so that adding the event takes one tap."
Description

Detect user device/OS and likely calendar provider to surface the most relevant one-tap option with graceful fallback. For iOS/Safari prefer .ics, for Android/Chrome prefer Google intent, for Outlook users present Outlook web/desktop options. Provide accessible, localized buttons usable in email, web embeds, and Slack messages with ARIA labels and keyboard support. Track click-through and completion to inform UX. Outcome: a streamlined, one-tap experience that minimizes friction across contexts.

Acceptance Criteria
iOS Safari one-tap Apple Calendar via webcal with auto-sync
Given a recipient opens the invite email on iOS and taps the Add to Calendar CTA When device/OS detection identifies iOS with Safari Then the primary option shown is "Add to Apple Calendar" And the link uses the webcal:// scheme to an ICS feed with a stable UID for the event And the event data includes correct IANA timezone, title, description, conferencing link, location, organizer, and alarms (if configured) And tapping opens the Apple Calendar subscribe/add flow and adds the event on confirmation And subsequent changes to the source event auto-sync to the subscribed event within 5 minutes of publication And if webcal is unsupported, the fallback .ics download with the same UID and fields is initiated
Android Chrome one-tap Google Calendar with intent and web fallback
Given a recipient on Android using Chrome taps Add to Calendar When detection identifies Android + Chrome Then the primary option shown is "Add to Google Calendar" And tapping attempts to launch the Google Calendar app via an intent targeting package com.google.android.calendar with prefilled title, description (including conferencing link), location, start/end in the event timezone And if the intent cannot be resolved, it falls back to the Google Calendar web URL (render?action=TEMPLATE) with the same fields encoded And a secondary "Subscribe for updates" option is offered using a GCal URL with a cid pointing to the event's webcal ICS; if chosen, subsequent event changes appear in Google Calendar within 10 minutes And if neither the app nor web is available, an .ics fallback is provided
Outlook users see Desktop and Web options with graceful fallback
Given a recipient is on Windows or user-agent indicates Outlook usage When the user taps Add to Calendar Then the UI presents two prominent options: "Outlook Desktop" and "Outlook Web" And selecting Outlook Desktop opens the system handler for .ics (or ms-outlook:// if available) with the event containing correct timezone, conferencing link, and a stable UID And selecting Outlook Web opens the Outlook/Office web compose/add flow with the same details prefilled And a "Subscribe to updates" option is available where supported (internet calendar), ensuring future changes sync within 10 minutes And if the Desktop handler is unavailable, clicking it falls back to the Outlook Web option without error
Cross-context rendering in Email, Web Embed, and Slack
Given the Add to Calendar CTA is included in an email When viewed in major clients (Gmail web, Outlook desktop, Apple Mail) Then a single primary button renders with a tappable area ≥ 44x44 dp and links to a detection landing page with no client-blocked scripts required Given the component is embedded on the web When the page loads Then the correct primary provider button appears within 300 ms with a visible secondary list for other providers and .ics fallback Given a TimeMeld link is posted in Slack When Slack unfurls the link Then a Block Kit message displays provider buttons (Google, Outlook, Apple/.ics) and clicking opens the detection landing page with the detected provider preselected
Keyboard-accessible, screen-reader-friendly buttons (WCAG 2.2 AA)
Given the Add to Calendar UI is rendered on the web When a user navigates using keyboard only Then all interactive elements are reachable in logical order, have visible focus indicators, and activate via Enter and Space And each button has an aria-label that includes the provider and meeting title (e.g., "Add to Google Calendar: Sprint Review") And roles/states are semantically correct (role="button", aria-pressed only when applicable) And color contrast for text and icons on buttons is ≥ 4.5:1 and target size is ≥ 44x44 px And screen readers announce focus and action without redundant or missing information
Localized labels and date/time with RTL support
Given a locale is provided (e.g., es-ES, fr-FR, ar) When the Add to Calendar UI renders Then button labels and helper text are translated for the locale, and date/time formats reflect the locale conventions And the timezone abbreviation/name remains accurate while localized where applicable And right-to-left locales render with dir="rtl", mirrored layout, and correct reading order And if a translation is missing, content gracefully falls back to English without broken placeholders And the same locale is applied consistently in email, web embed, and Slack contexts
Click-through and completion telemetry
Given the Add to Calendar UI is shown in any context (email landing, web, Slack) When the component is displayed, a provider button is clicked, a deep link is launched, or an add/import completes Then analytics events are emitted for view, click, launch, and completion with fields: feature_id, requirement_id, provider, platform, context, locale, detection_confidence, outcome, meeting_id_hash, timestamp And events exclude personal content (no titles/descriptions beyond hashed IDs) and respect user consent/opt-out And ≥ 95% of events are delivered within 60 seconds with retry-once behavior for transient failures And telemetry can be segmented by context and provider to compute click-through and completion rates

Smart Nudges

Localized reminders scheduled to the guest’s day (e.g., 24h/1h/10m before) with a single “Join Now” button and backup dial‑in. Reduces no‑shows and last‑minute confusion, while keeping reminders respectful of local hours.

Requirements

Local Time & Quiet Hours Compliance
"As an organizer, I want reminders to respect each attendee’s local hours so that nudges are helpful, not intrusive."
Description

Detect and persist each attendee’s local timezone from calendar metadata, invite headers, IP/locale hints, or explicit user settings, with full daylight‑saving awareness. Apply organizer‑defined quiet‑hours policies (e.g., do not send between 21:00–07:00 local) so reminders are automatically shifted to the nearest permissible window without violating the intended offsets (24h/1h/10m relative to the attendee’s local start time). Provide conflict handling for last‑minute meetings (e.g., if 1h falls in quiet hours, choose the nearest earlier permissible send). Expose controls at workspace, team, and event level; allow per‑attendee overrides when consented. Include a preview timeline that visualizes planned send times across timezones before scheduling. Log timezone resolution, policy decisions, and final send times for auditability. Fallback gracefully when timezone is unknown by defaulting to organizer’s policy or prompting for confirmation. Ensure compliance with regional privacy regulations and respect user notification preferences.

Acceptance Criteria
Timezone Resolution & DST Persistence
Given an attendee has an explicit timezone setting, When reminders are scheduled, Then the explicit setting is used and persisted with source=UserSetting and confidence=High. Given multiple timezone signals (CalendarMetadata, InviteHeader, Locale, IP) and no explicit setting, When resolving timezone, Then the system selects the highest-precedence source using the order UserSetting > CalendarMetadata > InviteHeader > Locale > IP and persists the chosen timezone with source and confidence. Given an event spans a daylight-saving transition for the attendee’s resolved timezone, When computing 24h/1h/10m reminders, Then send times align to the attendee’s local wall‑clock times accounting for DST shift (no 1-hour drift). Given a timezone has been persisted for an attendee, When the attendee is invited to a new event, Then the persisted timezone is reused unless an explicit override is provided.
Quiet Hours Application & Conflict Resolution
Given organizer quiet hours are 21:00–07:00 local and an attendee’s meeting is at 14:00 local, When computing 24h/1h/10m reminders, Then 24h=previous day 14:00, 1h=13:00, and 10m=13:50 (no sends during quiet hours). Given organizer quiet hours are 21:00–07:00 local and a meeting is at 07:30 local, When computing the 1h and 10m reminders, Then 1h (06:30) and 10m (07:20) are evaluated against quiet hours and any that fall within are shifted to the nearest earlier permissible time (e.g., boundary 21:00 previous day) and logged with shift_reason=quiet_hours. Given a computed nearest earlier permissible time is in the past relative to scheduling, When evaluating a reminder, Then the reminder is suppressed (not sent) and logged with outcome=suppressed and reason=quiet_hours_past. Given multiple reminders are shifted due to quiet hours, When finalizing the schedule, Then no duplicate send times are produced for the same attendee and event.
Granular Policy Controls & Per-Attendee Overrides
Given workspace-, team-, and event-level quiet-hours policies exist, When policies conflict, Then precedence is PerAttendeeOverride > Event > Team > Workspace. Given an organizer enables a per-attendee override with the attendee’s consent recorded, When computing reminders for that attendee, Then the override window is applied and consent metadata (who/when/method) is persisted. Given a policy is updated at any scope, When the organizer saves changes, Then all planned send times are recalculated within 5 seconds and the preview reflects the new schedule. Given an attendee has override quiet hours 22:00–06:00 and the team policy is 21:00–07:00, When reminders are computed, Then that attendee’s reminders respect 22:00–06:00 while others follow 21:00–07:00.
Preview Timeline Visualization Across Timezones
Given an event with attendees across multiple timezones, When the organizer opens the preview timeline, Then each attendee row shows 24h/1h/10m planned send timestamps in the attendee’s local time with quiet-hour periods visually indicated. Given any reminder is shifted due to quiet hours or conflicts, When viewing the preview, Then the item is marked as shifted and a tooltip reveals original_intended_time and shift_reason. Given the organizer changes a policy (e.g., quiet hours or overrides), When viewing the preview, Then the timeline updates to reflect new send times within 1 second without page reload. Given an attendee’s timezone is changed, When refreshing the preview, Then all displayed send times recalculate to the new local timezone.
Audit Logging of Timezone & Policy Decisions
Given reminders are computed, When logging the schedule, Then each planned send entry records event_id, attendee_id, resolved_timezone (IANA), source, confidence, dst_applied (boolean), intended_send_time, quiet_hours_window, final_send_time, shift_reason (if any), applied_policies (workspace/team/event/override IDs), and decision_timestamp (ISO 8601). Given an organizer reviews logs for an event, When filtering by attendee or date range, Then only matching log entries are returned and can be exported as CSV. Given access controls are enforced, When a non-authorized user requests audit logs, Then access is denied and the attempt is logged with reason=forbidden.
Fallback Behavior When Timezone Unknown
Given no timezone can be resolved from user settings, calendar metadata, invite headers, locale, or IP, When scheduling reminders, Then the system either prompts the organizer to confirm a timezone for the attendee or defaults to the organizer’s policy/timezone as configured. Given fallback to organizer’s policy/timezone is applied, When computing reminders, Then quiet hours and offsets are applied using that timezone and the decision is logged with fallback=true and fallback_source=OrganizerPolicy. Given the organizer later sets a definitive attendee timezone, When the change is saved, Then all future planned sends are recalculated to the attendee’s local time and prior fallback entries remain in the audit log.
Privacy Compliance & Notification Preference Respect
Given an attendee has opted out of reminders or disabled a notification channel, When scheduling sends, Then no reminders are sent to that attendee/channel and the suppression is logged with reason=opt_out. Given regional privacy constraints (e.g., GDPR), When deriving timezone from IP/locale, Then raw IP data is not persisted beyond derivation; only the resolved timezone and source=IP are stored, and data processing is recorded for audit. Given per-attendee overrides require consent, When an override is enabled without recorded consent, Then the system blocks the change and surfaces an error requiring consent capture. Given role-based access controls, When viewing timezone, preferences, or audit data, Then only authorized roles can access it, and access events are logged.
Multi‑Stage Reminder Orchestration (24h/1h/10m)
"As an organizer, I want a reliable sequence of reminders at 24h, 1h, and 10m so that invitees are prepared and on time."
Description

Provide a rules‑driven scheduler that attaches to each event and generates reminder jobs at 24h, 1h, and 10m relative to each attendee’s local start time. Support enabling/disabling stages per event, plus custom offsets when allowed by policy. Ensure idempotency (no duplicate sends) and automatic cancellation of pending reminders when the meeting is cancelled or after the attendee joins. Handle reschedules by recalculating offsets and migrating queued jobs. Allow conditional logic (e.g., skip 24h if invite sent <24h prior; suppress 10m if the attendee has joined the waiting room). Include retry/backoff for transient delivery errors and a kill‑switch to halt all reminders for an event. Expose orchestration state to the UI with per‑attendee status and next scheduled send.

Acceptance Criteria
Local-Time Scheduling with Stage Toggles and Custom Offsets
Given an event with attendees each having a known time zone When orchestration initializes for the event Then reminder jobs are queued at T-24h, T-1h, and T-10m in each attendee’s local time, honoring DST boundaries Given one or more reminder stages are disabled at the event level When orchestration queues jobs Then only enabled stages are queued per attendee and disabled stages are not scheduled Given custom offsets are configured and allowed by policy When orchestration runs Then jobs are queued at the configured offsets for each attendee instead of the defaults
Idempotent Delivery and Job Deduplication
Given the same reminder stage is triggered multiple times due to retries or duplicate events When the system attempts to send the reminder Then exactly one reminder per attendee per stage is delivered and duplicates are suppressed using a stable idempotency key Given duplicate scheduled jobs exist for the same attendee and stage When execution occurs Then the duplicates are detected and only a single job is processed
Cancellation and Kill-Switch Suppression
Given an event is canceled When the cancellation signal is received Then all pending reminder jobs for the event are canceled within 30 seconds and no further reminders are sent Given the event-level kill-switch is activated When scheduling or sending a reminder Then all pending and future reminders for that event are halted and no messages are delivered Given an attendee joins the meeting prior to pending reminder stages When join is detected Then all future reminder stages for that attendee are canceled
Reschedule Recalculation and Job Migration
Given an event start time is changed When the reschedule is saved Then queued jobs are recalculated relative to the new start time for each attendee and migrated without duplicate sends Given a reminder stage has already been sent before the reschedule When recalculation runs Then already-sent stages are not re-sent and only remaining stages are scheduled Given the reschedule causes a change in local DST or time zone offset for an attendee When jobs are recalculated Then new job times reflect correct local offsets at T-24h, T-1h, and T-10m
Conditional Skips: Late Invites and Waiting Room Presence
Given the initial invite is sent less than 24 hours before the event start When determining which stages to schedule Then the 24h reminder is not queued for that attendee Given an attendee is detected in the waiting room within 15 minutes of the start time When the 10m reminder would be sent Then the 10m reminder is suppressed for that attendee
Retry and Backoff Handling for Transient Failures
Given a transient delivery error occurs (e.g., 429, 5xx, or network timeout) When sending a reminder Then the system retries using exponential backoff with jitter up to the configured maximum attempts Given a non-retryable error occurs (e.g., invalid recipient or policy rejection) When sending Then no retries are attempted and the attempt is marked failed with a diagnostic reason Given the maximum retry attempts are exhausted without success When the retry policy completes Then the send is marked failed and no further attempts are scheduled
UI Exposure of Orchestration State Per Attendee
Given an event with orchestrated reminders When viewing the event in the UI Then each attendee shows current stage statuses (Pending, Sent, Skipped, Failed) and the next scheduled send timestamp, and whether the event kill-switch is active Given an orchestration state change occurs (send success/failure, cancel, reschedule, attendee join) When the change is processed Then the UI reflects the update within 60 seconds
Smart Channel Selection & Fallback Delivery
"As an invitee, I want reminders delivered on the channel I actually see so that I don’t miss the meeting."
Description

Deliver nudges over the most effective channel per attendee (email, SMS, Slack, or mobile push when available) based on known reachability, user preferences, and past engagement. Implement a channel ranking model with rules/weights (e.g., use SMS only for final 10m nudge if consented; prefer Slack for internal attendees). Validate contactability (phone verified, Slack DM permitted, push token active) before scheduling. On send failures or low‑confidence channels, automatically fall back to the next best channel within the same nudge window. Enforce rate limits and frequency caps to prevent notification fatigue. Provide opt‑in/opt‑out management, sender identity configuration, and compliance with carrier and messaging regulations. Expose delivery outcome telemetry for each channel to inform future selection.

Acceptance Criteria
Internal Attendee: Slack-First Delivery with Contactability Validation
Given the attendee is marked as internal to the organization And Slack direct messages are permitted for the attendee And the attendee has not opted out of Slack And Slack contactability check passes (permission=true, last DM receipt < 14 days) And channel ranking rules for internal attendees are Slack > Push > Email, with SMS disallowed except for 10m nudges When a 1-hour-before nudge is scheduled for this attendee Then Slack is selected as the primary delivery channel for this nudge And SMS is marked ineligible for this nudge And the system records channel eligibility and selection reasons in telemetry
SMS Only Eligible for Final 10-Minute Nudge with Explicit Consent
Given a nudge is scheduled 24 hours before the meeting Or a nudge is scheduled 1 hour before the meeting Then SMS is marked ineligible regardless of phone status or consent Given a nudge is scheduled 10 minutes before the meeting And the attendee’s phone number is verified And the attendee has explicitly opted in to SMS And per-channel frequency caps are not exceeded And sending is permitted for the attendee’s locale and carrier Then SMS is marked eligible for selection for this nudge And if SMS is not selected, the reason is logged (e.g., ranking, preference)
Automatic Fallback on Primary Channel Failure Within Nudge Window
Given a nudge has a selected primary channel and at least one eligible fallback channel And the primary channel send attempt fails (non-2xx provider response or no delivery acknowledgment within 60 seconds) When the failure is detected Then the system initiates delivery via the next-highest ranked eligible channel within 60 seconds And ensures only one successful delivery is recorded for the nudge (idempotency) And records the fallback attempt, timing, and final outcome in telemetry
Low-Confidence Channel Handling and Backup Scheduling
Given the channel ranking model returns a predicted engagement probability below 0.35 for the top-ranked eligible channel When scheduling the nudge Then the system selects the highest-ranked eligible channel with predicted engagement ≥ 0.35 And if no eligible channel meets the threshold, the system schedules a backup fallback attempt to the next-best eligible channel 60 seconds after the primary if no open/click/read/delivered event is observed And the selection rationale "low_confidence" is recorded in telemetry
Sender Identity Configuration and Regulatory Compliance Enforcement
Given organization-level sender identities are configured (email From name/domain, SMS brand/campaign or sender ID, Slack bot app, push app credentials) And per-channel compliance requirements are active (e.g., email DMARC alignment, SMS opt-in and STOP/HELP copy, Slack DM permission, push token validity) When a nudge is sent on any channel Then the message uses the configured sender identity for that channel And any channel failing configuration or compliance checks is marked ineligible and not used for delivery And the compliance status and any rejection reasons are logged in telemetry
Rate Limits and Frequency Caps Across Channels
Given default caps are configured as: max 3 nudges per attendee per event, minimum 30 minutes between nudges, and max 1 SMS per attendee per event When scheduling a nudge that would exceed any cap Then the nudge is not sent And the system records a suppressed event with reason "rate_limited" including the violated cap And no fallback attempts are triggered for suppressed nudges
Delivery Outcome Telemetry Exposed and Feeds Channel Ranking
Given delivery attempts occur for a nudge across one or more channels When telemetry is generated Then for each attempt the system records: attendee_id, meeting_id, nudge_type (24h/1h/10m), channel, eligibility flags, selection reason, send_timestamp, delivery_status, provider error_code (if any), engagement event (open/click/read), fallback_used, final_outcome, and latency_ms And the telemetry is available via API and admin console within 60 seconds of the attempt And a daily job updates per-attendee per-channel engagement scores using the last 30 days of telemetry And subsequent nudges for that attendee use the updated scores in channel ranking and record the version of the scoring data used
One‑Tap Join with Backup Dial‑In
"As an invitee, I want a single join button and a dial‑in fallback so that I can get into the meeting quickly from any device."
Description

Embed a context‑aware “Join Now” action in every nudge that deep‑links directly to the meeting provider (Zoom, Google Meet, Teams, etc.) using the canonical URL from the calendar event. Detect device and client capabilities to choose the best target (native app vs. browser) and gracefully degrade to web if the app is unavailable. Include localized backup dial‑in details (country‑specific access numbers, PIN/meeting ID) and a single‑tap dial string on mobile. Provide copy‑to‑clipboard actions and fail‑safe text formatting to avoid link corruption by email or SMS clients. Support authenticated join when possible and warn on potential phishing risks by displaying verified meeting metadata (host, title, start time).

Acceptance Criteria
Context-Aware One‑Tap Join Target Selection
- Given a device with a provider’s native app installed and enabled When the user taps "Join Now" Then the native app opens directly to the meeting within 2 seconds of tap - Given a device without the provider’s native app or with deep links unsupported When the user taps "Join Now" Then the meeting opens in the default browser using the provider’s web join URL - Given app detection takes longer than 1500 ms or fails When the user taps "Join Now" Then the system automatically falls back to the browser URL and logs a fallback event - Given desktop and mobile form factors When capability detection runs Then the selected target (app vs. web) is recorded in analytics with device type and provider
Canonical Deep Link Resolution Across Providers
- Given a calendar event with structured conferencing metadata (Zoom/Meet/Teams) When "Join Now" is tapped Then the opened URL exactly matches the canonical URL from the event’s conferencing field - Given multiple URLs exist in the event body When rendering the nudge Then the system prioritizes the structured canonical URL over free‑text links - Given a recurring meeting with occurrence‑specific links When "Join Now" is tapped for a specific instance Then the link resolves to that instance’s canonical URL - Given the event lacks a valid canonical URL When "Join Now" is tapped Then a non‑blocking error message is shown and backup dial‑in is elevated as the primary action
Localized Backup Dial‑In With Single‑Tap String
- Given the guest’s country can be inferred from locale, time zone, or phone When the nudge is generated Then the country‑specific access number is selected and displayed with country label - Given the device is mobile When the dial option is presented Then a single‑tap tel link is constructed with required pauses and separators for the provider (e.g., tel:+1XXXXXXXXXX,,<MeetingID>#,,<PIN>#) and successfully reaches the IVR join flow in smoke tests - Given no local access number exists for the guest’s country When the nudge is generated Then the nearest regional number is used and a short note indicates the region - Given the user taps "Copy Dial‑In" When copied to clipboard Then the number, meeting ID, and PIN are included with locale‑appropriate formatting and without line breaks that break dialing - Given the nudge is sent via email or SMS When rendered Then comma pauses and hash characters in the dial string are preserved and remain tappable/clickable
Authenticated Join and Phishing‑Safe Metadata Display
- Given the provider supports authenticated/SSO join and the user has an active session When the user taps "Join Now" Then an authenticated join URL is used and the provider indicates an authenticated session without prompting for credentials - Given verified meeting metadata (host, title, start time) from the calendar event When the nudge is displayed Then these fields are shown above the button and match the event values exactly - Given the join URL domain is not in the allowlist of recognized providers When rendering the nudge Then a phishing warning banner is displayed and a confirm step is required before opening the link - Given screen readers are used When focusing on the metadata and button Then accessible labels announce host, title, start time, and provider name
Fail‑Safe Link and Dial Formatting Across Channels
- Given major email clients (Gmail, Outlook, Apple Mail) and SMS clients (iMessage, Android Messages) When the nudge is received Then the "Join Now" button remains clickable and the URL is not truncated or altered by smart quotes or auto‑linking - Given long provider URLs with query parameters When embedded Then they are wrapped only at safe breakpoints without inserting spaces or zero‑width characters into the URL - Given tracking/redirect requirements When enabled Then only a trusted timemeld.io redirect is used and it preserves the full canonical URL and parameters, with the final destination restricted to an allowlisted provider domain
One‑Tap Copy to Clipboard for Link and Dial‑In
- Given the nudge displays copy actions When the user taps "Copy Join Link" Then the canonical join URL is placed on the clipboard exactly as used by the button and a confirmation toast appears within 1 second - Given the user taps "Copy Dial‑In" When copied Then the clipboard contains the access number, meeting ID, and PIN on a single line suitable for pasting into dialers - Given the clipboard write fails due to permissions When the user taps a copy action Then a fallback modal shows the content with a manual "Select All" affordance
Graceful Degradation and Error Recovery
- Given app launch is attempted and fails to foreground within 3 seconds When "Join Now" was tapped Then the system automatically opens the browser URL and surfaces a brief "Opened in browser" notice - Given both app and browser open are blocked (e.g., corporate policy) When "Join Now" is tapped Then a modal displays the raw URL and dial‑in details with copy actions so the user can join manually - Given any failure path is taken When the nudge flow completes Then an error event with device, provider, and failure reason is logged for diagnostics
Personalized & Localized Nudge Content
"As an invitee, I want reminders in my language and local time format so that details are clear and actionable."
Description

Generate concise, human‑friendly reminder content that includes attendee name, organizer, agenda snippet, and the attendee’s local start time in their preferred format (12/24‑hour). Provide full i18n support with automatic language selection from user preferences or locale, and allow organizers to override per event. Maintain brand‑consistent templates with variable placeholders and conditional sections (e.g., show dial‑in only where available). Support A/B variants for subject lines and copy, with preview across channels and languages. Append minimally invasive tracking for opens/clicks where permitted. Ensure accessibility (readable text length, contrast, alt text) and deliver channel‑optimized payloads (SMS length limits, Slack blocks, email HTML/text).

Acceptance Criteria
Auto language selection with per-event override
Given an attendee has a saved language preference, When a nudge is generated, Then the subject and body are localized to that language. Given no saved preference, When locale is detected from the attendee profile or invite address, Then the subject and body are localized to that locale’s language. Given the organizer sets a per-event language override, When the nudge is generated, Then the override language is used regardless of attendee preference. Given an unsupported language is selected, When the nudge is generated, Then content falls back to English and the fallback is logged. Then all system labels, dates, and connectors use the same language within the message.
Local time display in attendee’s preferred 12/24‑hour format
Given an attendee’s timezone and hour-format preference are known, When rendering the nudge, Then the start time is displayed in the attendee’s local timezone and preferred 12/24-hour format. Then the local date and day-of-week are included where channel length allows, and the time includes the correct DST adjustment for the event date. Then no UTC or organizer time is shown unless explicitly configured, and no ambiguous times are displayed. Then numeric formatting (AM/PM vs 24h) matches the attendee’s preference across subject and body.
Template rendering with placeholders and conditional sections
Given a brand-consistent template with placeholders {attendee_name}, {organizer_name}, {agenda_snippet}, {local_start_time}, {join_url}, {dial_in}, When rendering, Then all placeholders are resolved with event data and no literal placeholders appear. Then the “Join Now” CTA is present and links to {join_url} in all channels that support buttons/links. Then the dial-in section is included only when {dial_in} is available; otherwise it is omitted with no empty headers or extra spacing. Then messages render without HTML/CSS errors (email) and without JSON/schema errors (Slack blocks).
A/B variants for subject lines and copy
Given variants A and B are configured for subject and/or body, When sending to N eligible recipients, Then recipients are allocated A/B in a 50/50 split with a tolerance of ±5%. Then each sent message records the variant identifier in metadata for analytics. Then both variants include the required fields (attendee name, organizer, agenda snippet, local start time, “Join Now” link) and share the same language and time formatting rules. Given variant B is disabled or incomplete, When sending, Then all recipients receive variant A.
Cross-channel, multi-language preview
Given an organizer selects a language and channel in the preview, When preview is generated, Then it renders exactly the text/blocks/HTML that will be sent for that combination, with sample data resolving all placeholders. Then SMS preview displays the estimated segment count for GSM-7 vs UCS-2 and warns if limits will be exceeded. Then Slack preview validates Block Kit against API limits and shows any truncation. Then Email preview provides both HTML and plain-text views and reports missing alt text, if any.
Consent‑aware open/click tracking
Given workspace and recipient tracking permissions are known, When generating the message, Then open tracking is added only to email and only if permitted; click tracking is added as wrapped links only if permitted. Then no tracking parameters or pixels are added when permission is not granted or region policy forbids it, and the send is not blocked. Then tracked links use the branded redirect domain and preserve UTM parameters. Then send, open, and click events are recorded with message ID and variant ID when tracking is active.
Accessibility and channel‑optimized payloads
Email: Then HTML meets WCAG 2.1 AA color contrast; base font size is at least 16px; images include alt text; and the “Join Now” link has an accessible name. SMS: Then the message fits within 2 segments for GSM-7 (≤306 chars) or 2 segments for UCS-2 (≤134 chars); if longer, the body is truncated with an ellipsis and a fallback URL to full details. Slack: Then the message uses Block Kit with ≤50 blocks and ≤3000 characters per text block; includes a primary “Join Now” button; and includes a plain-text fallback section.
Attendance Signals & Nudge Suppression
"As an organizer, I want insight into which nudges were seen and to suppress further reminders after joining so that we avoid noise and learn what works."
Description

Capture and correlate engagement signals (open, click, join, decline) from all channels and meeting providers to infer attendance state in near‑real time. When an attendee has joined or explicitly declined, automatically suppress remaining reminders for that attendee while leaving others unaffected. Feed aggregated metrics (send, delivery, engagement, attendance rate, no‑show rate) back into TimeMeld’s analytics and scheduling heuristics. Provide organizer‑visible dashboards and per‑event reports. Offer webhook/exports for downstream systems. Implement strict privacy controls, retention policies, and deduplication to avoid double‑counting across channels/devices.

Acceptance Criteria
Suppress reminders upon join event
- Given an attendee is on the invite for a scheduled event with Smart Nudges enabled - When a join signal is received from any supported meeting provider or a Join Now click results in a confirmed session start - Then suppress all remaining reminders for that attendee for that event within 5 seconds p95 and 15 seconds p99 - And do not modify other attendees’ reminder schedules - And record a suppression audit entry with event_id, attendee_id, provider/channel, timestamp, reason="joined", dedupe_key - And reflect the attendee state as "Joined" on organizer dashboards within 15 seconds p95 - And process repeated join signals idempotently (no duplicate suppressions or counts)
Suppress reminders upon explicit decline
- Given an attendee explicitly declines via any channel (email decline link, SMS reply keyword, or calendar RSVP = Declined) - When the decline signal is ingested and verified - Then suppress all remaining reminders for that attendee for that event within 5 seconds p95 - And mark the attendee state as "Declined" on dashboards and reports - And exclude the attendee from no-show rate calculations while including in invitee counts - And emit a suppression_applied event with reason="declined"
Cross-channel deduplication of engagement and attendance signals
- Given multiple engagement signals for the same attendee, event, and nudge instance across channels/devices - When deduplication is applied using idempotency keys (event_id + attendee_id + nudge_id + action_type) - Then count at most one of each action_type per nudge instance per attendee in analytics - And treat parallel "Join Now" link success and dial-in bridge connect within 2 minutes as a single attendance - And process webhook retries idempotently using the same keys - And keep false-duplicate rate under 0.1% over 10k events in validation tests
Organizer dashboards and per-event reports show real-time metrics
- Given an organizer opens the per-event report or dashboard - When the page loads or auto-refreshes every 15 seconds - Then display metrics: sends, deliveries, bounces, opens, clicks, joins, declines, attendance rate, no-show rate - And allow filtering by channel, role (organizer/guest), and timezone - And show per-attendee state (Pending, Joined, Declined, No-show) with last signal timestamp - And provide CSV export that matches on-screen totals within 0.5% variance - And reflect new signals within 15 seconds p95 of ingestion
Reliable webhooks and exports for downstream systems
- Given a tenant configures a webhook endpoint with a shared secret - When events of types send, delivery, open, click, join, decline, suppression_applied, attendance_state_change occur - Then deliver JSON webhooks signed with HMAC-SHA256 within 60 seconds p95 and retry for up to 24 hours with exponential backoff on non-2xx responses - And include idempotency_key to enable consumer deduplication - And provide a replay endpoint to re-send events by time range and type - And support bulk exports via API/CSV for a date range with schema versioning and gzip compression
Privacy controls and data retention for signals
- Given tenant privacy settings and default system policies - When storing engagement and attendance events - Then store only minimal metadata (event_id, attendee_id hash, timestamps, channel, action_type, provider) and never store message body content - And encrypt data in transit (TLS 1.2+) and at rest (AES-256) - And enforce role-based access so only organizers and admins of the event’s tenant can view per-attendee states - And honor configured retention: raw events purged after 30 days by default (configurable 7–90), aggregated metrics retained 12 months, with deletion executed within 7 days of request - And provide per-attendee per-event purge that cascades to exports and webhook replays
Aggregated metrics power scheduling heuristics
- Given TimeMeld’s scheduling heuristics consume attendance aggregates - When daily rollups are generated at 01:30 UTC and updated incrementally in near real time - Then produce aggregates by timezone window, weekday, role, channel, and meeting type with definitions documented - And exclude declined attendees from no-show rates and include joined attendees regardless of join channel - And expose aggregates via an internal API with p95 query latency under 300 ms and availability 99.9% monthly - And version metric schemas to allow backward-compatible evolution

Join Precheck

A quick pre‑join diagnostic that tests mic/camera/network and preloads the conferencing token so guests enter cleanly. Offers a fallback join path if something fails, minimizing awkward “can you hear me?” starts.

Requirements

Device Diagnostics & Permissions
"As a remote participant, I want to confirm my mic, speakers, and camera work and have the right permissions so that I can join without audio/video issues."
Description

Implement a pre-join hardware check that verifies microphone input (with visual level meter and loopback playback), speaker output (test tone), and camera preview, including device enumeration and selection. Handle browser permission prompts gracefully, detect blocked devices, and provide clear remediation steps (e.g., enable permissions, select a different device). Persist last-known device choices per user/browser while supporting one-click re-test. Gate the “Join” action behind at least one valid audio path or provide a warned bypass. Ensure cross-browser support (Chromium, Firefox, Safari), timeouts for hung device calls, and robust error messaging integrated into TimeMeld’s pre-join flow.

Acceptance Criteria
Mic Input Check with Level Meter and Loopback
Given the user is on the Join Precheck screen When they click "Test Microphone" Then getUserMedia({ audio: true }) is invoked within 300ms and any browser permission prompt is surfaced Given microphone permission is granted When the mic stream starts Then a level meter renders and updates at ≥10 fps and shows non-zero level when the user speaks and near-zero when silent Given loopback is enabled When the user records a 3-second sample and stops Then playback begins within 1.5s through the selected output and completes without error Given no audio energy above threshold is detected for 5s after stream start When the user remains on the mic test step Then a warning appears with remediation steps and a visible "Retry" control Given the mic request hangs When getUserMedia does not resolve in 5s Then the request is aborted and a timeout error with retry is shown Given multiple microphones are available When the user selects a different microphone Then the input stream switches within 1s and the meter reflects the new source while the previous track is stopped
Speaker Output Test Tone and Device Selection
Given the user is on the Join Precheck screen When they click "Test Speaker" Then a 2-second test tone plays and the UI shows a playing state Given the browser supports setSinkId When the user selects a specific output device Then subsequent playback uses that device and the selection is reflected in the UI Given the browser does not support setSinkId When the user views output options Then the UI indicates output selection is not supported and uses the system default Given autoplay is blocked When the user clicks "Enable Sound" Then the test tone plays successfully Given playback fails (e.g., NotAllowedError, NotFoundError) When the test is triggered Then an error message with remediation and a "Retry" control is displayed
Camera Preview and Selection
Given the user is on the Join Precheck screen When they click "Enable Camera" Then getUserMedia({ video: true }) is invoked within 300ms and any browser permission prompt is surfaced Given camera permission is granted When the video stream starts Then a live preview renders at a minimum of 640x360 within 1.5s Given multiple cameras are available When the user selects a different camera Then the preview switches within 1s and prior video tracks are stopped Given permission is denied or the request hangs for 5s When camera enable is attempted Then a clear error or timeout message is shown with browser-specific remediation and a retry option
Device Enumeration and Persistence of Selections
Given device access is available When enumerateDevices is called on load and after permissions change Then the microphone, speaker, and camera dropdowns populate with accurate labels and update on devicechange events Given the user selects specific microphone, speaker, and camera When they revisit the pre-join screen in the same browser profile Then the last-known selections are restored from storage if still present; otherwise sensible defaults are applied Given a previously saved device is no longer available When the pre-join screen loads Then a notice is shown and the next available default device is selected Given the user chooses to clear saved selections When they click "Reset devices" Then persisted device preferences are removed and defaults are applied on next load
Permission Handling and Error Messaging (Chromium, Firefox, Safari)
Given the user has not previously granted permissions When a device test is initiated Then the app surfaces the native permission prompt and blocks further test results until a decision is made Given the user denies, dismisses, or has permanently blocked permissions When the app detects the state via Permissions API (where available) or getUserMedia errors Then the UI shows explicit state (Denied, Dismissed, Blocked), browser-specific remediation steps, and a "Try again" control Given a permissions-related error occurs When the error is handled Then an error code and context are logged for diagnostics without exposing sensitive data to the user
One-Click Re-Test All Devices
Given device selections are set When the user clicks "Re-test" Then microphone, speaker, and camera checks are re-run without page reload, preserving current selections Given the re-test is running When checks complete or time out Then each device shows a pass/fail/timeout status and the overall status summarizes results Given existing media tracks are active When re-test begins Then prior tracks are stopped/replaced cleanly to avoid resource leaks or echo
Join Gating with Warned Bypass
Given the user has not established a valid audio path When they attempt to press "Join" Then the "Join" button is disabled and a message indicates that at least one audio path (microphone activity detected in last 5s or successful speaker test) is required, with an option to "Join Anyway" Given the user chooses "Join Anyway" When they confirm the warning Then the join proceeds, the event is logged, and the conferencing token (if available) is preloaded to avoid delay Given at least one valid audio path is established When the checks pass Then the "Join" button becomes enabled within 300ms
Network Health Check & Grading
"As a participant on a variable network, I want a quick network check with clear guidance so that I know whether to join normally or switch to a lower-bandwidth option."
Description

Run a WebRTC preflight to assess connectivity and quality: ICE reachability to STUN/TURN, round-trip latency, jitter, packet loss, and sustained up/down throughput via small test streams. Compute a user-friendly grade (e.g., Excellent/Good/Fair/Poor) with recommendations (e.g., switch to audio-only, enable low-bandwidth mode, use PSTN). Detect corporate firewall/NAT constraints and suggest TURN or alternative transports. Display results in the pre-join UI, auto-select optimal media profile based on thresholds, and expose a quick “re-test” control. Integrate with TimeMeld’s meeting context to log results and inform fallback logic.

Acceptance Criteria
ICE Reachability & Corporate Firewall Detection
Given I am on the Join Precheck screen When I start the Network Health Check Then the system performs ICE gathering with STUN within 5 seconds and records success/failure And the system attempts TURN connectivity (UDP, then TCP, then TLS) within 10 seconds and records which transports are reachable And if no server-reflexive (srflx) candidate is obtained OR STUN is blocked, the system flags Restricted NAT/Firewall = true And if only relay candidates are available, the system displays "Relay-only connectivity" and recommends TURN/TLS or PSTN as alternatives And a summary shows STUN Reachable (Yes/No) and TURN Reachable (UDP/TCP/TLS) And the reachability phase completes in under 15 seconds on typical broadband networks
Quality Metrics Measurement & Grade Computation
Given the preflight is running When latency, jitter, and packet loss are sampled for at least 10 seconds using RTCP pings and test media frames Then the system computes average RTT (ms), jitter (ms), and packetLoss (%) And grade is assigned as the worst category across all metrics (including throughput classification): - Excellent: RTT < 50 AND jitter < 15 AND loss < 0.5 AND throughput not below HD classification - Good: no metric in Fair/Poor AND (50<=RTT<100 OR 15<=jitter<30 OR 0.5<=loss<1.5) - Fair: no metric in Poor AND (100<=RTT<200 OR 30<=jitter<50 OR 1.5<=loss<3) OR throughput classified SD - Poor: RTT >= 200 OR jitter >= 50 OR loss >= 3 OR throughput classified Audio-Only And the computed grade and numeric metrics are exposed to the UI and logging layers
Sustained Throughput Assessment
Given the preflight is running When the system streams controlled test media up and down for at least 8 seconds with congestion control enabled Then it reports sustained upstream and downstream throughput in Mbps to one decimal place And upstream capability is classified as: HD (>= 1.0), SD (>= 0.5 and < 1.0), Audio-Only (< 0.5) And downstream capability is classified as: HD (>= 1.5), SD (>= 0.8 and < 1.5), Audio-Only (< 0.8) And if the throughput test aborts due to network error, the throughput subscore is marked Poor and included in grading
Auto Media Profile Selection Before Join
Given network check metrics and grade are available When the system determines an optimal media profile Then if grade is Excellent or Good AND upstream >= 1.0 Mbps AND packetLoss < 1.5%, the default profile is Video High (720p enabled, HD simulcast on) And if grade is Fair OR (0.3 Mbps <= upstream < 1.0 Mbps), the default profile is Video Low (360p, low-bandwidth mode, HD off) And if grade is Poor OR upstream < 0.3 Mbps OR downstream < 0.3 Mbps, the default profile is Audio Only (camera off by default) And the user can override the suggested profile before joining; the preview updates within 500 ms to reflect changes And the selected profile is embedded in the join token/session parameters
Pre-Join UI Results & Recommendations
Given the network check completes When results are ready Then the UI displays within 1 second: overall grade label (Excellent/Good/Fair/Poor), RTT/jitter/loss values, up/down throughput, STUN/TURN status, and a plain-language recommendation And recommendations map as follows: Poor -> "Switch to audio-only and consider PSTN"; Fair -> "Enable low-bandwidth mode"; Restricted NAT/Firewall -> "Connecting via TURN/TLS" And the grade label uses distinct colors and icons with WCAG AA contrast, and each metric has an accessible name/description for screen readers And the UI provides a visible "Re-test" control
One-Click Re-Test Runs Full Preflight
Given I have completed an initial network check When I click Re-test Then the system re-runs ICE reachability, quality metrics, and throughput end-to-end And the Join button is disabled during the re-test and re-enabled upon completion And results, grade, recommendations, and suggested media profile update to reflect the latest measurements And the user can perform up to 3 re-tests within 2 minutes; beyond that, the control is temporarily disabled with a rate-limit message
Diagnostics Logging & Fallback Integration
Given a network check completes When results are finalized Then the system logs to the meeting context a record containing: meetingId, userId, timestamp, RTT ms, jitter ms, packetLoss %, up Mbps, down Mbps, STUN/TURN reachability, ICE candidate types (host/srflx/relay), restrictedNat flag, overall grade, selected profile, attempt number And the record is retrievable via the internal API for that meeting within 5 seconds of completion And if no ICE connectivity can be established to STUN or TURN and the grade is Poor, the UI flags fallbackNeeded and surfaces fallback join options (e.g., "Join with phone audio" or PSTN), while allowing retry And logging failures do not block join; the system retries logging in the background up to 3 times with exponential backoff
Conferencing Token Preload & Validation
"As a host, I want my conferencing token preloaded and validated so that everyone can enter the meeting instantly without authentication delays."
Description

Pre-fetch, validate, and securely cache the conferencing access token prior to join. Support SSO/OAuth flows, role-based capabilities (host/guest), and token refresh if expiry is near. Prefetch room metadata, ICE server lists, and warm DNS/TLS where possible to minimize join latency. Store tokens only in memory with strict TTLs and bind to meeting/user context to prevent reuse. Provide deterministic error handling and automatic retry/backoff on transient failures, falling back to on-demand token fetch if preload fails. Surface readiness state to the UI so users can join instantly when diagnostics pass.

Acceptance Criteria
SSO/OAuth Token Prefetch Success Path
Given a user opens Join Precheck for a scheduled meeting and has a valid SSO/OAuth session When preloading begins Then the system requests a conferencing access token using the active session without additional user interaction And validates token signature, issuer, audience, expiry, and required scopes/claims And completes token prefetch and validation within 1500 ms p95 And securely associates the token with the current userId and meetingId
In‑Memory Token Storage, TTL, and Context Binding
Given a preloaded token is obtained Then the token is stored only in volatile memory, never in localStorage, sessionStorage, cookies, or disk And the token TTL is set to min(server expiry minus 60 seconds skew, 10 minutes), after which it is discarded And the token is bound to meetingId and userId; any reuse in a different meetingId or userId context is rejected and triggers a fresh fetch And the token is cleared on Precheck exit, app reload, or explicit sign-out
Proactive Token Refresh When Expiry Is Near
Given a valid preloaded token that expires within 5 minutes When precheck is active Then the system proactively refreshes the token in the background using a refresh flow And performs at most one refresh attempt per precheck session And on successful refresh, the new token expires at least 10 minutes in the future And if refresh fails with a permanent error, state becomes FALLBACK and no further refresh attempts are made
Prefetch Room Metadata, ICE Servers, and Warm Network
Given precheck starts When preloading runs Then room metadata and participant role capabilities are fetched and cached And an ICE server list containing at least one TURN and one STUN server is retrieved and cached And DNS resolution and TLS preconnect to conferencing/SFU and TURN endpoints are initiated And 95% of preconnect handshakes succeed within 1000 ms And join path requires no additional network calls for room metadata or ICE on the READY path
Deterministic Errors, Retry with Backoff, and Fallback to On‑Demand Fetch
Given a transient fetch failure (HTTP 5xx, network timeout, DNS error) When preloading token or metadata Then retry up to 3 times with exponential backoff starting at 200 ms, multiplier 2, with 0–100 ms jitter, total wait <= 2000 ms And on success within retries, proceed to READY Given a permanent failure (401/403, invalid signature/claims) Then do not retry; set state FALLBACK and surface an error code in {TOKEN_INVALID, TOKEN_EXPIRED, PERMISSION_DENIED, NETWORK_TIMEOUT, SERVER_ERROR} And record telemetry with error code, attempt count, and duration And ensure on-demand fetch is invoked at join time if in FALLBACK
Readiness State Surfaced to UI and Instant Join
Given precheck runs Then UI state transitions through PRELOADING -> READY or FALLBACK within 2000 ms p95 And when READY, the Join button is enabled and labeled "Ready to join"; clicking Join initiates session without a token network call and reaches first media within 500 ms p95 (network permitting) And when FALLBACK, the Join button remains enabled; clicking Join triggers on-demand token fetch once and adds no more than 1000 ms p95 to join time compared to READY And UI exposes ARIA live status updates for state changes
Role-Based Capabilities Enforced via Token Claims
Given a preloaded token with role=host and matching meetingId When attempting host-only actions (start/record/mute-all) Then actions succeed and are authorized within 300 ms Given a preloaded token with role=guest When attempting the same host-only actions Then requests are rejected with PERMISSION_DENIED within 200 ms and no side effects occur And any token with mismatched meetingId or invalid signature is rejected with TOKEN_INVALID and triggers a fresh fetch if allowed
Adaptive Fallback Join Paths
"As a participant, I want a reliable fallback path if tests fail so that I can still join the meeting on time."
Description

Offer resilient alternatives when diagnostics fail or conditions are degraded: audio-only mode, low-bandwidth video (reduced resolution/frame rate), PSTN dial-in with PIN, and optional “call me” bridging where available. Provide browser-switch guidance and a magic-link email fallback for locked-down environments. Auto-suggest and preselect the best fallback based on device and network results, with a manual override and clear tradeoff copy. Ensure seamless transition from precheck to chosen fallback, preserving meeting identity and attendance tracking in TimeMeld. Log chosen fallback for analytics and postmortems.

Acceptance Criteria
Auto-Suggest and Preselect Best Fallback After Diagnostics
Given pre-join diagnostics complete with uplink < 250 kbps OR packet loss >= 15% OR CPU load >= 85%, When fallback options are presented, Then audio-only is auto-suggested and preselected. Given pre-join diagnostics complete with uplink between 250–600 kbps OR packet loss between 5–15% OR camera max capability < 720p, When fallback options are presented, Then low-bandwidth video (360p @ 15 fps) is auto-suggested and preselected. Given microphone access is denied OR no input devices are found, When fallback options are presented, Then call-me (if available) is auto-suggested and preselected; Else PSTN dial-in is preselected. Given WebRTC is unsupported OR getUserMedia is blocked by policy, When fallback options are presented, Then PSTN/call-me or magic-link email fallback is auto-suggested (preferring call-me where available). Then the suggestion displays a one-sentence rationale referencing the failing metric(s) that triggered the choice. Then the preselected option can be confirmed with a single action; all manual options are visible without scrolling on a 1366x768 viewport.
Seamless Transition Preserving Meeting Identity and Attendance
Given the user confirms a fallback option from precheck, When join is initiated, Then the same meeting_id and participant_id are used and the host sees a single attendee entry. Then an attendance record is created/updated with fields: meeting_id, attendance_id, fallback_type, chosen_reason_code, joined_at, and session_id. Then no duplicate attendee records are created if the user switches fallback within 60 seconds; the existing record is updated in place. Then the conferencing token is reused or reissued seamlessly without additional authentication prompts. Then time-to-media (first audio frame) is <= 5 seconds at P50 and <= 10 seconds at P90 on a 300 ms RTT test network; otherwise a non-blocking retry banner is shown with an error code.
PSTN Dial-in and Call-Me Bridging
Given the user selects PSTN dial-in, When a PIN is generated, Then it is 6 digits, unique per meeting instance, and expires 2 hours after meeting end. Then at least one in-country dial-in number is displayed for the detected country (if available); otherwise the nearest regional number is shown. When the caller enters the PIN via IVR, Then they are admitted to the correct meeting lobby and prompted for a name if lobby naming is enabled. Given the user selects call-me, When a valid E.164 phone number is provided and consent is checked, Then the bridge rings the number within 10 seconds at P95 and two-way audio is established within 15 seconds at P95. If three consecutive call attempts fail OR 30 seconds elapse without answer, Then the UI surfaces PSTN dial-in with the same PIN as the next-step fallback. Then phone numbers are masked in UI/logs except for country code and last 2 digits; full numbers are never persisted. Then each call attempt logs call_sid, country_code, outcome, and duration for auditing.
Browser Switch Guidance and Magic-Link Email Fallback
Given the browser is unsupported (e.g., IE, Safari < 14.1, Chrome < 80) OR required media APIs are blocked by enterprise policy, When precheck completes, Then a guidance panel lists at least two supported browsers with minimum versions and an action to open in the recommended browser. Then a Send magic link control is visible; When the user confirms an email, Then a single-use link is delivered within 60 seconds at P95 and expires in 30 minutes. When the user follows the magic link, Then they join the same meeting with the same identity without re-entering PIN or password. If mail delivery fails (bounce or provider error), Then the UI offers copy-link and QR-code alternatives preserving meeting identity. Then the guidance panel includes a short rationale referencing the specific detected block (e.g., camera access blocked by policy).
Manual Override With Clear Tradeoff Copy
Given fallback options are presented, When details are expanded for any option, Then tradeoff copy is shown: Audio-only disables camera and reduces data by ≥90%; Low-bandwidth video sets 360p@15fps and reduces data by ≥60% vs 720p@30fps; PSTN disables screen-share receive. When the user selects any available option, Then the selection updates immediately and can be confirmed in a single action. If diagnostics improve by >30% for key metrics before confirmation, Then the auto-suggested option updates with a non-intrusive notice; the user's explicit manual choice remains selected unless they opt-in to the update. Then the component meets WCAG 2.1 AA for focus order, contrast, and screen-reader labels on all actionable elements. Then the last explicit user choice is remembered for the same device/browser for 24 hours unless diagnostics differ by >30%.
Analytics and Postmortem Logging for Fallbacks
Given any fallback is suggested, selected, changed, or results in a join outcome, When the action occurs, Then an analytics event is sent with: meeting_id, user_id_hash, attendance_id, fallback_type, suggestion_rank, chosen_reason_code, uplink_kbps, packet_loss_pct, rtt_ms, device_os, browser, call_region (if telephony), time_to_join_ms, and outcome. Then 99% of events persist within 5 seconds of the action with retries for up to 2 minutes using exponential backoff. Then events can be correlated to attendance_id and session_id for postmortems without creating duplicate attendees. Then for PSTN/call-me, only country_code and last2 digits of the phone number are included; full numbers are never persisted. Then a nightly job aggregates fallback_type distribution and success rate; QA can query raw events by meeting_id within 24 hours of occurrence.
Pre-Join UI & Guided Fixes
"As a user, I want a simple pre-join screen with actionable fixes so that I can resolve issues quickly and join confidently."
Description

Create a streamlined pre-join screen that presents real-time status of device checks, network grade, and token readiness with clear pass/fail indicators. Include device selectors, quick actions (retry, switch to audio-only, open system settings), and contextual troubleshooting cards for common issues. Support one-click re-test and a “Join anyway” option with warnings. Persist user preferences (e.g., preferred mic/camera) and integrate branding. Ensure accessibility (keyboard navigation, screen reader labels, sufficient contrast) and localization readiness for key languages used by remote-first teams.

Acceptance Criteria
Real-Time Pre-Join Diagnostics Display
Given a user opens the Pre-Join screen on a supported browser When automatic checks start Then mic, camera, network, and token readiness statuses render within 2 seconds with clear Pass/Fail/Degraded indicators and plain-language labels Given the network test completes When metrics are calculated Then a grade is shown using thresholds: A (RTT ≤ 100 ms, jitter ≤ 30 ms, packet loss < 1%), B (RTT ≤ 200 ms, jitter ≤ 50 ms, packet loss < 2.5%), C (RTT ≤ 400 ms, jitter ≤ 80 ms, packet loss < 5%), D (otherwise) with a tooltip explaining impact Given token preloading begins When the token is successfully retrieved Then a "Token ready" status appears within 1.5 seconds; otherwise a "Token not ready" status with a Retry action appears Given device permission changes occur (grant or deny) When the permission state changes Then the corresponding status updates within 1 second and includes an actionable message Given the Pre-Join view is loaded When UI elements render Then TimeMeld branding (logo and theme colors) is visible and matches the current style guide
Device Selection & Preference Persistence
Given multiple input/output devices are available When the user opens the mic/camera/speaker selectors Then all detected devices are listed with human-friendly names and the current selection is highlighted Given the user selects a different device When the selection is confirmed Then the preview/test uses the new device immediately and the selection is saved as the preferred device Given the user is authenticated When they return to the Pre-Join screen in a new session Then their preferred mic/camera/speaker are pre-selected from their profile; if a saved device is unavailable, the system falls back to the default device and shows a non-blocking notice Given the user is unauthenticated (guest) When they return within 30 days on the same browser Then the last selected devices are restored from local storage; if unavailable, fall back as above Given keyboard-only navigation When tabbing through selectors Then focus order is logical, selection is possible via Enter/Space, and the selector announces the current selection to assistive tech
Quick Actions for Fix & Fallback
Given any individual check has failed or is degraded When the user clicks Retry on that check Then only that check re-runs and updates its status within 2 seconds Given the camera check fails or the user opts to reduce bandwidth When "Switch to audio-only" is selected Then video preview is disabled, audio preview remains active, the join mode is set to audio-only, and status updates to "Ready (audio-only)" Given a permission-related failure is detected When the user clicks "Open system settings" Then the relevant browser/OS permissions page opens in a new tab/window and an in-app guide shows the steps to enable access Given any quick action is in progress When the user attempts to trigger it again Then the action control is temporarily disabled and a progress indicator is shown to prevent duplicate requests
Contextual Troubleshooting Cards
Given a failure cause is detected (e.g., "Mic access denied", "No input level", "High packet loss") When the Pre-Join UI renders troubleshooting Then a contextual card appears with a clear title, cause summary, 2–3 recommended steps, and a primary action relevant to the cause Given more than one issue exists When cards are displayed Then cards are ordered by severity and category (permissions first, device not found, quality issues) and are individually dismissible Given the user follows a recommended action from a card When the subsequent re-test passes Then the card auto-collapses, the related status shows Pass, and a success toast confirms the fix Given an error has a technical code When the card is expanded Then the code and a "Copy details" control are available for support escalation
One-Click Re-Test & 'Join Anyway' with Warnings
Given at least one check is in Fail or Degraded state When the user clicks "Re-test all" Then all checks re-run in parallel and render updated results with a timestamp within 3 seconds Given one or more checks remain in Fail or Degraded state after re-test When the user selects "Join anyway" Then a confirmation modal summarizes the specific risks (by failing checks) and requires explicit confirmation to proceed Given the user confirms "Join anyway" When the meeting join is initiated Then the conference opens within 2 seconds and the chosen mode (full or audio-only) is preserved Given all checks pass after re-test When the user proceeds Then "Join anyway" remains available but is visually de-emphasized compared to "Join"
Accessibility: Keyboard, Screen Reader, Contrast
Given the Pre-Join screen is used with a keyboard only When navigating all controls Then no keyboard traps exist, focus is always visible, and actionable elements are reachable in a logical order Given a screen reader is active When statuses change (Pass/Fail/Degraded, token ready) Then changes are announced via polite ARIA live regions with meaningful, non-visual labels Given the UI is audited When tested with Axe (or equivalent) on the Pre-Join screen Then there are 0 Critical and 0 Serious violations and it meets WCAG 2.1 AA for contrast (text ≥ 4.5:1, non-text ≥ 3:1) and non-color cues for status Given users require larger targets When interacting with key controls (Join, Re-test, Retry, selectors) Then hit areas are at least 44x44 px and have visible focus and hover states
Localization & Branding Readiness
Given the application locale is set to English, Spanish, French, German, Portuguese, or Japanese When the Pre-Join screen loads Then all visible strings are translated using externalized resources with no truncation, overlap, or clipped text at up to 120% text expansion Given pluralizable or variable strings are used (e.g., "x devices found") When rendered in each supported locale Then correct pluralization and number/date formats are applied per locale rules Given pseudo-localization is enabled When the Pre-Join screen is tested Then no hard-coded strings appear and layout remains usable without overflow Given brand theming is applied When switching locales or toggling system dark mode (if supported) Then TimeMeld branding (logo, colors) remains consistent and accessible, and does not reduce contrast below WCAG thresholds
Precheck Telemetry & Support Artifact
"As a support engineer, I want precheck metrics and a shareable diagnostic artifact so that I can troubleshoot join issues and improve overall reliability."
Description

Capture structured, privacy-aware telemetry from the precheck (device availability, permission outcomes, network metrics, token preload status, chosen fallback) and correlate with meeting/user IDs using pseudonymous identifiers. Respect consent and admin controls, minimize PII, and enforce a 30-day retention. Provide an exportable diagnostic bundle (hash-signed JSON) that users can share with support to accelerate root-cause analysis. Stream aggregate metrics to analytics for reliability tracking and to inform TimeMeld’s scheduling heuristics (e.g., flag recurring join issues by region).

Acceptance Criteria
Precheck Telemetry Capture Completeness
Given a user runs Join Precheck for a scheduled meeting When the precheck completes (success or failure) Then a telemetry record is created with fields: timestamp (UTC ISO-8601), precheckSessionId, pseudonymousMeetingId, pseudonymousUserId, device availability (mic/camera present/absent), permission outcomes (granted/denied/prompt), network metrics (RTT ms, jitter ms, packet loss %, up/down bandwidth Mbps), token preload status (success/failure with error code), chosen join path (primary/fallback with reason), client app version, OS, browser, region, ASN And the telemetry record is persisted within 2 seconds of precheck completion for 99% of sessions And no duplicate record exists for a single precheckSessionId (idempotent upsert)
Consent and Admin Controls Enforcement
Given workspace telemetry is enabled and the user has not provided consent When the user opens precheck Then a consent prompt is displayed before any telemetry is persisted When the user declines consent Then no telemetry is stored or streamed; only in-memory operational checks run; UI proceeds in reduced mode When the user grants consent Then consent is recorded against the pseudonymousUserId and is revocable; consent state persists for up to 12 months unless revoked Given the admin disables telemetry at the workspace level When any user runs precheck Then no telemetry is collected or streamed regardless of prior user consent and the UI indicates telemetry is disabled Then PII minimization rules are enforced for all flows: no raw emails, names, phone numbers, exact IP addresses, device serials, or full hostnames are stored; geo is stored as region + ASN only
Pseudonymous Correlation Without Re-identification
Given a workspace-scoped secret key and 90-day salt rotation When creating stored identifiers Then userId and meetingId are HMAC-SHA256 hashed and stored as 128-bit truncated hex digests; raw identifiers are never persisted And the same (user, meeting) pair hashes consistently within a salt window and changes after rotation And salts/keys are stored in a secure secrets manager and not exportable via application logs or bundles Then any query interface returns only hashed identifiers; attempts to ingest raw identifiers into storage are rejected at validation
30-Day Retention and Verified Deletion
Given telemetry and diagnostic bundle objects older than 30 days When the retention job runs hourly Then all qualifying records are hard-deleted from primary storage and aged-out from object storage via lifecycle rules And deletion audit logs record counts removed and any failures When querying by a known precheckSessionId older than 30 days Then zero records are returned And on deletion job failure, an alert is emitted within 5 minutes to on-call
Exportable Diagnostic Bundle (Hash-Signed JSON)
Given a completed precheck session When the user selects Export Diagnostic Bundle Then a JSON file is generated within 3 seconds containing: schemaVersion, createdAt, precheckSessionId, pseudonymousMeetingId, pseudonymousUserId, device availability, permission outcomes, network metrics, token preload status and errors, fallback choice and reason, client environment summary And the bundle size is ≤ 256 KB and contains no raw PII or exact IP address And the bundle is signed with Ed25519; offline verification with the published TimeMeld support public key succeeds; any modification causes verification to fail And copy-to-clipboard and download actions produce byte-identical content
Aggregate Metrics Streaming for Reliability and Heuristics
Given a telemetry record is created When emitting to the analytics pipeline Then aggregate metrics (precheck success rate, average/95th latency, jitter, packet loss, token preload success rate, fallback rate) are streamed within 60 seconds for 95% of events And events contain no user- or meeting-level identifiers; include only region, ASN, client environment, app version, and time bucket When regional fallback rate > 15% or token preload failure rate > 10% for a 15-minute window with N ≥ 50 sessions Then a region-issue flag is published to the reliability dashboard and made available to scheduling heuristics within 5 minutes
Fallback Join Path Telemetry and Outcome Correlation
Given precheck detects a blocking issue (e.g., permission denied, device missing, high packet loss, token preload failure) When the fallback path is presented and selected (or auto-selected for hard failures) Then telemetry captures fallbackReasonCode, selection timestamp, and subsequent join outcome (success/failure) with timestamp And the UI label for fallback reason matches the recorded reason code And correlation between precheck session and meeting join uses a pseudonymous joinAttemptId with < 0.1% orphaned prechecks over a rolling 7 days

Auto Block Sync

Continuously ingests personal focus blocks, PTO, travel, and team maker hours from connected calendars and org defaults. Handles recurring patterns, DST, and timezone moves automatically, so proposed meeting windows always reflect the latest protected time—no manual upkeep required.

Requirements

Multi-Calendar Ingestion & Normalization
"As a remote team member, I want TimeMeld to pull my protected time from all my calendars so that meeting proposals never land on my focus, PTO, or travel blocks."
Description

Connect to Google Workspace and Microsoft 365 calendars via OAuth with least-privilege scopes to continuously ingest events from personal, shared, and team calendars. Normalize busy-time into standardized categories (focus blocks, PTO, travel, maker hours) using event metadata, keywords, and admin-defined tags. Support read-only ingestion, ICS imports for non-managed calendars, and per-calendar opt-in. Map ingested blocks to TimeMeld’s protected-time model so scheduling proposals automatically exclude these windows across participants. Provide idempotent upserts, deduping of mirrored events, and resilient backfill for historical recurring series to ensure consistency after reconnects.

Acceptance Criteria
Least-Privilege OAuth Connections with Per-Calendar Opt-In
- Given a user connects Google Workspace or Microsoft 365 via OAuth, When the consent screen is shown, Then only read-only calendar scopes (list/read events) and basic profile are requested; no write or email/send scopes are requested. - Given the connection completes, When the integration is saved, Then the selected calendars default to opt-out and require explicit per-calendar opt-in before ingestion begins. - Given access is revoked at the provider, When webhooks or token refresh fail, Then the connection is marked revoked and ingestion stops within 10 minutes, and the user is notified.
Continuous Ingestion Latency and Timezone/DST Handling
- Given a connected, opted-in calendar, When an event is created, updated, or deleted, Then the change is reflected in TimeMeld’s protected-time model within 2 minutes (p95) and 5 minutes max. - Given a recurring series spans a DST transition or a user changes home timezone, When the provider updates are received, Then the protected-time occurrences align with the correct local times for each occurrence within 5 minutes. - Given the user relocates across timezones, When their primary timezone changes, Then future occurrences are recalculated to the new timezone without shifting past occurrences.
Busy-Time Normalization to Standard Categories
- Given an ingested event with provider metadata (e.g., out of office), admin-defined tags, or keywords (e.g., “PTO”, “travel”, “focus”), When normalization runs, Then the event is classified into focus, PTO, travel, or maker hours with a precedence of admin tag > provider metadata > keyword > default busy. - Given an event series with an override applied by an admin/user, When future occurrences are ingested, Then the override is applied idempotently to the series and exceptions. - Given maker hours are defined via org defaults or team calendars, When the workweek begins, Then daily maker-hour blocks materialize as read-only protected time visible in the model and UI.
ICS Import for Non-Managed Calendars
- Given a valid .ics file up to 10 MB is uploaded, When import runs, Then all events within the selected date range are imported as read-only and normalized using the same rules as live feeds. - Given the same .ics is re-imported, When import runs, Then upsert is idempotent: existing events are updated in place, no duplicates are created, and deleted events are not reintroduced. - Given malformed lines exist in the .ics, When import runs, Then the importer skips invalid entries, logs a count of skipped items, and completes import for valid items.
Idempotent Upserts and Deduping of Mirrored Events
- Given an event appears on multiple calendars (e.g., personal invite + shared/team calendar), When ingestion occurs, Then TimeMeld stores a single protected-time block by matching iCalUID/provider UID and start/end (±60s tolerance) and prefers the primary attendee’s instance as canonical. - Given reconnects or repeated backfills occur, When the same event is re-seen, Then upsert by provider etag/lastModified updates the existing record without creating duplicates. - Given an event is cancelled or replaced by an update, When ingestion runs, Then the protected-time block is removed or updated accordingly within 5 minutes.
Resilient Backfill After Outage/Reconnect
- Given access is restored after a provider outage or token refresh, When backfill starts, Then events are reconciled for the past 90 days and next 365 days, including recurring series and exceptions. - Given provider rate limits are encountered, When backfill runs, Then ingestion throttles with exponential backoff, persists progress checkpoints, and resumes without data loss. - Given partial failures occur, When retry completes, Then the final state matches the provider’s calendar and audit logs show a complete pass.
Scheduling Proposals Exclude Protected Time Across Participants
- Given multiple participants have connected calendars and opt-ins, When TimeMeld generates meeting windows, Then all protected-time blocks categorized as focus, PTO, travel, or maker hours are excluded from proposals. - Given a candidate slot overlaps any protected time by 1 minute or more, When proposals are generated, Then that slot is not proposed unless an explicit override is set by the organizer. - Given a protected-time block ends at time T, When proposals are generated, Then earliest proposal start is T + 5 minutes (configurable buffer).
Recurring & Exception Pattern Engine
"As a product manager, I want recurring and exception rules to be handled automatically so that I don’t have to fix proposals every time a series changes."
Description

Parse RRULE-based recurrences, EXDATE exceptions, and instance overrides to maintain an accurate, expanded set of protected-time intervals. Respect per-event semantics (e.g., modified single occurrences) and align recurrence expansion windows with scheduling horizons. Detect implicit routines (e.g., repeated ad-hoc focus blocks) and allow users to promote them to formal recurrences via suggested patterns. Ensure changes propagate instantly to TimeMeld’s window generator so proposed times remain valid without manual cleanup when series shift or exceptions are added.

Acceptance Criteria
RRULE Weekly Expansion within Horizon
Given an event E exists on a connected calendar with DTSTART 2025-10-01T09:00:00 America/Los_Angeles and RRULE:FREQ=WEEKLY;BYDAY=MO,WE And the system scheduling horizon is 30 days starting now When the Recurring & Exception Pattern Engine ingests and expands E Then it creates protected-time intervals only for E occurrences whose start is within [now, now+30d) And each occurrence is placed at 09:00 America/Los_Angeles on Mondays and Wednesdays And no protected interval for E exists outside the 30-day window And the number of created intervals equals the number of E occurrences in that window
EXDATE and Single-Instance Overrides
Given a recurring event R with DTSTART 2025-10-07T14:00:00 America/New_York and RRULE:FREQ=WEEKLY;BYDAY=TU And EXDATE includes 2025-10-14 And an overridden instance exists with RECURRENCE-ID 2025-10-21T14:00:00 America/New_York and a new start 2025-10-21T15:30:00 America/New_York and duration 60 minutes When the engine expands protected intervals for R within the scheduling horizon Then no protected interval exists on 2025-10-14 for R And a protected interval exists on 2025-10-21 starting 15:30 America/New_York for 60 minutes And all other Tuesday occurrences within the horizon start at 14:00 America/New_York with the base duration And if both EXDATE and an overridden instance exist for the same date, the overridden instance takes precedence and is included
DST Boundary Preservation
Given a recurring event D with DTSTART 2025-10-24T09:00:00 America/Los_Angeles and RRULE:FREQ=WEEKLY;BYDAY=FR that spans a DST change within the scheduling horizon When the engine expands protected intervals for D Then every Friday occurrence starts at 09:00 America/Los_Angeles local time before and after the DST transition And the UTC offset for each occurrence reflects the correct pre-/post-DST offset And no duplicate or skipped occurrences are produced due to the DST change
Timezone Move During Travel
Given the user's working timezone is set to Europe/Berlin for a travel period [T1, T2] And a daily recurring event T exists with DTSTART 2025-10-01T10:00:00 America/Los_Angeles and RRULE:FREQ=DAILY When the engine computes protected-time intervals and evaluates meeting-window conflicts during [T1, T2] Then T is preserved at 10:00 America/Los_Angeles wall time and converted to Europe/Berlin time for conflict detection and display And proposed meeting windows do not overlap the converted protected intervals within [T1, T2] And after T2, conversions revert to the user's original timezone without manual changes
Implicit Routine Detection and Promotion
Given at least 4 ad-hoc focus blocks (no RRULE) start between 09:00 and 09:15 local time on weekdays over the last 14 days with duration 90±10 minutes When the detected alignment of day/time meets or exceeds an 80% threshold Then the engine generates a Suggested Pattern with RRULE {FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0} and DURATION 90 within 60 seconds And the user receives a one-click "Promote to Recurrence" action referencing the suggestion When the user accepts the suggestion Then a formal recurrence is created starting at the next valid occurrence, future protected intervals derive from it, and duplicate overlaps with the original ad-hoc blocks are prevented When the user declines the suggestion Then no recurrence is created and the same pattern will not be suggested again for at least 7 days
Instant Propagation to Window Generator
Given existing proposed meeting windows have been generated for the current scheduling horizon When a change to protected time occurs via RRULE edit, EXDATE addition/removal, instance override, or promotion of a suggested pattern Then within 2 seconds the engine recomputes protected intervals and updates the window generator And any proposed windows that now conflict are withdrawn from the API/UI and replaced by conflict-free alternatives within the same horizon And the update is idempotent (repeating the same change does not create duplicate withdrawals or proposals) And the API emits a change event containing affected window IDs and a monotonic version number
DST & Timezone Drift Resolver
"As an engineer who travels, I want my protected time to follow me through timezone and DST changes so that proposals stay ergonomic wherever I am."
Description

Automatically reconcile protected-time across daylight saving transitions and user timezone changes, preserving event intent (local wall-clock vs absolute UTC) based on source calendar semantics. Detect travel or location-based timezone updates and rebase focus/maker hours so personal ergonomics are respected in the new locale. Harmonize offsets across participants so TimeMeld’s timezone-weighted proposals avoid newly inconvenient slots created by DST shifts or travel, without requiring user intervention.

Acceptance Criteria
DST Transition: Preserve Local-Intent Focus Blocks
- Given a recurring focus block Mon–Fri 09:00–12:00 created with local/wall-clock semantics and the user’s timezone transitions from UTC−5 to UTC−4 due to DST spring-forward, When the DST change occurs, Then the block instances on and after the transition date appear at 09:00–12:00 in the new local timezone with no one-hour drift. - Given a recurring focus block created with absolute UTC semantics, When DST changes, Then the local display time shifts by one hour consistent with UTC anchoring, and intent is preserved. - Then no duplicate or missing instances occur in the affected week (instance count matches expectation). - And all-day/date-only PTO entries remain date-aligned across the transition (start/end dates unchanged).
User Travel: Rebase Maker Hours to New Locale
- Given a user’s device timezone changes from America/Los_Angeles to Asia/Tokyo and a travel itinerary event indicates arrival at a specific date/time, When TimeMeld detects two corroborating signals (device TZ change persists ≥5 minutes and itinerary arrival time reached), Then the user’s maker hours (e.g., 10:00–16:00 local) are rebased to Asia/Tokyo starting at arrival plus ≤30 minutes, and prior instances in the origin timezone remain unchanged. - Then proposals generated after rebase avoid windows outside 10:00–16:00 Asia/Tokyo for that user. - And no retroactive edits are applied to protected-time in the past. - And an audit entry records old TZ, new TZ, effective time, and source signals.
Cross-Participant Harmonization After Staggered DST
- Given participants in US/Pacific and Europe/Berlin with maker hours configured in local time, When US DST begins while EU DST has not yet begun, Then TimeMeld recomputes timezone-weighted proposals so the top 3 candidate windows keep each participant within their maker hours (≤0 minutes outside). - And any previously saved but unsent proposal sets are refreshed automatically within 2 minutes of the DST change. - And windows that newly violate any participant’s protected time are removed from proposals.
Timezone Change Signal Debounce and Accuracy
- Given transient timezone flips (e.g., VPN causes device TZ to alternate for <5 minutes), When the signal does not persist beyond the debounce threshold (5 minutes) and no corroborating calendar/location signal exists, Then TimeMeld does not rebase protected time or proposals. - Given conflicting signals (device TZ says Europe/London, calendar travel indicates arrival tomorrow), When ambiguity exists, Then TimeMeld schedules rebase at the earlier of itinerary arrival or persistent device TZ ≥30 minutes and records pending status without prompting the user. - Then the false-positive rebase rate in automated tests is ≤0.5%.
Recurring Series Integrity Across DST and TZ Moves
- Given a weekly recurring focus series with local intent, When a DST change or timezone move occurs, Then TimeMeld creates series exceptions as needed to preserve wall-clock times without gaps or overlaps; total number of instances in a 90-day window equals expected count. - And no adjusted instance overlaps with existing meetings by more than 0 minutes due to the adjustment. - And ICS exports and connected calendars show the same start/end timestamps as TimeMeld for adjusted instances.
Propagation and Latency SLAs
- Given a detected DST change or confirmed timezone rebase event, When the change is applied, Then the user’s protected-time blocks are updated in TimeMeld within 60 seconds and propagated to connected calendars within 120 seconds. - And team proposal recomputation completes within 120 seconds, and the UI displays an updated status within 150 seconds. - And API webhook notifications (if enabled) are delivered with 99th percentile latency ≤180 seconds.
Real-time Sync & Conflict Resolution
"As a team lead, I want changes to my calendar to update TimeMeld within a minute so that newly blocked time is never suggested for meetings."
Description

Establish near-real-time updates using calendar watch channels/webhooks with exponential backoff and token renewal, falling back to smart polling when push is unavailable. Debounce rapid event churn, batch process deltas, and apply optimistic concurrency with versioning to avoid race conditions. Guarantee end-to-end propagation to proposal generation and invite updates within a target SLA (e.g., p95 < 60s). Provide atomic updates to the protected-time store to prevent transient overlaps and ensure TimeMeld never proposes within newly created blocks.

Acceptance Criteria
Push Sync with Intelligent Polling Fallback
Given a connected calendar supports push and a valid watch is active, when an event is created/updated/deleted, then a notification is received and processed and the protected-time store is updated and visible to proposal generation within SLA targets. Given push registration fails, is revoked, or the provider does not support push, when the condition is detected, then smart polling activates within 15s and uses incremental sync tokens to fetch changes without duplication. Given polling is active, when push becomes available again, then the system switches back to push within 60s with missed delta count = 0 (verified by incremental token continuity). Rule: After a daily full reconcile, drift between source calendars and protected-time store = 0 items.
Debounce and Batch Processing of Rapid Calendar Changes
Given ≥10 changes to the same calendar occur within 3s, when processing begins, then changes are coalesced into ≤2 batches and the final protected-time state matches the source state. Rule: Per-calendar debounce window = 1s; max coalescing delay = 5s; no individual change waits >5s to enter a batch. Rule: Batch processing preserves order per resource, and partial batch failures are retried without duplicating already-applied deltas. Rule: Under burst load (≥100 changes/min/calendar), throughput sustains ≥500 changes/min/node with no SLA breach for end-to-end propagation.
End-to-End Propagation SLA (p95 < 60s)
Given a change in a connected calendar that affects protected time, when the change is committed to the protected-time store, then updated proposed windows and any related invite updates are produced within p95 < 60s and p99 < 120s measured over ≥1000 events under nominal load. Rule: Measurement starts at provider event time (or receipt time if provider omits event time) and ends when proposal generation output reflects the change and invites (if any) are updated. Rule: SLA metrics are emitted (latency histogram, p95/p99, error rate) and an alert triggers if p95 ≥ 60s for 5 consecutive minutes. Rule: Dead-letter/poison message rate ≤ 0.1% with automatic retries and operator visibility.
Optimistic Concurrency with Versioned Protected-Time Store
Given two concurrent writers update the same protected-time record, when a stale version is submitted, then the write fails with 409 Conflict (or equivalent) and includes the current version for retry. Rule: Successful writes increment the version atomically and expose a strictly increasing version per record. Rule: Each write is atomic across all affected time slices; readers never observe partial updates, and no transient overlaps exist post-commit. Rule: Store enforces non-overlapping intervals per user/team policy; attempts to create overlaps are rejected or merged deterministically per specification. Rule: End-to-end tests simulate race conditions and verify zero lost updates and deterministic final state.
Watch Channel Auto-Renewal and Exponential Backoff
Given a push watch/channel has an expiry, when the remaining lifetime reaches 5 minutes, then the system renews the watch or re-registers successfully without losing the sync token. Given token refresh is required, when access tokens are near expiry or invalid, then tokens are refreshed proactively and re-registration uses fresh credentials. Given transient provider errors (429/5xx) occur, when retries are scheduled, then exponential backoff with full jitter is applied (initial 1s, cap 15m) and missed deltas are recovered via sync tokens. Rule: Channel outage recovery results in missed delta count = 0 (validated by incremental sync) and no duplicate side-effects. Rule: All renewals/backoffs are logged with correlation IDs and surfaced in operational dashboards.
Idempotent Delta Handling and Duplicate Suppression
Given duplicate or out-of-order webhook notifications for the same event/change, when processing occurs, then exactly-once application is achieved using event IDs and sequence/version checks, and no duplicate proposals/invites are produced. Rule: Reprocessing the same delta is safe and has no side effects (idempotent handlers for store updates, proposal regeneration, and invite updates). Rule: Deduplication window ≥ 24h with bounded memory usage; eviction does not result in missed or duplicated application (covered by source-of-truth reconciliation). Rule: Verification includes replay tests with shuffled and duplicated streams yielding identical final state and side-effect counts.
Org Defaults & Maker Hours Policy
"As an ops manager, I want org-wide maker hour policies applied automatically so that proposals respect both company standards and individual schedules."
Description

Allow admins to define organization and team-level defaults for maker hours, meeting-free days, company holidays, and blackout windows. Merge org policies with user-specific calendars using clear precedence rules and per-team overrides. Support role-based templates (e.g., support vs engineering) and location-aware policies to reflect regional holidays. Surface effective protected-time to users for transparency and feed directly into TimeMeld’s proposal engine to optimize for collective ergonomics while respecting individual preferences.

Acceptance Criteria
Admin Defines Org Defaults and Team Overrides
Given an authenticated Org Admin When they create and publish an Org Default policy with: - Maker hours: Mon–Thu 10:00–16:00 (local) - Meeting‑free day: Friday - Daily blackout: 12:00–13:00 - Holiday sets: Company + relevant regional calendars And they create and publish a Team Override for Engineering with: - Maker hours: Mon–Thu 09:00–17:00 - Meeting‑free day: none - Additional blackout: Wed 15:00–17:00 Then: - Both policies are persisted with unique policy_id and version numbers - Team Override is effective for all members of Team=Engineering - Effective Protected‑Time preview for a test Engineering user reflects team values overriding org in same categories and retains org settings for categories not overridden
Policy Precedence Merge: User Blocks, Team Overrides, Org Defaults
Given User U in Team=Engineering, Location=America/New_York And Org Defaults: Maker hours Mon–Thu 10:00–16:00; no blackout And Team Override: Maker hours Mon–Thu 09:00–17:00; no blackout And Org Blackout: Daily 16:30–18:00 And User Hard Block (PTO): Thu 13:00–15:00 (Busy=Out of office) When Effective Protected‑Time is computed for Thu 2025‑09‑18 Then: - Precedence order is applied: User Hard Blocks > Holidays (location‑aware) > Team Blackouts/Meeting‑free > Org Blackouts/Meeting‑free > Team Maker Hours > Org Maker Hours - Category overrides are replacement, not union, between team and org - Effective Protected‑Time intervals are 09:00–18:00 local (union of team maker hours 09:00–17:00 and org blackout 16:30–18:00), annotated to show PTO within 13:00–15:00 - Proposed meeting windows exclude any time that intersects [09:00, 18:00) - The Effective Protected‑Time calendar contains no overlaps and is represented at 1‑minute granularity
Role-Based Templates Applied With Team Overrides
Given role templates exist: - Engineering: Maker hours 10:00–16:00; Meeting‑free Fri - Support: Maker hours 08:00–11:00 and 13:00–16:00; Meeting‑free Wed And User S is assigned Role=Support and Team=Support And Team=Support has an override removing Meeting‑free Wed while leaving maker hours as defined by the template When Effective Protected‑Time is computed for Wed Then: - Support template maker hours are applied - Team override removes Meeting‑free Wed from the effective policy - Org defaults for the same categories do not apply - Changing User S Role to Engineering updates the effective policy on the next recompute, visible within 2 minutes
Location-Aware Regional Holidays and Travel
Given Org Holiday Sets include US and UK calendars And User A is located in US/Eastern on 2025‑11‑27 (US Thanksgiving) And User B is located in Europe/London on 2025‑11‑27 When Effective Protected‑Time is computed Then: - User A’s entire 2025‑11‑27 local day is a blackout (no proposals generated) - User B’s 2025‑11‑27 is not a blackout due to UK location And Given User B has a calendar travel event arriving in London on 2025‑12‑24 18:00 local When Effective Protected‑Time is computed for 2025‑12‑25 Then: - 2025‑12‑25 is a blackout for User B due to UK holiday - Location change is detected and applied no later than 15 minutes after the recorded arrival time
DST Stability of Local Maker Hours
Given maker hours are 09:00–17:00 anchored to the user’s local timezone America/Los_Angeles When Effective Protected‑Time is computed for: - 2025‑03‑07 (PST, UTC‑8) - 2025‑03‑10 (PDT, UTC‑7) Then: - Both days show 09:00–17:00 local as protected - UTC representation is 17:00–01:00+1 day for 2025‑03‑07 and 16:00–00:00+1 day for 2025‑03‑10 - No one‑hour gaps or duplications occur in the protected intervals across the DST transition
Transparency of Effective Protected-Time and Sources
Given a user opens the Protected Time panel When the effective schedule is displayed for the next 14 days Then: - Each protected interval shows its source category and origin (e.g., Team Override, Org Default, Role Template, Holiday, User PTO) - A “Why is this blocked?” explainer lists the precedence that produced the interval - The total protected hours per day and per source are shown - The exported ICS/JSON feed for Effective Protected‑Time exactly matches the UI rendering and the proposal engine’s inputs
Policy Change Propagation to Proposal Engine
Given an Org Admin publishes a change that adds a company‑wide blackout on Mon 11:30–13:30 When a participant search and proposal generation is requested for any set of org users Then: - Within 2 minutes of publish, /availability and proposal results exclude 11:30–13:30 on the next applicable Mondays for all affected users - API responses include the new policy ETag/version, and logs show cache invalidation at publish time
Privacy & Consent Controls
"As a privacy-conscious user, I want fine-grained control over what TimeMeld reads and stores so that my sensitive event details remain private."
Description

Provide granular consent for which calendars to sync and which fields to store; default to busy-only ingestion with optional title/description masking and hashing for deduplication. Display clear permission scopes during OAuth, allow per-calendar revoke, and implement data minimization with configurable retention. Maintain audit logs of sync activity and admin actions, and expose a user-facing privacy panel within TimeMeld to review synced sources. Ensure encryption at rest/in transit and isolate tenant data so Auto Block Sync protects user privacy while delivering accurate scheduling outcomes.

Acceptance Criteria
Per-Calendar Consent Selection During OAuth
Given a user with three calendars discovered from the provider And the user initiates Connect Calendars in TimeMeld When the TimeMeld OAuth pre-consent screen is displayed Then the screen lists each requested provider scope with a plain-language description And each discovered calendar is presented with an unchecked checkbox by default And the Authorize action is disabled until at least one calendar is selected When the user selects two calendars and completes OAuth Then only the selected calendars are added as active sources in Auto Block Sync And no data is ingested or stored from any unselected calendars
Default Busy-Only Ingestion
Given a newly added calendar source with no overrides When Auto Block Sync ingests events Then only availability state and time boundaries (start, end, timezone, recurrence meta) are stored And event titles, descriptions, attendees, locations, and attachments are not stored And proposed meeting windows use busy/free only with no content-field exposure And querying stored records returns null/empty for all content fields
Event Field Masking and Hash-Based Deduplication
Given org setting Store content fields = Off and Hash for deduplication = On And two calendars contain the same event title and description at the same time window When Auto Block Sync ingests those events Then title and description are stored as masked placeholders And a salted, non-reversible hash is stored for deduplication And only one busy block is created for the overlapping events And the hash value differs across tenants for the same input When Hash for deduplication = Off Then overlapping events are not deduped via hash while content fields remain masked
User Privacy Panel: Synced Sources Visibility and Controls
Given a user has connected multiple calendars When the user opens Settings > Privacy in TimeMeld Then the panel lists each source with provider, calendar name, scopes granted, masking/dedup status, retention policy, last sync timestamp, and next scheduled sync And each source row provides Revoke and View Audit Trail actions When the user clicks Revoke on a source and confirms Then the source status changes to Revoked and is removed from active sources And no further sync occurs for that source within 5 minutes And the revoked source appears in a Revoked section with revocation timestamp until its data is purged per retention policy
Configurable Data Retention and Minimization
Given an org admin sets retention to 30 days and field minimization to Minimum Required When the nightly retention job runs Then sync artifacts older than 30 days are permanently deleted And only start, end, timezone, availability state, recurrence meta, source id, tenant id, and hash (if enabled) remain for active records And an audit log entry is created with deletion counts and job id When the admin changes retention to 7 days Then the next job deletes items older than 7 days
Audit Logging for Sync and Admin Actions
Given audit logging is enabled by default When any of the following occurs: calendar added, scopes approved, source revoked, retention policy changed, sync run started/completed/failed Then an immutable audit entry is created with timestamp (UTC), actor, tenant id, action, target resource id, outcome, and metadata And org admins can filter logs by action and date range in the Privacy Panel And attempts to modify or delete an audit record via API return 403 and leave the record unchanged
Security Controls: Encryption and Tenant Isolation
Given data flows between providers, TimeMeld services, and storage When inspecting transport security Then TLS 1.2+ is enforced end-to-end with strong ciphers and HSTS on web endpoints When inspecting data at rest Then records are encrypted using KMS-managed keys (AES-256 or equivalent) And each record includes a tenant id and row-level security denies cross-tenant access When a user from Tenant A requests a resource belonging to Tenant B via direct URL or API Then the system returns 403/404 with no data leakage And a security audit entry is recorded for the denied access

Guarded Proposals

Treats focus blocks and maker hours as hard constraints in the scheduler. Proposals never land inside protected windows and are clearly labeled with protection badges, eliminating accidental erosion of deep work and the back‑and‑forth of "can we squeeze it in?" asks.

Requirements

Protected Window Ingestion & Normalization
"As an engineer, I want my focus blocks and maker hours automatically recognized so that proposed meetings never land during my deep work time."
Description

Continuously ingest protected time from connected calendars and user/team settings, normalize them into a unified "protection interval" model, and expose them to the scheduler as hard constraints. Sources include calendar events tagged as focus/deep work/do-not-schedule, user-defined maker hours, and org-level blackout policies. The system reconciles overlapping intervals, handles time zone conversions and recurrence rules, classifies source and sensitivity (user policy vs. org policy), and stores results in a low‑latency constraint service. This ensures Guarded Proposals always operate on accurate, up‑to‑date constraints while preserving privacy controls and auditability.

Acceptance Criteria
Calendar Tag Ingestion to Protection Intervals
Given a connected calendar event labeled with any of ["focus","deep work","do-not-schedule"] (case-insensitive, via tag or category), When the platform receives a webhook or polling delta for creation or update, Then a protection interval is created or updated with matching start/end (to the minute), hardConstraint=true, source="calendar", classification="user policy", within 30 seconds of change receipt. Given an all-day tagged event in timezone T, When ingested, Then a protection interval spans local 00:00–24:00 for each day of the event in T, stored in UTC with T recorded. Given a tagged event is deleted or untagged, When the change is received, Then the corresponding protection interval is removed within 30 seconds.
User Maker Hours Normalization
Given maker hours defined as weekly windows in a user's local timezone, When saved, Then recurring protection intervals are generated with RRULEs so that local wall-clock times remain constant across DST changes, and are stored with classification="user policy". Given a week crossing a DST transition, When queried, Then intervals reflect the correct local start/end each applicable day. Given maker hours are changed, When saved, Then future intervals are replaced and visible via the constraint service within 30 seconds; past intervals remain unchanged.
Org Blackout Policy Ingestion and Precedence
Given an org-level blackout policy (fixed window or RRULE), When activated, Then protection intervals are created with classification="org policy", sensitivity="high", hardConstraint=true. Given overlap between org policy and any user-level protection, When normalized, Then the resulting interval is the union with sensitivity resolved to "org policy" and proposal eligibility is false for the union span. Given the org policy is deactivated, When processed, Then affected intervals are removed within 60 seconds.
Overlapping Interval Reconciliation
Given two or more protection intervals that overlap or abut within the same scope (user or team), When normalized, Then they are merged into a minimal set of non-overlapping intervals with contiguous boundaries coalesced (e.g., [10:00–11:00] + [11:00–12:00] => [10:00–12:00]). Given the merged interval originates from multiple sources, When stored, Then metadata retains the set of contributing sources and the highest sensitivity across them. Given gaps exist between intervals, When normalized, Then no new intervals are introduced.
Recurrence and Exception Handling
Given a recurring tagged calendar series with RRULE and instance exceptions (EXDATE or modified single instance), When ingested, Then protection intervals are generated for occurrences excluding EXDATEs and reflecting per-instance edits. Given a series is updated (RRULE change) or an instance is edited/deleted, When the change is received, Then affected intervals are added/updated/removed accordingly within 60 seconds, without duplicating unaffected instances. Given a long-running RRULE, When stored, Then intervals are materialized only within the configurable planning horizon (e.g., next 12 weeks) and extended incrementally as the horizon advances.
Low-Latency Constraint Service and Freshness
Given a request for constraints for a team and time window with up to 10k intervals in scope, When queried under nominal load (100 QPS per org), Then the service responds in ≤50 ms p95 and ≤200 ms p99 with complete intervals. Given a source change (create/update/delete) is received, When queried after propagation, Then the updated intervals are visible via the service within 60 seconds end-to-end. Given a scheduler proposal is evaluated, When its time overlaps any hard constraint interval, Then the service flags it as ineligible with a reason including source classifications.
Privacy-Preserving Storage and Auditability
Given any ingested calendar event, When normalized, Then only interval bounds, timezone, source type, classification, sensitivity, and opaque event identifiers are stored; titles, descriptions, attendees, and locations are not stored or are irreversibly redacted. Given an authorized auditor requests an audit log for a user and time window, When retrieved, Then logs include trace ID, operation (create/update/delete), source, timestamps, before/after interval bounds, and actor/process, with retention ≥180 days. Given an unauthorized actor queries constraints or audit logs outside their scope, When access is attempted, Then the request is denied and the attempt is logged.
Maker Hours Configuration UI
"As a product manager, I want to configure and preview my maker hours so that the scheduler reliably respects my recurring deep work patterns."
Description

Provide a self-serve configuration interface for users and teams to define recurring maker hours (by weekday/time, time zone, and duration), add exceptions and temporary pauses, and import from existing calendars or templates. Include validation to prevent overlaps with working-hour rules, a heatmap preview of protected coverage across the week, and one-click application of team templates. Persist preferences to user profiles and allow admins to apply org-wide defaults while respecting individual overrides within policy bounds.

Acceptance Criteria
Create Recurring Maker Hours Block
Given I have edit permission and open the Maker Hours configuration UI When I add a recurring block specifying weekday(s), start time, duration, and a time zone Then the block is saved and appears in the list with times normalized to the chosen time zone Given I create a block that spans past midnight When I save it Then the UI clearly represents the cross-day span and the block is persisted without truncation Given I attempt to create a duplicate block (same weekday, start, duration, and time zone) When I save Then the system prevents duplication and displays a non-blocking notice
Validate Non-Overlap With Working-Hour Rules
Given organization or user working-hour rules exist When I attempt to save maker hours that overlap any working-hour rule Then the save is blocked and an inline error lists each conflicting rule and the overlapping time span Given no overlap exists When I save maker hours Then the save succeeds without warnings or errors
Add Exceptions and Temporary Pauses
Given a recurring maker-hours block exists When I add a one-time exception for a specific date Then the block is suppressed for that date and the heatmap reflects the gap Given I add a temporary pause with a start and end date When I view the schedule Then maker hours are suspended during that window and automatically resume after the end date Given I remove an exception or pause When I save Then the original recurrence behavior is restored and reflected in the heatmap
Import Maker Hours From Calendar or Template
Given I choose Import and select a connected calendar or a predefined template When I complete the selection flow Then candidate maker-hour blocks are previewed and I can confirm to create them Given imported blocks would conflict with existing maker hours or working-hour rules When I confirm import Then the system surfaces conflicts, allows me to deselect conflicting items, and blocks only conflicting items from being created Given source events or templates specify a time zone When I import Then resulting maker hours inherit the source time zone
Heatmap Preview Updates and Accuracy
Given I have configured maker hours, exceptions, and pauses When I open the heatmap Then it displays protected coverage for all seven days with a legend and correct local-time labels Given I change a configuration value (add, edit, or remove) When I save the change Then the heatmap updates to reflect the change without requiring a page reload Given I toggle between My View and Team View When I view the heatmap Then My View shows my protection only, and Team View shows aggregated team coverage respecting individual time zones
Apply Team Template With One Click
Given a team template exists When I click Apply Template Then the template’s maker-hour blocks are applied to my profile and previewed before confirmation Given applying the template would override existing blocks When I confirm Then existing blocks are replaced as indicated and an Undo option is shown for at least 10 seconds Given conflicts with working-hour rules are detected during template application When I apply the template Then only compliant blocks are created and all conflicts are listed for review
Persist Preferences and Admin Policy Bounds
Given I save my maker-hours configuration When I log out and back in or retrieve my settings via API Then the saved preferences persist and exactly match what I configured Given an admin defines org-wide defaults and policy bounds When I attempt an override outside the bounds Then the system blocks the change and displays the violated policy with required limits Given my override is within bounds When I save Then it is accepted and takes precedence over the org default for my profile Given an admin updates org-wide defaults When I next load the UI Then my within-bounds overrides remain unchanged and default-only settings update to the new defaults
Hard-Constraint Slot Generation
"As a team lead, I want the scheduler to enforce protected windows as hard constraints so that proposals only include truly viable times for all attendees."
Description

Upgrade the slot generation engine to treat all protection intervals as non-negotiable constraints for every attendee. Candidate windows must exclude protected intervals, satisfy minimum meeting duration and buffer rules, and incorporate TimeMeld’s timezone-weighted ergonomics and fairness scoring. Provide fallback behavior when no viable windows exist (e.g., expand search horizon or suggest invoking the override workflow) and maintain performance SLAs for cross-time-zone, multi-attendee searches.

Acceptance Criteria
Exclude Protected Windows Across All Attendees and Time Zones
Given a meeting request with multiple attendees across different time zones and each attendee has one or more protection intervals within the search horizon When the system generates candidate meeting windows for the next 14 days Then 100% of proposed windows have zero temporal overlap with any protection interval for any attendee (overlap count = 0) And each proposed window is marked in the API payload with protectionBadge = "Protected Windows Respected" And the response summary includes protectedWindowViolations = 0
Enforce Minimum Duration and Pre/Post Buffers
Given minDuration = 45 minutes, bufferBefore = 15 minutes, bufferAfter = 15 minutes, and attendees have calendars with events and protected intervals When the system generates candidate meeting windows Then every proposed window duration is >= 45 minutes And startTime of each proposed window is >= (endTime of the nearest preceding event/protection + 15 minutes) And endTime of each proposed window is <= (startTime of the nearest following event/protection - 15 minutes) And each proposed window includes bufferCompliance = true in the API payload
Rank by Timezone Ergonomics and Fairness with Score Transparency
Given ergonomics scoring is enabled and fairness rotation is enabled with rankingWeights = { ergonomics: 0.7, fairness: 0.3 } And attendees have local-time ergonomic preferences and recent ownership history When the system generates and ranks candidate windows Then each proposed window includes ergonomicsScore, fairnessScore, combinedScore = 0.7*ergonomicsScore + 0.3*fairnessScore And proposals are sorted strictly by combinedScore descending with tie-breaker = earliest startTime And no proposal with a lower combinedScore appears before a proposal with a higher combinedScore And if an attendee exceeds the 4-week ownership quota, proposals burdening that attendee include fairnessPenaltyApplied = true
Fallback on No Viable Windows: Expand Horizon, Suggest Override
Given constraints yield zero viable windows in the default 14-day search When the system attempts fallback search Then the engine expands horizon in +7 day increments up to a maximum of 28 days until windows are found or the limit is reached And if still zero windows, the response includes noResults = true and fallbackActions contains ["SuggestOverrideWorkflow"] And the response includes blockingConstraintsSummary and fallbackAttemptCount >= 1 And analytics/logs record reasonCodes for infeasibility
Performance SLA: Cross-Time-Zone Multi-Attendee Searches
Given a request with 8–10 attendees across >= 5 time zones and a 14-day horizon When generating the first page of top 20 proposals under warm-cache conditions Then p95 end-to-end latency at the slot-generation service boundary is <= 2.0 seconds and p99 <= 3.0 seconds over a sample of >= 1000 requests And under cold-start conditions p95 latency is <= 2.5 seconds And results are streamed or returned atomically with consistent ordering across retries (idempotency key respected)
Handle DST Transitions and Overnight Protected Blocks
Given protected intervals that span midnight and a daylight saving time transition within the horizon When the system normalizes calendars and generates candidate windows for all attendee time zones Then no proposed window partially overlaps a protected interval due to DST offset changes (overlap count = 0 in both UTC and local time checks) And protection intervals are treated as half-open [start, end); a proposal may start exactly at protection end only if buffers are satisfied And proposals that would cross into a protected block after DST shift are excluded
Protection Badges & Reason Transparency
"As a participant, I want proposals to show badges explaining protected times so that I understand why slots are excluded and avoid asking to squeeze meetings in."
Description

Display clear protection badges on proposed and excluded time windows across web UI, extensions, and email. Badges indicate the protection type (e.g., Maker Hours, Focus Block, Org Policy), the affected attendee(s), and a concise reason with hover/tap details and accessible text. Respect privacy settings by redacting sensitive event titles while still conveying the constraint. Provide consistent visual semantics and localization to reduce back-and-forth and build trust in Guarded Proposals.

Acceptance Criteria
Proposed Slots Badge Visibility (Web UI)
Given a scheduling request includes attendees with active protections (Maker Hours, Focus Block, Org Policy) that influenced slot selection And proposed time windows are generated in the web UI When the user views the proposed windows Then each proposed window displays badges for the protections respected that influenced the proposal And each badge shows the protection type and affected attendee name/initials per privacy settings And hovering or tapping a badge reveals a detail tooltip with a concise reason (≤140 chars) and the protection’s start–end time in the viewer’s local timezone And badges are visible at standard desktop and mobile breakpoints (≥320px width) without overlap or truncation And badge display order is deterministic: Org Policy, Focus Block, Maker Hours, then others alphabetically
Excluded Slots Reason Badges (Web UI)
Given excluded time windows are displayed in the day/week view and in the Excluded list When the user inspects an excluded window Then at least one badge indicates the primary blocking protection for that window And the user cannot select the excluded window for proposal (selection control disabled with tooltip explaining why) And hovering/tapping the badge reveals all blocking protections with affected attendees (show up to 5, then “+N more”) And badge styling (icons, colors, shape) matches proposed-slot badges for consistency
Email and Extension Badge Rendering
Given a proposal email and the calendar extension show proposed and excluded windows When the recipient/user views the content Then each slot includes text badges that state protection type and affected attendee(s) per privacy settings And badges render legibly in Gmail web, Outlook (desktop & web), and Apple Mail; if CSS/images are blocked, a plain-text fallback shows the same information And in the extension, hover/tap reveals details; in email, a “Why this time?” link opens the web UI details view And badges include accessible text (no color-only meaning) and alt text for any icons And badge text is localized to the recipient’s locale when known; otherwise falls back to en-US
Privacy Redaction of Sensitive Details
Given an attendee has a private Focus Block or event title and organization policy requires redaction for non-owners When a non-owner views protection badges across web, extension, or email Then the badge shows the protection type with a “Private” qualifier and affected attendee, but does not reveal the event title or description And the tooltip shows a generic reason and time range only (no sensitive text) And the event owner sees the full title per their permissions; admins see details only if policy permits And redaction behavior is consistent across all surfaces and respects per-attendee privacy settings
Localization and Visual Semantics Consistency
Given the application is set to locales fr-FR, de-DE, es-ES, ja-JP, and ar When viewing badges and tooltips across web UI, extension, and emails Then badge labels, dates, times, and pluralization are correctly localized for each locale And right-to-left layout (ar) renders badge alignment and icon placement correctly And the same icons and color semantics are used for each protection type across all surfaces And if a translation is missing, en-US is used and a missing-translation event is logged
Accessibility: Keyboard, Screen Reader, and Contrast
Given a user navigates badges using keyboard and a screen reader When a badge receives focus Then focus is clearly visible and meets minimum 3:1 focus indicator contrast And badge text meets WCAG 2.2 AA (≥4.5:1 contrast) and touch targets are ≥24x24px And the badge exposes an accessible name including protection type, affected attendee(s), and “opens details” when applicable And the details tooltip/panel is announced, linked via aria-controls/expanded, and is dismissible via Esc and focus loss without trapping focus
Policy Hierarchy and Aggregation Rules
Given multiple protections overlap for a time window across one or more attendees When rendering badges for that window Then badges are prioritized by Org Policy > Focus Block > Maker Hours > Other And no more than 3 badges are shown inline; additional protections are summarized as “+N” And the details view lists all protections sorted by priority then attendee name And the same aggregation and ordering rules are applied across web UI, extension, and email And unit tests cover overlap, priority order, and overflow cases with ≥90% coverage of badge rendering logic
Consent-based Override & Audit Trail
"As an organizer, I want a consent-based override flow so that I can handle true emergencies without undermining our focus culture."
Description

Enable organizers to request a scoped override when no viable windows are found or in urgent cases. The flow requires selecting the specific protection to override, entering a justification, and obtaining explicit consent from impacted attendees. Record all actions in an audit log, enforce policy controls (e.g., disable overrides for org policies, require admin or majority consent), and deliver notifications via email/Slack. Overrides are time-bound and revert automatically after the event or expiration.

Acceptance Criteria
Scoped Override Request When No Viable Windows
Given a scheduling attempt finds no viable windows due to protected blocks When the organizer clicks "Request scoped override" Then the UI requires selecting one or more specific protections to override per impacted attendee And the UI requires a non-empty justification of at least 20 characters And the UI displays a summary of impacted attendees, protections, and proposed time window(s) And the Submit action remains disabled until selections and justification are valid And on submit, a pending override request with a unique ID is created
Explicit Attendee Consent Collection and Thresholds
Given a pending override request with impacted attendees exists When the request is submitted Then consent requests are delivered via email and Slack to each impacted attendee within 60 seconds And each consent request includes the justification, protections to be overridden, the time window, and explicit Approve/Decline actions And the system records each response with timestamp and channel And scheduling proceeds only when the configured policy threshold is met (e.g., admin approval or majority of impacted attendees) And until the threshold is met, no event is created and protected blocks remain enforced
Admin and Policy Controls Enforcement
Given an org policy disables overrides entirely When a non-admin attempts to open the override flow Then the override action is blocked with the message "Overrides are disabled by your organization" and an audit entry is recorded Given an org policy requires admin approval for overrides When a non-admin submits an override request Then the request is routed for admin approval and is not scheduled until admin approval is granted in addition to any attendee consent requirements configured
Audit Trail Completeness and Immutability
Given any action occurs in the override lifecycle (creation, update, consent, approval, decline, expiration, reversion) Then an audit log entry is written with actor, action, target, UTC timestamp, and request ID And entries are append-only; updates produce new entries without modifying prior entries And organizer, impacted attendees, and org admins can view the full audit trail for the request And the audit trail can be exported to CSV and JSON including all entries for the request
Notifications and In-Product Indicators
Given a pending override request exists Then the organizer sees an "Override pending" badge on the proposal and draft event And impacted attendees see a "Protected time override requested" badge on relevant time windows And email/Slack notifications contain localized times per recipient timezone and deep links to the consent page And reminder notifications are sent 2 hours before the consent timeout if no response has been recorded
Time-Bound Override Reversion
Given an override is approved and an event is created Then selected protections are lifted only for the event time window specified by the override And after the event ends or the override expiration time passes (whichever is earlier), protections automatically revert without manual action And if the event is canceled or rescheduled outside the overridden window, protections revert immediately and attendees are notified And recurring events require explicit per-occurrence overrides by default; no blanket override is applied unless explicitly configured by policy
Edge Cases and Error Handling
Given all impacted attendees decline or the consent timeout elapses without meeting the threshold Then the override request is marked as failed, no event is created, and organizer and impacted attendees are notified with the reason And if any notification channel fails, the system retries and falls back to alternate channels when available, with failures logged And if the organizer edits protections or time window after requests are sent, prior consents are invalidated, a new consent cycle starts, and audit entries link the versions And if relevant org policy changes mid-process, the request is revalidated immediately; incompatible requests are paused with guidance to comply or cancel
Recurring Meeting & Rotation Compliance
"As a distributed team, I want recurring meetings and rotation to respect protected windows so that no one repeatedly sacrifices deep work or sleep."
Description

Ensure recurring series proposals respect weekly protection patterns and integrate with TimeMeld’s equity scoreboard to rotate ownership and time burdens without violating maker hours. The system simulates multiple future occurrences to avoid repeating inconvenient slots for the same person, rebalances when participants or constraints change, and surfaces a preview of the rotation plan before finalizing.

Acceptance Criteria
Weekly Guard Compliance for Recurring Series
Given a recurring meeting is proposed with Guarded Proposals enabled And all participants have maker hours and focus blocks defined weekly When the system generates the series across the next 12 weeks Then zero occurrences overlap any participant’s protected windows And each proposed occurrence displays protection badges summarizing enforced constraints And if no guard-compliant window exists for a given week, the system withholds that occurrence and surfaces a "No compliant window" reason with impacted participants And daylight saving time transitions are accounted for using each participant’s local timezone so compliance still holds
Equity Scoreboard Ownership Rotation
Given a recurring series with rotation enabled and equity weights configured When generating the next 8 occurrences Then ownership is assigned per occurrence so that no participant is owner twice in a row unless all other owners would violate guards And the cumulative owner count difference between any two participants over the 8 occurrences is at most 1, respecting weights And any owner substitution due to guard conflicts is recorded with reason and reflected in the preview
Time-Burden Distribution Without Violating Maker Hours
Given participants span three or more time zones and guard windows are enforced as hard constraints When proposing times for the next 8 occurrences Then no participant is scheduled outside their maker hours or focus blocks And each participant receives at most one occurrence in their personal edge window (defined as the first or last hour of their allowed scheduling window) within the 8 occurrences, unless constraints make this impossible And in impossibility cases, edge-window assignments rotate so no participant receives consecutive edge-window occurrences
Multi-Occurrence Simulation and Repeat Avoidance
Given the simulation horizon is set to 8 weeks When computing proposals for a new recurring series Then the system evaluates all 8 occurrences before finalizing any And it avoids assigning the same participant to the same relative slot bucket (early/mid/late within their allowed window) more than once within the horizon when alternatives exist And the preview displays a simulation scorecard including, per participant: counts of early/mid/late slots and ownership totals
Dynamic Rebalance on Participant or Guard Changes
Given a recurring series is active and a participant is added, removed, or updates guard windows When the change is saved Then only future occurrences more than 48 hours away are rebalanced by default And rebalanced occurrences remain guard-compliant and maintain rotation fairness constraints And the system presents a change diff listing moved, canceled, and newly scheduled occurrences before applying And upon confirmation, calendar updates are sent and the equity scoreboard is updated accordingly
Rotation Plan Preview and Confirmation Gate
Given a new recurring series is being created When the user opens the rotation preview Then at least the next 6 occurrences are shown with local times per participant, assigned owner, protection badges, and fairness metrics And the Finalize action remains disabled until the user confirms the preview And any manual edit forces the preview to refresh and revalidate before enabling Finalize
No-Feasible-Plan Handling
Given constraints yield no compliant schedule within the horizon When proposals are computed Then the system returns no times and surfaces a structured explanation listing constraint conflicts per participant and week And it offers next actions that do not violate guards (e.g., adjust participants, extend horizon), without placing any occurrence in protected windows
Post-Send Drift Detection & Auto-Reproposal
"As a calendar owner, I want TimeMeld to detect new conflicts after proposals are sent so that it can proactively offer alternatives before my focus time is interrupted."
Description

Monitor calendars for changes after proposals or invites are sent and detect when newly added protection intervals create conflicts. Automatically generate alternative windows that honor all constraints, notify participants with clear protection badges and rationale, and update calendar invites (ICS) when rescheduling is confirmed. Apply smart throttling and organizer preferences to minimize notification noise.

Acceptance Criteria
Drift Detection After Protected Block Added
Given a proposal or invite was sent and has not started or completed When any participant adds or extends a protection interval that overlaps the proposed or scheduled time Then the meeting is marked In Conflict within 5 minutes Given a non-protection calendar event overlaps the time When drift detection evaluates Then no auto-reproposal is triggered by this requirement Given a conflict is created less than 15 minutes before the scheduled start When detection runs Then auto-reproposal is suppressed and only the organizer is alerted Given a protection interval is added and then removed within 2 minutes When drift detection evaluates Then no notification or reproposal is sent Given a drift event is detected When it is recorded Then the log includes meeting ID, actor, overlap reason, and timestamp
Constraint-Compliant Alternative Generation
Given a meeting is marked In Conflict When alternatives are generated Then at least 3 ranked candidate windows are produced that satisfy all participants’ protection windows, declared working hours, minimum notice, and meeting duration Given alternatives are generated When evaluating each option Then no candidate overlaps any participant’s protected intervals and ergonomic limits are respected (e.g., back-to-back caps, lunch breaks if configured) Given alternatives are ranked When scoring is applied Then options are timezone-weighted to minimize total inconvenience and presented in descending suitability Given historical inconvenient slots exist for this meeting in the last 4 weeks When generating options Then no candidate repeats a slot flagged as inconvenient by any participant Given organizer preferences specify single-instance or series adjustment When generating options Then options match the specified scope (instance vs series)
Participant Notification With Protection Badges and Rationale
Given conflict-driven alternatives exist When notifying recipients Then the subject and body include the conflict reason, named participant, overlapping times, and protection badges (e.g., Maker Hours, Focus Block) Given organizer notification preferences are set When sending notifications Then messages are sent to the organizer only by default, or to all participants if configured, or auto-rescheduled if enabled Given a notification is delivered When the recipient views actions Then options include Accept top suggestion, Choose another time, and Request exception Given notifications are rendered When times are displayed Then each time is shown in the recipient’s local timezone and UTC Given throttling bundles multiple conflicts When a consolidated message is sent Then it summarizes the conflicts and lists the current top-ranked options
Smart Throttling and Preference-Aware Delivery
Given multiple drift events occur for the same meeting within 30 minutes When notifications are prepared Then a single consolidated notification thread is sent instead of multiples Given organizer quiet hours are configured When a drift event occurs during quiet hours Then notifications are deferred to the next allowed send window while alternatives are precomputed Given organizer sets a daily max of 5 scheduling notifications When the limit is reached Then subsequent notifications are rolled into a daily digest Given a meeting has an active reproposal awaiting decision When another drift event occurs Then no new reproposal is created and the existing thread is updated with the latest options Given a drift event resolves within 2 minutes of detection When throttling rules are applied Then no external notification is sent
Confirmed Reschedule Updates ICS Correctly
Given the organizer (or authorized delegate) confirms a proposed alternative When calendars are updated Then an ICS update is sent within 2 minutes using the same UID, incremented SEQUENCE, updated DTSTART/DTEND, and preserved attendees and conferencing details Given attendees receive the update When it is processed by their calendars Then the prior time is superseded without creating a duplicate event Given the meeting is a recurring series and only one instance is moved When generating ICS Then a RECURRENCE-ID is included to update the single instance without altering other occurrences Given the event is updated due to protection conflicts When composing the description Then a brief rationale with protection badges is appended to the event notes Given time zone data is required When composing the ICS Then an appropriate VTIMEZONE component is included to ensure correct local time display
Idempotency, Deduplication, and Auditability
Given the same protection interval is edited multiple times within 10 minutes When drift detection runs Then only one drift event and one notification are created Given a reproposal exists for a meeting and no decision has been made When the same conflict persists Then the system does not resend identical options Given a reproposal was sent and the protection interval causing the conflict is removed When detection confirms no conflict remains Then the reproposal is withdrawn and the organizer is notified once subject to throttling Given drift-related actions occur When audit logs are produced Then each drift event, generated options, notifications, and ICS updates are recorded with timestamps and correlation IDs and retained for at least 90 days

Humane Finder

When a requested slot collides with a guard, instantly offers the nearest humane alternatives ranked by explicit tradeoff scores (context‑switch cost, timezone burden, rotation impact). Organizers get transparent, fair options and can confirm the best fit in one click.

Requirements

Real-Time Guardrail Collision Detection
"As an organizer, I want the system to instantly tell me when a requested slot violates participant guardrails so that I don’t waste time on times we can’t use."
Description

Detect scheduling conflicts the moment an organizer proposes a slot by evaluating participant guardrails (working hours, focus blocks, do-not-disturb, no-meeting days, public holidays, and previously assigned rotation constraints). Integrates with connected calendars (Google, Outlook, ICS) and TimeMeld’s team policies to classify a proposed time as hard-blocked, soft-blocked, or acceptable. Exposes a low-latency service (<300ms p95 for up to 12 participants) that returns conflict reasons with machine-readable codes to trigger humane alternative generation. Handles partial attendance requirements (optional vs required attendees), recurring events, and overlapping holds, with robust DST and locale handling. Emits structured telemetry for conflicts to support analytics and continuous tuning.

Acceptance Criteria
Classify Proposed Slot Against Guardrails
Given an organizer proposes a meeting slot and participant guardrails (working hours, focus blocks, do-not-disturb, no-meeting days, public holidays, rotation constraints) are loaded per team policy When the slot is evaluated for all participants Then the service returns overall_classification = hard-blocked if any required participant has a hard conflict under current policy And returns overall_classification = soft-blocked if no required hard conflicts exist but at least one required participant has a soft conflict And returns overall_classification = acceptable if no required participant has a hard or soft conflict (optional attendee conflicts do not elevate the classification)
Low-Latency SLA for Up to 12 Participants
Given a proposed slot with between 1 and 12 participants and valid calendar/policy context When the evaluation request is made to the detection endpoint Then the end-to-end response time p95 is <= 300 ms measured from request receipt to last byte over a rolling 5-minute window under nominal load
Return Machine-Readable Conflict Codes
Given at least one conflict is detected for any participant When the response is returned Then each conflict includes: participant_id, guardrail_type, severity in {hard, soft}, start_ts, end_ts, source in {calendar, policy}, timezone, locale, and a code from an enumerated set And the top-level response includes overall_classification and schema_version And emitted code values conform to the published enumeration and remain backward compatible across versions
Aggregate Classification with Optional vs Required Attendees
Given a meeting proposal with a mix of required and optional attendees When evaluating conflicts Then any hard conflict for a required attendee yields overall_classification = hard-blocked And if no required hard conflicts exist but at least one required attendee has a soft conflict, overall_classification = soft-blocked And if only optional attendees have conflicts, overall_classification = acceptable while their conflicts are still enumerated in the response
Handle Recurring Events with DST Transitions
Given a recurring meeting proposal defined by an RRULE and a start time zone When evaluating the series Then the service returns per-occurrence evaluations within the requested horizon including occurrence_timestamp (organizer time zone), per-occurrence overall_classification, and conflict codes And DST transitions are handled so each participant’s local time reflects correct offsets And locale-specific public holidays and no-meeting days are applied per participant for each occurrence
Merge Multi-Calendar Sources and Overlapping Holds
Given participants have connected Google, Outlook, and/or ICS calendars with overlapping events and holds When evaluating the proposed slot Then events are merged and deduplicated across sources using stable identifiers and time windows And overlapping events collapse to a single conflict with the highest severity per policy (e.g., busy > tentative/hold) And tentative/hold events are treated per team policy as soft or hard and labeled source=calendar with provider metadata
Emit Structured Conflict Telemetry
Given any evaluation request is processed When the response is generated or an error occurs Then a telemetry event guardrail_evaluated is emitted containing request_id, org_id, meeting_id, participant_count, latency_ms, overall_classification, conflict_counts_by_type, per-severity counts, has_recurring flag, timezone_spread, error_code (if any), and schema_version And no PII beyond opaque IDs is included And the event is successfully delivered >= 99% of the time over a rolling 24-hour window
Nearest Humane Alternatives Generator
"As an organizer, I want nearby humane alternatives suggested automatically so that I can quickly choose a workable time without manual back-and-forth."
Description

When a conflict is detected, compute and return the closest feasible meeting windows that minimize participant burden while respecting guardrails and team policies. Generates 3–7 ranked alternatives within a configurable search horizon (e.g., next 10 business days), considering participants’ local times, meeting duration, buffer times, and organizer constraints. Supports hard/soft constraints, mandatory/optional attendees, and per-team “no back-to-back” spacing. Provides a deterministic, explainable selection with ties broken by historical fairness signals. Guarantees sub-700ms p95 end-to-end from proposal to alternatives for teams up to 12 participants.

Acceptance Criteria
Generate 3–7 Ranked Alternatives within Configurable Horizon
Given a scheduling request collides with a guard and the search horizon is configured to 10 business days When the generator runs with a meeting duration and organizer constraints provided Then it returns between 3 and 7 feasible alternatives within the horizon, sorted by total_score descending And if fewer than 3 feasible alternatives exist, it returns all feasible (including zero) and sets result_flag="insufficient_feasible" And each alternative includes: start_utc, end_utc, duration_minutes, participant_timezones[], component_scores{context_switch_cost, timezone_burden, rotation_impact}, total_score, and feasibility_notes
Deterministic, Explainable Ranking with Tradeoff Scores
Given identical inputs (participants, calendars, constraints, weights, horizon) and system seed When the generator is executed 5 times Then the set of alternatives, their order, total_score, and component_scores are identical across runs And each alternative exposes an explanation object enumerating contributions and penalties, whose sum equals total_score within 1e-6 tolerance
Hard/Soft Constraints and Mandatory/Optional Handling
Given attendees have hard constraints, soft preferences, and are marked mandatory or optional When alternatives are generated Then no alternative violates any hard constraint or working-hours guardrail of mandatory attendees And soft-constraint breaches are allowed only with explicit penalties reflected in component_scores and noted in feasibility_notes And alternatives may omit optional attendees only if inclusion would make the slot infeasible, with omitted_optional listed and a recomputed score
No Back-to-Back Spacing and Buffers Enforcement
Given a team rule min_spacing_minutes=S and per-attendee buffers before/after are configured When alternatives are computed Then each proposed slot ensures spacing >= S from adjacent events for all included attendees And per-attendee buffers before and after the meeting are preserved, otherwise the slot is excluded from results
Timezone Ergonomics and Working-Hours Guardrails
Given participants span multiple time zones with defined working hours When alternatives are generated Then every alternative schedules all mandatory attendees within their working hours And the timezone_burden component_score is computed for each alternative and included in the response
Performance SLA: p95 ≤ 700ms for ≤12 Participants
Given teams up to 12 participants and realistic calendar data When measuring end-to-end latency from request to alternatives response over 2000 requests Then the p95 latency is ≤ 700ms and any breach logs an sla_breach event with request_id and measured_latency_ms
Confirm-Ready Payload for One-Click Scheduling
Given a ranked list of alternatives has been returned When the organizer selects an alternative Then the response contains a confirm_token, normalized start/end in UTC, attendee lists segmented by mandatory/optional, and policy references used in scoring And POST /meetings/confirm with the confirm_token creates the event, returns 201 with event_id, or 409 with refreshed alternatives if the slot becomes invalid
Transparent Tradeoff Scoring
"As an organizer, I want to see transparent scores and reasons for each suggested time so that I can choose the fairest option confidently."
Description

Attach a normalized tradeoff score to each alternative based on three weighted factors: context-switch cost (focus fragmentation, buffers, back-to-back risk), timezone burden (distance from participants’ preferred hours, weekend/holiday proximity), and rotation impact (fairness delta vs equity scoreboard). Provide a per-option breakdown and plain-language rationale so organizers can see why an option ranks higher. Offer team-level default weights with per-meeting overrides; persist choices for learning. Ensure scoring is reproducible, auditable, and side-effect free, with versioned formulas and A/B toggles for experimentation.

Acceptance Criteria
Normalized Tradeoff Score Calculation
Given team-level default weights (w_context, w_timezone, w_rotation) exist and sum to 1.0 ± 0.001 When Humane Finder computes scores for a set of alternatives Then each factor subscore is computed in the range [0,100] And weights are each in [0,1] and validated to sum to 1.0 ± 0.001, otherwise computation is rejected with a validation error And the composite score = round(w_context*context_subscore + w_timezone*timezone_subscore + w_rotation*rotation_subscore, 2) and is in [0,100] And the same inputs produce identical composite scores across repeated computations
Per-Option Factor Breakdown and Plain-Language Rationale
Given composite and factor subscores are computed for each alternative When an organizer views an alternative in Humane Finder or retrieves it via API Then the response includes: composite score, each factor subscore, current weights, and each factor’s weighted contribution And a rationale section includes at least one plain-language sentence per factor referencing concrete data (e.g., buffers, preferred hours deviation, equity delta) And all displayed numbers match the underlying computed values within 0.01 And the full breakdown is exportable as JSON via an endpoint with the meeting and option identifiers
Team Default Weights with Per-Meeting Overrides and Persistence
Given a team admin edits default weights When weights are saved Then each weight is between 0 and 1 and totals 1.0 ± 0.001 or the save is rejected with actionable errors And the change is persisted with actor, timestamp, and version Given an organizer sets per-meeting weight overrides during scheduling When scores are computed for that meeting Then the overrides are used instead of team defaults for that session only And the organizer can revert to team defaults in one action And the organizer’s last-used weights are persisted and pre-populated for their next meeting in that team
Reproducibility, Side-Effect Free Scoring, and Auditability
Given a fixed set of inputs (participants, calendars, holidays, preferences, weights, formula version, experiment cohort) When scoring is executed multiple times or on different instances Then the outputs (scores and ranking order) are identical and include a deterministic result checksum And no calendar events, invites, notifications, or other external resources are created, modified, or deleted by the scoring operation And an audit log entry is written capturing: input hash, weight vector, factor versions, formula version, experiment cohort, requester, timestamp, and result checksum And audits are retrievable by meeting ID and include the per-option breakdown used to produce scores
Versioned Formulas and A/B Experiment Toggle
Given formula versions vN and vN+1 are registered and enabled for experimentation When a team is enrolled in experiment E with a 50/50 split Then organizers are stably bucketed into cohorts A or B by a deterministic hash (teamId, organizerId, meetingType) unless an explicit override is set And every score payload includes formulaVersion and experimentCohort metadata And an admin kill switch can disable vN+1, causing new computations to fall back to vN within 60 seconds And audit entries preserve the original version and cohort regardless of subsequent configuration changes
Rotation Impact Fairness Delta vs Equity Scoreboard
Given an equity scoreboard with current ownership balances exists for the team When computing rotation impact for an alternative Then the fairness delta is derived from the projected change to the scoreboard if that alternative is selected And the rotation subscore monotonically increases as projected inequity decreases, per the documented mapping And alternatives that increase inequity beyond a configurable threshold T are flagged in both UI and API And the rationale includes the signed fairness delta and the impacted owners
Deterministic Ranking and Tie-Breaking
Given a set of alternatives with computed composite scores When Humane Finder returns ranked options Then options are sorted by composite score descending And ties within 0.01 are broken by (1) lower timezone burden subscore loss, (2) lower context-switch subscore loss, (3) earlier UTC start time, (4) lexicographic ISO datetime And the ranking order is stable across repeated computations with the same inputs And the top-ranked option corresponds to the maximum composite score within numeric precision
One-Click Confirm & Auto-Invite
"As an organizer, I want to confirm a suggested time in one click so that invites go out immediately without manual editing."
Description

Enable organizers to confirm any suggested alternative in one click, automatically creating the calendar event, adding conferencing details, inviting participants, and posting notifications (email/Slack). Preserves original meeting metadata (title, agenda, docs), updates series logic for recurring events, and writes back to connected calendars with correct organizer/owner. Handles consent prompts when the time falls outside a participant’s preferred hours, and offers fallback placeholders if conferencing provisioning fails. Emits success/failure webhooks and updates TimeMeld timelines for traceability.

Acceptance Criteria
One-Click Confirm Creates Event With Preserved Metadata
Given an organizer views Humane Finder alternatives for a meeting request with title, agenda, and attached docs And the organizer’s calendar and conferencing accounts are connected and have create permissions When the organizer clicks Confirm on an alternative Then an event is created in the designated calendar at the selected time within 5 seconds And the event title matches the original request exactly And the event description contains the original agenda and links to the attached docs And conferencing details are provisioned and inserted into the event location or description And all requested participants are added as invitees with RSVP status "needsAction" And email and Slack notifications are sent to all invitees within 30 seconds containing final time and join details
Correct Organizer Ownership and Multi-Calendar Writeback
Given the meeting has a designated owner based on rotation rules And the owner’s calendar is connected to TimeMeld When the organizer clicks Confirm on an alternative Then the event organizer field is set to the designated owner account And the event is written to the owner’s primary calendar And for participants with connected calendars, the event is added or updated on their calendars And for participants without connected calendars, standard ICS invites are delivered And the rotation ledger is updated to reflect this occurrence assigned to the owner
Consent Prompt for Outside Preferred Hours
Given at least one required participant’s preferred hours exclude the selected alternative time When the organizer clicks Confirm Then a consent modal appears listing impacted participants and the time outside their window And the organizer must choose Request Consent, Override (if policy allows), or Pick Another Time And if Request Consent is chosen, consent requests are sent via email and Slack within 30 seconds And the event remains in Awaiting Consent state and is not sent as final until all required participants approve or the organizer overrides under policy And all approvals and declines are captured in the timeline with timestamps and actor identities
Recurring Series Scope and Series Logic
Given the request is part of a recurring meeting series When the organizer clicks Confirm on an alternative Then the organizer is prompted to select scope: This occurrence only, This and all following, or Entire series And the calendar is updated to reflect the chosen scope using recurrence exceptions where applicable And participants receive updated invitations that correctly reflect the chosen scope And the rotation ownership schedule is recalculated if scope affects future occurrences And the original meeting metadata remains consistent across affected occurrences
Conferencing Provisioning Failure Fallback
Given conferencing provisioning fails or times out within 10 seconds during confirm When the organizer clicks Confirm on an alternative Then the event is still created at the selected time without a conferencing link And a visible placeholder "Conferencing link to be added" is inserted in the event description And a retry job is queued and attempted per provider backoff policy And participants are notified that conferencing details will follow And a failure webhook is emitted with error code, provider, correlationId, and retry schedule
Success and Failure Webhooks with Timeline Traceability
Given an alternative is confirmed When the flow completes with success or failure Then a webhook is emitted within 5 seconds with eventId, meetingId, status (success|failure), selectedSlot, scope (single|series), organizerId, participantIds, and correlationId And the TimeMeld timeline is updated with a single entry containing the same correlationId, the tradeoff scores of the selected slot, and delivery status for email and Slack And in case of retries (e.g., conferencing), subsequent webhooks and timeline entries reference the same correlationId And no sensitive document contents or private notes are included in webhook payloads
True One-Click Confirmation From Alternatives List
Given the Humane Finder alternatives list is visible and no consent prompt is required And conferencing provider tokens are valid When the organizer clicks the Confirm button on a specific alternative Then the meeting is scheduled without any additional required inputs or screens And total user actions from alternatives list to scheduled state is one click And the UI shows a success toast within 3 seconds and auto-dismisses within 6 to 10 seconds And the confirmed alternative is marked as Scheduled and logged with its tradeoff scores in the timeline
Guardrail & Preference Sync
"As a participant, I want my working hours and focus blocks respected automatically so that suggestions fit my schedule without revealing private details."
Description

Continuously ingest and reconcile participant guardrails and preferences from calendars, TimeMeld profiles, and team policies: working hours, focus blocks, time-off, meeting-free days, minimum buffer, and meeting length caps. Provide conflict resolution rules (policy > profile > inferred) and incremental sync with backoff to avoid API throttling. Expose a unified availability model to the conflict detector and generator, with per-user privacy controls that hide sensitive event details while retaining busy/available signals.

Acceptance Criteria
First-Time Multi-Source Ingestion
Given a participant has a connected calendar, a TimeMeld profile, and an active team policy, When the initial sync job runs, Then working hours, focus blocks, time-off, meeting-free days, minimum buffer, and meeting length cap are ingested from all available sources. Given source data spans multiple time zones and includes DST transitions, When times are normalized, Then all intervals are stored in the participant’s primary timezone with UTC offsets preserved per occurrence. Given ingestion completes without fatal errors, When the unified availability model is built for the configured planning horizon, Then each field includes a provenance tag (policy, profile, inferred) and a lastUpdated timestamp. Given a field is missing in one source but present in others, When reconciliation occurs, Then the field value is taken from the highest-priority available source and the provenance reflects that source. Given initial sync completes, When persistence occurs, Then sync checkpoints (lastSyncAt per source and any provider sync tokens) are saved atomically.
Deterministic Conflict Resolution (Policy > Profile > Inferred)
Given a participant’s team policy sets working hours that differ from their profile, When reconciliation runs, Then the policy working hours override the profile values in the unified model. Given a profile defines a minimum buffer and an inferred default also exists, When reconciliation runs, Then the profile value overrides the inferred value. Given overlapping constraints (e.g., a profile focus block during a policy meeting-free day), When availability is computed, Then the stricter constraint (policy meeting-free day) prevails, marking that interval unavailable. Given the same input sources and values, When reconciliation runs multiple times, Then the unified availability output is identical across runs (deterministic). Given a lower-priority source changes while a higher-priority source remains unchanged, When reconciliation runs, Then the resulting unified value for that field does not change.
Incremental Sync with Backoff and Throttling Safety
Given provider sync tokens or ETags are available, When incremental sync runs, Then only changed or new items since the last checkpoint are fetched and applied. Given a calendar API responds with HTTP 429 or a Retry-After header, When retry logic executes, Then exponential backoff with jitter is applied, honoring Retry-After, up to the configured retry limit. Given throttling persists beyond the retry limit, When the sync loop evaluates, Then the job backs off for a longer scheduled delay and exits without hot-looping. Given a transient network error occurs mid-batch, When sync resumes, Then it continues from the last committed checkpoint without duplicating or losing applied changes. Given a large backlog exists, When sync proceeds, Then rate limits are not exceeded and progress metrics (items processed, duration, throttle events) are emitted for observability.
Unified Availability Model Exposure to Detector/Generator
Given the conflict detector requests availability for a time range, When the unified model is queried, Then it returns merged busy/available intervals with minimum buffers and meeting length caps applied to the availability calculation. Given the generator requests constraints for a participant, When the unified model is queried, Then the response includes per-field values (working hours, buffers, caps, meeting-free days) and their provenance (policy, profile, inferred). Given identical inputs (time range, participant set, source states), When the model is queried multiple times, Then the same intervals and constraint values are returned (idempotent and deterministic). Given an invalid query (e.g., end before start), When the model is queried, Then a validation error is returned without side effects. Given a daylight saving time transition within the requested window, When the model is queried, Then intervals accurately reflect the shift without overlapping or gaps beyond the source data.
Per-User Privacy Redaction Controls
Given a participant has privacy set to hide event details, When their availability is exposed to the detector/generator, Then only busy/available signals and permitted categories are returned; titles, descriptions, attendees, and locations are redacted. Given the same participant views their own data within TimeMeld, When availability is rendered for them, Then their own event details remain visible according to their permissions while others’ details remain redacted. Given cross-tenant sharing and no explicit consent, When availability is exposed, Then the most restrictive privacy setting is applied by default. Given logging and caching are enabled, When events are processed, Then sensitive fields are excluded from logs and only redacted views are stored in caches. Given a user changes their privacy setting, When the next sync or query occurs, Then the new redaction rules take effect for subsequent exposures.
Buffers, Focus Blocks, Time-Off, and Meeting-Free Days Handling
Given a policy defines meeting-free days, When availability is computed, Then no schedulable availability is returned for those days regardless of other source data. Given profile-defined focus blocks exist, When availability is computed, Then those intervals are treated as busy for scheduling purposes. Given a configured minimum buffer before and after meetings, When adjacent events are closer than the buffer interval, Then the busy intervals are expanded/merged to enforce the buffer. Given approved time-off spans multiple time zones, When availability is computed, Then the entire time-off interval is marked unavailable across the participant’s normalized timeline. Given overlapping focus blocks and time-off, When reconciliation occurs, Then the stricter unavailability (time-off) is retained for the interval in the unified model.
Equity Rotation Impact & Scoreboard Update
"As a team lead, I want meeting choices to update our fairness rotation automatically so that inconvenience is shared equitably over time."
Description

Calculate how each alternative affects meeting ownership rotation and equity scores, preventing repeated inconvenience for the same people and distributing off-hours impact fairly. On confirmation, atomically update the shared equity scoreboard, logging credits/debits and rationale. Provide guardrails to cap consecutive early/late meetings per participant and surface warnings if fairness thresholds would be exceeded. Integrates with reporting to track fairness over time and supports retroactive adjustments when attendees change.

Acceptance Criteria
Rotation Impact Scoring and Ranking
Given a conflicting meeting request with participants having defined working hours, existing equity balances, and configured weights (default rotation-impact weight = 40%) When Humane Finder generates alternative time slots Then each alternative includes per-participant credit/debit deltas, an overall rotation-impact score (0–100), and a composite tradeoff score with visible breakdown And alternatives are ranked deterministically by composite score; ties break by lowest timezone burden, then earliest in requester’s working hours And the top 5 alternatives render within 300 ms for up to 20 candidates And the UI reveals rotation-impact rationale per alternative, including before/after balances and consecutive early/late counters per participant
Guardrails for Consecutive Off-Hours Caps
Given org-level caps for consecutive early and late meetings (default 2 each) with optional per-user overrides When an alternative would cause any participant to exceed a hard cap Then the alternative is marked as blocked by guardrail, the Confirm action is disabled, and the impacted participant(s) and violated cap are displayed And when an alternative would meet but not exceed the soft threshold, a warning is displayed with current counter state And guardrail evaluation includes already scheduled meetings in the past 14 days and proposed alternatives in the current session
Atomic Equity Scoreboard Update on Confirmation
Given an organizer confirms a selected alternative When the confirmation is processed Then the equity scoreboard updates atomically: apply per-participant deltas, persist before/after balances, and write an audit entry with meetingId, seriesId, timestamp (UTC), actor, rationale, deltas, and version And the operation is idempotent via a confirmationId so retries do not duplicate entries And if calendar invite creation fails, the transaction is rolled back and an error is shown within 2 seconds And audit entries are immutable and queryable by meetingId and participant for at least 18 months
Retroactive Adjustments for Attendance Changes
Given attendees are added, removed, marked absent, or a meeting is canceled/rescheduled after confirmation When the change is finalized within the adjustment window (default 72 hours) Then the system recalculates fair deltas, posts adjustment entries with rationale, and updates balances without violating hard caps And affected participants are notified via email/in-app within 5 minutes with before/after balances and audit links And manual admin adjustments require a reason code and are recorded as compensating entries (no mutation of prior records)
Fairness Reporting Integration
Given a team with recorded equity transactions When the fairness report is viewed or the reporting API is called Then metrics are available per participant and team: cumulative credits/debits, current balance, consecutive early/late streaks, off-hours share %, and a fairness dispersion metric (Gini) And filters include date range, team, meeting series, and meeting type; responses return within 2 seconds for up to 10,000 transactions And data is exportable as CSV and accessible via /reports/fairness with pagination and OAuth2 scopes time:read and equity:read
Timezone and DST Robustness
Given participants across timezones and upcoming DST transitions or personal timezone changes When alternatives are scored and later confirmed during a DST boundary or after a user updates their timezone Then off-hours determination uses the participant’s effective local time at meeting occurrence And consecutive early/late counters roll over by local-day boundaries post-change with no double-counting across DST fall-back And a backfill job recalculates scores for affected upcoming meetings within 15 minutes of a timezone change and posts adjustments if required And automated tests cover at least 6 DST transition dates across NA, EU, and APAC
Timezone Normalization & DST Safety
"As an organizer, I want times displayed and scheduled correctly across timezones and DST changes so that no one joins at the wrong hour."
Description

Normalize all computations to a canonical time model with accurate per-user timezone detection, DST transitions, regional holidays, and short-notice changes. Validate suggested times against future DST shifts, handle ambiguous/nonexistent local times, and present localized times consistently across UI, emails, and calendar invites. Include regression tests for common DST edge cases and provide fallbacks when a locale database update is pending.

Acceptance Criteria
Canonical UTC Normalization for Scheduling Computations
Given organizers and attendees across at least three IANA timezones When Humane Finder computes and ranks alternative meeting windows Then all internal computations are performed in UTC with minute-level precision And the same input produces identical rankings regardless of the requester’s local timezone And each candidate retains per-attendee mapping of UTC start/end to local time via IANA TZID And no candidate’s computed local offset changes after normalization round-trip (UTC -> local -> UTC)
Per-User Timezone Detection and Override Persistence
Given a new user connects their calendar and visits the app When TimeMeld detects timezone from browser and calendar provider Then the stored timezone equals the provider’s IANA TZID by default And a mismatch greater than 30 minutes triggers a non-blocking prompt to confirm or override And a user-selected override persists across sessions and API responses And subsequent alternative-window computations use the persisted TZID
Future DST Shift Validation for Suggested Windows
Given suggested windows may occur after upcoming DST transitions in any attendee’s locale When Humane Finder generates alternatives for the next 12 months Then candidates that fall into nonexistent local times (spring-forward gaps) for any attendee are excluded And ambiguous local times (fall-back overlaps) are disambiguated to the earlier wall-clock occurrence with explicit offset labeling And no .ics payload is produced with DTSTART/DTEND that serialize to nonexistent local times And regression tests cover US, EU, and AU/NZ DST transition dates for the next two seasons
Handling Ambiguous and Nonexistent Local Times in UI and Invites
Given a candidate occurs on a DST transition day for any attendee When the candidate is displayed in UI and notification email and generated as a calendar invite Then the display includes local time, GMT offset, and zone abbreviation (e.g., 09:30 GMT-7 PDT) And a tooltip or detail view shows the canonical UTC timestamp And the .ics contains TZID and a correct VTIMEZONE block matching the attendee’s TZ rules And expanding the .ics with a standards-compliant parser yields the same local clock time as shown in the UI
Cross-Surface Localization Consistency (UI, Email, Calendar Invites)
Given a meeting alternative is selected and confirmed When viewed by each participant across web UI, email, and calendar client Then all surfaces present identical local clock time and offset for that participant And 12/24-hour format follows the participant’s locale preference And automated tests detect no cross-surface discrepancy greater than 1 minute or any offset mismatch And tradeoff scores shown reference the same localized time values used to compute timezone burden
Regional Holidays and Guard Compliance in Humane Alternatives
Given per-attendee regional holiday calendars and personal guard rules are enabled When a requested slot collides with a holiday or guard for any attendee Then Humane Finder excludes the conflicted slot and proposes nearest humane alternatives And ranking penalizes alternatives within 12 hours of a holiday for affected attendees And the UI shows an explanation chip listing affected regions/attendees and rule source And unit tests verify exclusion and penalty for at least US, IN, and AE public holidays
Timezone Database Outage/Update Fallbacks and Reconciliation
Given the timezone database for a locale is outdated or temporarily unavailable When TimeMeld must compute and present alternatives involving that locale Then the system uses last-known tz rules with explicit provisional labeling to users And candidates likely impacted by pending changes are highlighted and optionally deferred And once the tz database updates, the system automatically revalidates and reconciles affected events, notifying organizers of any changes And monitoring emits an alert when fallback mode is active for more than 1 hour

Focus Buffers

Auto-adds smart pre/post buffers around focus blocks and long meetings, adjusting length by meeting type and role. Prevents back‑to‑back context switching, preserves ramp‑up/down time, and improves on‑time starts and session quality.

Requirements

Dynamic Buffer Rules Engine
"As a remote product manager, I want buffer times to adapt to my role and meeting type so that I avoid back-to-back context switching and start sessions prepared."
Description

Compute and auto-apply pre/post buffer durations based on meeting type (e.g., standup, 1:1, design review), role (host, presenter, note-taker, attendee), meeting length, time of day, and context-switch intensity. Incorporate timezone fatigue and TimeMeld’s equity scoreboard signals to lengthen buffers for participants bearing off-hours load or heavy facilitation. Provide configurable defaults, min/max thresholds, and deterministic priority ordering when multiple rules match. Recalculate buffers idempotently on create/update/cancel events, ingesting metadata from invites (labels, templates) and series patterns. Outcome: consistently preserved ramp-up/down time and improved on-time starts without manual tuning.

Acceptance Criteria
Buffers by Meeting Type and Role
Given rule config maps (Design Review, Presenter) to pre=15m and post=10m And a 60-minute Design Review where the current user is the Presenter exists on the user's calendar When the rules engine computes buffers Then it creates a 15-minute pre-buffer immediately before and a 10-minute post-buffer immediately after the meeting on the user's calendar And both buffers are marked as busy and inherit the meeting's privacy setting And no existing non-buffer events are shifted or overlapped by the buffers Given rule config maps (Standup, Attendee) to pre=5m and post=0m And a 15-minute Standup where the current user is an Attendee exists When the rules engine computes buffers Then it creates only a 5-minute pre-buffer and no post-buffer
Timezone Fatigue and Equity Scoreboard Weighting
Given baseline buffers for a meeting compute to pre=10m and post=10m from type/role rules And the meeting starts at 22:00 local time for the current user And an equity scoreboard off-hours burden percentile >= 80% applies to the user And an off-hours multiplier of 1.5x and equity bonus of +5m are configured When the rules engine computes final buffers Then the user's buffers are increased to pre=20m and post=20m (10m * 1.5 + 5m), subject to threshold clamping And the increased buffers remain adjacent to the meeting And other participants without off-hours burden do not receive increased buffers on their calendars
Defaults and Min/Max Threshold Enforcement
Given no type/role/length/time-of-day rules match a meeting And global defaults are configured to pre=5m and post=5m When the rules engine computes buffers Then it applies pre=5m and post=5m Given computed pre-buffer is 40m and post-buffer is 1m And thresholds are configured as min=3m and max=30m When thresholds are enforced Then the pre-buffer is clamped to 30m and the post-buffer is raised to 3m And the final applied buffers equal the clamped values
Deterministic Rule Priority and Tie-Breaking
Given two rules match a meeting And Rule A has priority=90 and Rule B has priority=80 When the rules engine selects a rule Then Rule A is selected and applied Given two rules match with equal priority And Rule C matches (type, role, length) and Rule D matches (type, role) When the rules engine selects a rule Then Rule C (more specific) is selected and applied Given two rules match with equal priority and equal specificity And Rule E has updatedAt=2025-09-10T12:00:00Z and Rule F has updatedAt=2025-08-30T12:00:00Z When the rules engine selects a rule Then Rule E (most recently updated) is selected and applied Given two rules match with equal priority, specificity, and updatedAt And Rule G has ruleId="rule-01" and Rule H has ruleId="rule-02" When the rules engine selects a rule Then the rule with lexicographically smaller ruleId (rule-01) is selected And the same selection occurs on every recomputation with identical inputs
Idempotent Recalculation on Create/Update/Cancel
Given a meeting is created and eligible buffers compute to pre=10m and post=10m When the rules engine runs the first time Then exactly two buffer events are created adjacent to the meeting Given the rules engine runs again with no changes When it recomputes Then no additional buffer events are created and existing buffers are left unchanged Given the meeting start time is moved 15 minutes later When buffers are recomputed Then both buffer events shift to remain exactly adjacent, preserving their durations Given the meeting is canceled When buffers are recomputed Then all associated buffer events are deleted from the user's calendar
Invite Metadata and Series Pattern Ingestion
Given an invite contains label="Design Review" and template="DR-v2" When the rules engine evaluates rules Then it treats the meeting as type=Design Review regardless of the title text And applies the corresponding buffers Given a weekly recurring series with 10 occurrences When a series-level label is added that matches a rule Then buffers are applied to all future occurrences consistently Given a single occurrence is edited to have label="1:1" When rules are recomputed for the series Then the edited occurrence uses 1:1 buffers while other occurrences retain Design Review buffers
Context-Switch Intensity Scaling
Given the user's previous event ends immediately before the meeting and is categorized as Deep Work with intensity=0.9 And a role switch occurs from Note-Taker to Presenter And high-intensity multiplier=1.5x is configured When the rules engine computes the pre-buffer Then the pre-buffer equals base-pre * 1.5, subject to max threshold, and remains adjacent to the meeting Given the previous event and the meeting share the same category and role (low intensity) When the rules engine computes the pre-buffer Then the pre-buffer equals the base-pre with no intensity scaling applied
Calendar Auto-Block & Visibility Controls
"As an engineer, I want buffers to appear as private busy blocks on my calendar so that my time is actually protected without spamming colleagues with extra invites."
Description

Automatically create and maintain adjacent buffer events on connected calendars (Google Workspace, Microsoft 365) with correct duration, color, and privacy (default Private with minimal titles). Support selection of target calendar (primary or dedicated "Buffers" calendar), busy/free display options, and exclusion from attendee notifications. Keep buffers in sync when meetings are moved, extended, or canceled; handle recurring series. Provide offline queueing and rate-limit/backoff handling. Respect OOO/all-day events and working hours. Outcome: buffers are reliably enforced as actual protected time across integrated calendars.

Acceptance Criteria
Auto-create Adjacent Buffers on Meeting Creation (Google & Microsoft 365)
Given the user has connected Google Workspace or Microsoft 365 and enabled Focus Buffers with configured pre/post durations by meeting type and role And the user has selected a target calendar (Primary or a dedicated "Buffers" calendar) and a buffer color and Busy/Free setting When the user creates a new meeting within working hours Then pre- and post-meeting buffer events are created immediately adjacent to the meeting on the selected calendar And the buffer durations match the configured rules for the meeting type and organizer role And the buffer events are marked Private and display a minimal title "Focus Buffer" And the buffer events use the configured color And the buffer events include no attendees and trigger no notifications to any meeting participants And the buffer events’ free/busy status matches the user’s buffer visibility setting And the buffers appear within 10 seconds of meeting creation
Maintain Buffers on Meeting Move/Extend/Cancel
Given a meeting with existing adjacent buffer events When the meeting is moved to a new start time/date Then both buffer events shift to remain immediately adjacent to the meeting with original relative durations When the meeting is extended or shortened Then the buffer events adjust to remain adjacent without overlapping the meeting When the meeting is canceled Then the associated buffer events are deleted within 10 seconds And no orphan or duplicate buffer events remain And updates originating from any client (web, mobile, desktop) are detected and applied within 15 seconds
Offline Queueing and Rate-Limit/Backoff Reliability
Given the system loses connectivity or receives API 429/5xx responses from Google or Microsoft When buffer create/update/delete operations are required Then the operations are queued locally and retried with exponential backoff respecting provider rate limits And operations are idempotent to prevent duplicate buffer events And all queued operations succeed within 5 minutes of connectivity being restored (subject to provider availability) And no user-facing errors persist after successful retries
OOO/All-day Events and Working Hours Compliance
Given the user has defined working hours and may have Out of Office (OOO) or all-day events When a meeting is created or updated adjacent to OOO/all-day events or outside working hours Then buffers are only created within working hours and never overlap all-day or OOO events And if a buffer would fall entirely outside working hours or exclusively within an OOO/all-day block, that buffer is skipped And remaining valid buffers are created as usual and remain Private And skipped buffers are recorded in logs for auditability
Target Calendar Selection and Permissions
Given the user selects a dedicated "Buffers" calendar as the target and has write permission When buffers are created or updated Then all buffer events are placed on the selected "Buffers" calendar When the selected calendar is unavailable or lacks write permission Then the system falls back to the primary calendar and notifies the user in-app without blocking buffer creation And no buffers are attempted on calendars without write access And changing the target calendar only affects newly created buffers; existing buffers remain on their original calendars
Busy/Free and Privacy Visibility Controls
Given the user configures buffers to appear as Busy or Free and sets default privacy to Private with minimal titles When buffers are created or updated Then the buffer events’ transparency (Busy/Free) matches the user configuration And event visibility is Private with a minimal title "Focus Buffer" and no description And no attendees are added and no notifications are sent to any meeting participants And other viewers see only free/busy impact per configuration and cannot view buffer details
Conflict Resolution for Back-to-Back Meetings
Given two meetings are adjacent or near-adjacent such that their configured buffers would overlap When buffers are created or updated Then at most one buffer event exists between the two meetings And the single intermediate buffer has a duration equal to the greater of the two overlapping buffer durations and remains Private And buffers never overlap meetings or extend beyond working hours And no duplicate or fragmented buffer events remain after conflict resolution
Conflict Resolution & Rescheduling Intelligence
"As a team lead, I want the system to intelligently resolve buffer conflicts so that my core focus time isn’t broken and meetings still start on time."
Description

When buffer placement conflicts with existing events or focus blocks, apply policy-driven resolution: preserve hard focus blocks, shrink/expand buffers within min/max thresholds, or propose alternate meeting times via TimeMeld’s suggestion engine. Provide a preview of impacts before applying changes and a one-click rollback. Ensure series-aware adjustments and avoid fragmenting long focus sessions. Outcome: intelligent adjustments maintain ergonomics without disrupting critical commitments.

Acceptance Criteria
Policy-Driven Conflict Resolution Order
Given a buffer placement that conflicts with existing events and a hard focus block When TimeMeld evaluates the conflict Then it preserves the hard focus block unchanged per policy And it attempts buffer shrink/expand within policy-configured min/max thresholds And if the conflict persists, it generates alternate meeting times via the suggestion engine And no calendar changes are committed until the user confirms via the impact preview
Buffer Elasticity Within Policy Thresholds
Given pre/post buffers defined by meeting type and role with policy min/max durations And a buffer conflicts with an adjacent event When adjustment is attempted Then the buffer is reduced or expanded only within the configured min/max bounds And if a valid duration cannot be achieved within bounds, the buffer remains at the nearest bound And the system flags the event as requiring rescheduling suggestions instead of violating bounds
Alternate Meeting Time Proposals When Constraints Are Unsatisfied
Given a buffer conflict that cannot be resolved within policy thresholds without impacting a hard focus block When TimeMeld invokes the suggestion engine Then it returns at least 3 alternate time windows ranked by timezone-weighted ergonomic score ≥ the policy threshold And each suggestion preserves required min buffers, honors hard focus blocks, and respects participants’ working hours And each suggestion includes a reason code summarizing which constraints are satisfied and which conflicts are avoided
Impact Preview and One-Click Rollback
Given pending buffer adjustments and/or reschedules have been computed When the user opens the impact preview Then the preview lists all affected events (title, date/time, attendees), buffer duration deltas, and any moved occurrences And the user can Apply all changes with a single action And after applying, a one-click Rollback restores the exact prior state for all affected items within the current session And rollback events are logged in the audit trail with timestamps and actor
Series-Aware Adjustments for Recurring Events
Given a recurring meeting series where buffer placement for one occurrence causes a conflict When adjustments are applied Then the user can choose This occurrence only or All future occurrences And selecting All future occurrences applies consistent buffer logic across the series respecting per-occurrence exceptions And the system prevents partial updates that would leave inconsistent buffer lengths within the same recurrence rule unless explicitly chosen
Avoid Fragmenting Long Focus Sessions
Given a long focus block exceeding the minimum uninterrupted duration policy And a conflicting buffer adjustment would split the focus block into segments shorter than the minimum When TimeMeld resolves the conflict Then it does not split the focus block And it instead prioritizes rescheduling the adjacent meeting via suggestions or adjusts the meeting’s buffers within policy And the final schedule contains no focus segment shorter than the configured minimum
Personalization & Org Policy Templates
"As an ops admin, I want to define buffer policies by role and meeting type so that teams get consistent protection without manual setup."
Description

Enable users to create personal buffer profiles (e.g., heavier buffers before presentations, lighter after 1:1s) while allowing org admins to define team-wide templates mapped to roles, meeting types, and timezones. Support inheritance and precedence (org > team > user > meeting override), "Do Not Buffer" tags, exception windows, and work-hour alignment. Integrate with HRIS/SCIM for role and team syncing. Outcome: scalable, consistent adoption with room for individual ergonomics.

Acceptance Criteria
Policy Precedence Resolution: Org > Team > User > Meeting Override
Given an org template, a team template, a user profile, and a meeting-level override all define buffer values for the same meeting type When buffer computation runs for a scheduled meeting Then the applied values are selected strictly by precedence Org > Team > User > Meeting Override for each attribute (pre/post length, min/max) And unspecified attributes at a lower level inherit from the nearest higher level that specifies them And a resolution log records the winning source per attribute and the discarded sources with reasons And the same inputs produce identical outputs across repeated runs
HRIS/SCIM Sync Maps Roles/Teams to Templates
Given SCIM/HRIS provides a user with role and team attributes When an initial sync completes Then the user is assigned the correct org/team templates within 15 minutes and policies are evaluated for all future meetings And subsequent attribute changes received via webhook or polling update the mapping within 2 minutes and trigger recomputation of future buffers And if multiple templates match, the highest org-defined priority is applied; ties fall back to most specific (team over org) And if SCIM is unavailable, the last successful mapping persists and sync retries with exponential backoff without duplicating assignments And all mapping and changes are written to an audit log with timestamp, source, and result
User Personal Buffer Profiles by Meeting Type
Given a user creates multiple personal buffer profiles with per–meeting-type pre/post settings When the user selects a default personal profile Then it is applied to their meetings for types not explicitly set by higher-precedence org/team policies And when the user switches to a different profile, future meetings reflect the new settings within 60 seconds without altering meeting start/end times And validation prevents saving profiles with negative values or totals exceeding 60 minutes per side (error displayed with inline message) And a preview panel shows the effective pre/post buffer for a selected upcoming meeting and the source of each value
Respect "Do Not Buffer" Tags and Meeting-Level Flags
Given an event contains a configured "Do Not Buffer" tag (title keyword, label, or metadata flag) When buffer evaluation runs Then no pre or post buffers are added for that event, regardless of policy level And any previously scheduled buffers for that event are removed within 60 seconds And tag detection is case-insensitive and matches whole words from an admin-managed list And an entry in the resolution log states suppression due to Do Not Buffer with the detected token
Exception Windows Modify or Disable Buffers
Given an admin defines exception windows (disable buffers or cap to N minutes) scoped by org/team/timezone and meeting type When a meeting falls fully inside a disable window Then all buffers for that meeting are suppressed And when a meeting falls partially inside a cap window Then buffers are truncated so effective buffer inside the window does not exceed the cap, without changing the meeting time And the exception that applied is recorded in the resolution log with window ID and rule And outside the window, normal policy evaluation resumes
Work-Hour Alignment Across Time Zones
Given per-user working hours derived from calendar settings or org policy and the user's timezone When buffers would extend outside a user's working hours Then buffers are clipped at the workday boundary for that user without moving the meeting And for multi-timezone meetings, clipping is applied per attendee’s personal buffer blocks independently And if a clipped buffer would overlap another event on that user’s calendar, the buffer is further shortened to avoid overlap And a note in the resolution log indicates work-hour clipping with before/after durations
Calendar Updates and Non-Disruptive Invites
Given buffers are created, updated, or removed by policy evaluation When changes are applied Then calendar holds are added/updated/removed within 30 seconds, marked Busy and Private where supported, and do not send email updates to other attendees And meeting start/end times remain unchanged And operations are idempotent: repeating the same evaluation does not create duplicate holds And failures to write to the calendar are retried up to 3 times with backoff and surfaced in an error log
Inline Scheduler UI & Overrides
"As a designer, I want to see and tweak buffer times while scheduling so that I can adjust for special cases without breaking my overall preferences."
Description

Visualize pre/post buffer halos directly in TimeMeld’s scheduler and event detail views, showing computed durations and rationale (rule source, role, time-of-day). Allow one-click per-meeting overrides, series-level edits, and bulk apply. Include guardrails against going below minimum thresholds, undo/redo, keyboard shortcuts, and accessible interactions across web and mobile. Outcome: transparent, controllable buffers that users trust and can adjust quickly when needed.

Acceptance Criteria
Buffer Halos Visualization in Scheduler Grid
Given a user opens the TimeMeld scheduler on web or mobile, When events with eligible focus blocks or long meetings are rendered, Then pre- and post-buffer halos appear around each applicable event with visible duration labels (e.g., "Pre 15m", "Post 10m"). Given an event is selected or hovered, When the user invokes the buffer tooltip, Then the tooltip displays rationale including rule source, user role, and time-of-day modifier. Given the scheduler is zoomed or the viewport changes, When the grid re-renders, Then buffer halos remain aligned to event boundaries and scale accurately to the time grid. Given two buffer halos would visually overlap, When rendered, Then halos clearly indicate constraint state (e.g., striped pattern) without obscuring event details and remain selectable via keyboard and touch. Given a user navigates via keyboard, When focus moves across events, Then halos and tooltips are reachable with visible focus outlines and have accessible names and roles (WCAG 2.1 AA).
Event Detail View Shows Buffer Durations & Rationale
Given a user opens an event’s detail view, When the event has computed buffers, Then the view displays separate Pre and Post buffer durations and a rationale breakdown listing rule source, role, and time-of-day. Given an event is ineligible for buffers, When the detail view is opened, Then the UI shows "No buffer" with reason (e.g., "Short meeting under 10m") and does not show override controls. Given an event has constrained buffers due to adjacent events, When the detail view is opened, Then the UI indicates the constraint with an explanation and a link to preview the impacted time span on the scheduler. Given assistive technology is used, When the detail view loads, Then buffer fields, rationale, and states are announced with semantic labels and meet contrast requirements (WCAG 2.1 AA).
One-Click Per-Meeting Buffer Override
Given a user selects an eligible event, When they click "Override buffers", Then the event switches to manual mode and displays quick-select durations (e.g., 5m/10m/15m) and a custom input for Pre and Post. Given a user adjusts a buffer duration, When the new value is within allowed thresholds, Then a live preview updates on the scheduler and the Save action becomes enabled. Given a user inputs a value below the minimum threshold, When they attempt to save, Then the save is blocked, the invalid field is highlighted, and an inline message states the minimum allowed value. Given the user clicks "Reset to smart", When in manual mode, Then the buffers revert to computed defaults and manual mode is cleared. Given the override is saved, When the user re-opens the event on any device, Then the persisted manual values are shown and applied consistently in scheduling.
Series-Level Buffer Edit Applies to All Future Instances
Given a user opens a recurring event, When they choose "Edit series buffers", Then a scope selector is shown with options: This event only, This and following, Entire series. Given the user selects "This and following" or "Entire series", When they save, Then buffer changes apply to the correct set of future instances within 5 seconds for up to 200 upcoming events. Given some instances have per-event overrides, When a series-level change is initiated, Then the user is prompted to either preserve instance overrides or replace them; the chosen option is honored. Given time conflicts prevent the requested buffers on certain instances, When the series update runs, Then those instances are reported as exceptions with counts and reasons, and no partial saves occur for an instance. Given the series change completes, When the user views the series in scheduler and detail views, Then displayed buffers reflect the new series settings and any preserved overrides.
Bulk Apply Buffer Settings to Selected Events
Given a user multi-selects events via lasso, checkboxes, or filter (e.g., role=Engineer, type=Focus, date range), When they click "Bulk apply buffers", Then a bulk panel shows the target count and selected buffer options. Given the user confirms bulk apply, When processing starts, Then a progress indicator shows completion percentage and an estimated time remaining; the process is cancellable. Given some events are not eligible or conflict with policy, When bulk apply finishes, Then a summary lists successes, failures with reasons, and offers a retry for failed items. Given network latency or app suspend occurs, When bulk apply resumes, Then the operation is idempotent and does not duplicate changes. Given bulk updates complete, When the scheduler refreshes, Then all changed events display updated halos and rationales consistently across web and mobile.
Minimum Threshold Guardrails & Warnings
Given an organization minimum pre/post buffer is configured, When a user attempts to set a value below the minimum, Then the input is blocked at the minimum and a tooltip explains the policy. Given a user’s role has a higher minimum than the org baseline, When setting buffers, Then the role-specific minimum is enforced and surfaces in the rationale. Given applied buffers would cause overlap into locked events or outside working hours, When the user attempts to save, Then the UI proposes the nearest valid durations and disables "Save" until a valid selection is chosen. Given policy forbids overrides below minimum, When the user tries to force save, Then the action is prevented and logged, and a non-dismissable banner explains the restriction with a link to policy settings (if permissions allow).
Undo/Redo and Keyboard Shortcuts for Buffer Changes
Given the user has made buffer changes (per-event, series, or bulk), When they press Cmd/Ctrl+Z, Then the last buffer change is undone; when they press Shift+Cmd/Ctrl+Z, Then the change is redone. Given no further history exists, When undo or redo is invoked, Then the command is ignored and a subtle indicator shows "No more actions". Given the user is on mobile, When editing buffers, Then an on-screen Undo and Redo control is available and performs the same actions as keyboard shortcuts. Given an undo/redo occurs, When using a screen reader, Then the action and resulting state are announced. Given a new change is made after an undo, When the user attempts redo, Then the redo stack is cleared to maintain a correct action history.
Outcomes Analytics & Auto-Tuning
"As a CTO, I want analytics that show how buffers affect punctuality and overruns so that we can tune policies to maximize focus and meeting quality."
Description

Measure on-time starts, meeting overrun vs. planned, late-join rates, context-switch frequency, and focus block integrity to evaluate buffer effectiveness. Provide privacy-preserving, role- and team-level dashboards, export, and alerts. Use feedback loops and opt-in A/B tests to auto-tune default buffer lengths by meeting type and role, with clear change logs. Outcome: data-driven continuous improvement of buffer policies that increases attendance quality and reduces schedule churn.

Acceptance Criteria
Privacy-Preserving Role/Team Outcomes Dashboard & Export
Given a Team Lead with access to Team A selects Role = 'Engineer' and Time Range = 'Last 4 weeks', When they load the dashboard, Then aggregate metrics for on-time start rate, overrun %, late-join rate, context-switch frequency, and focus block integrity are displayed for the selection within 2 seconds. Given the selected cohort contains fewer than k=5 unique participants, When the dashboard is loaded, Then metric cards and charts are suppressed and a message "Insufficient cohort size" is shown. Given a valid cohort (k>=5), When the dashboard is displayed, Then no names, emails, event titles, or raw timestamps are shown and only aggregate values and anonymized cohorts are visible. Given a user clicks "Export CSV" for the current view and k>=5, When the export is requested, Then a CSV with the same aggregates and a data dictionary is downloaded within 5 seconds and contains no user identifiers or raw event data. Given a user lacks permission for Team A, When they attempt to access the dashboard or export, Then access is denied and no metric data is returned.
On-Time Start Metric Calculation
Given the on-time threshold is configured to 2 minutes, When a meeting host joins within 2 minutes of the scheduled start, Then the meeting is counted as on-time; otherwise it is late. Given multiple hosts exist, When computing the start time, Then the earliest host join time is used. Given a set of meetings in the date range, When computing the on-time start rate, Then cancelled meetings and meetings with zero attendees are excluded. Given a recurring series with 10 instances, When 8 are on-time, Then the on-time start rate is reported as 80%. Given a user opens the metric tooltip, When viewing the on-time start card, Then the definition and threshold value are displayed.
Overrun vs Planned Duration Metric
Given a meeting scheduled for 60 minutes with pre/post buffers of 10 minutes total, When the actual end occurs 73 minutes after the scheduled start, Then planned_end is 60 minutes and overrun_minutes is 13. Given a meeting ends before or at the planned_end, When computing overrun, Then overrun_minutes is 0. Given multiple meetings in a range, When computing overrun %, Then overrun % = meetings with overrun > 0 divided by total eligible meetings, excluding cancelled. Given the user opens the metric tooltip, When viewing overrun, Then the definition states buffers are excluded from planned duration.
Late-Join Rate Alerts
Given the late-join threshold is configured to 10% for Team A and Meeting Type = 'Weekly Sync', When the trailing 14-day late-join rate exceeds 10% with n>=50 attendees evaluated, Then a Slack alert is sent to the team's alerts channel with the metric, trend, cohort, and dashboard link. Given an alert was sent for the same metric and cohort within the last 24 hours, When the condition persists, Then no duplicate alert is sent in that window. Given team quiet hours are set to 20:00–08:00 local time, When an alert triggers during quiet hours, Then delivery is deferred to the next window start. Given a user changes the threshold to 15%, When the next computation runs, Then alerts are evaluated against the new threshold.
Context-Switch Frequency & Focus Block Integrity
Given two consecutive calendar events for a user have different categories or organizers and a gap < 10 minutes with no buffer between, When computing context-switch events, Then the transition counts as one context switch. Given a week of data per user, When aggregating to team level, Then context-switch frequency is computed as average context switches per user per week for k>=5 users. Given a focus block is scheduled for 90 minutes, When a meeting overlaps the block by >= 15 minutes, Then the focus block is counted as interrupted. Given focus block integrity is computed for a cohort, When aggregating for the dashboard, Then integrity = uninterrupted focus blocks / total focus blocks in range. Given out-of-office events are present, When computing these metrics, Then OOO blocks are excluded from both numerators and denominators.
Opt-In A/B Testing for Buffer Lengths
Given experimentation is enabled, When a user opts in, Then they are randomly and deterministically assigned per meeting type and role to control or variant with 50/50 split unless configured otherwise. Given assignment is made, When the user schedules meetings of the tested type, Then the assigned buffer policy is applied consistently for the experiment duration. Given a user opts out, When they schedule subsequent meetings, Then default (non-experiment) buffer policies are applied and the user is removed from analysis. Given non-participants, When they schedule meetings, Then experiment policies are never applied. Given an experiment info panel is opened, When a participant views it, Then they can see assignment, cohort definition, start/end dates, and opt-out control. Given experiment data is exported or displayed, When cohorts are smaller than k=5, Then aggregates are suppressed to preserve privacy.
Auto-Tuning Default Buffers with Change Logs and Guardrails
Given an experiment shows improvement of on-time start rate >= 5% absolute with 95% confidence and min sample size n>=200 meetings per arm, When evaluation completes, Then auto-tuning is eligible for that meeting type and role. Given eligibility is met, When auto-tuning applies, Then new defaults must remain within configured bounds (e.g., 5–20 minutes per side) and cannot change by more than 5 minutes per release. Given a change is applied, When the change logs are viewed by an admin, Then an entry shows timestamp, meeting type, role, previous defaults, new defaults, metrics summary, cohort size, confidence, and approver (system or admin). Given a rollback is initiated within 30 days, When executed, Then defaults revert to the previous values and a rollback log entry is recorded. Given impacted users next schedule a meeting of the affected type, When the new defaults are in effect, Then they see an in-app notice summarizing the change with a link to details. Given cohort size is below k or confidence is insufficient, When evaluation runs, Then no change is applied and a "criteria not met" entry is recorded.

Graceful Overrides

Enables controlled exceptions with reason codes and time‑bound waivers. If an override is necessary, the system suggests compensation (swap ownership, extend future buffer, grant make‑up focus time) and updates equity metrics—keeping urgency possible without normalizing violations.

Requirements

Override Request Flow with Time-Bound Waivers
"As a PM scheduling a critical cross-timezone meeting, I want to request a one-time waiver with a reason and end date so that we can meet urgently without permanently relaxing our team’s ergonomics."
Description

Provide a guided, in-context flow to request an override whenever a proposed meeting violates ergonomic constraints (e.g., outside comfort hours, insufficient buffer). The flow captures a mandatory reason code, scope (single meeting vs. window), waiver start/end, and optional notes; annotates the proposed event; and previews downstream effects. On approval, TimeMeld applies the waiver only within the specified window, auto-expires it, and restores normal constraints. The flow integrates with the scheduling engine, calendar connectors, and policy services, supports one-click initiation from conflict banners, and fails safely when required inputs or permissions are missing.

Acceptance Criteria
One-Click Override Flow Launch from Conflict Banner
Given a proposed meeting violates ergonomic constraints and displays a conflict banner When the user clicks "Request Override" Then the override form opens in-context within 1 second with meeting details prefilled (attendees, proposed time, violating rule) Given the form is opened from the banner When it renders Then scope defaults to "This meeting only" and the violating constraint is highlighted Given the form is open When the user cancels Then no changes are persisted and the conflict banner remains visible
Mandatory Reason Code and Time-Bound Waiver Inputs Validation
Given the override form is open When the user attempts to submit without selecting a reason code Then submission is blocked with an inline error "Reason code is required" Given the override form is open When scope "Time window" is selected Then start_at and end_at fields become required and are shown in the requestor's primary timezone Given start_at and end_at are entered When validation runs Then start_at <= end_at, the window length does not exceed the organization-configured maximum, and both times align to minute precision Given all required inputs are valid When the user submits Then the payload includes reason_code, scope, start_at, end_at, optional notes, and requestor_id
Downstream Effects Preview and Compensation Selection
Given required inputs are valid When the user clicks "Preview effects" Then the system displays projected equity impact, suggested compensation options (swap ownership, extend future buffer, grant make-up focus time) with computed values, impacted attendees, and waiver expiry within 2 seconds Given a compensation option is selected When the user proceeds to submit Then the selection is persisted and included in the request payload Given the preview is shown When the inputs change Then the preview recalculates within 1 second and indicates the last refresh time
Waiver Approval, Scope Enforcement, and Auto-Expiry
Given a request is approved by policy services When the scheduling engine re-evaluates the meeting Then the violating constraint is bypassed only within the specified scope/window, and all other constraints remain enforced Given end_at is reached When subsequent scheduling occurs Then the waiver no longer applies and normal constraints are restored automatically without user action Given multiple waivers exist When evaluating a meeting time Then the system applies a waiver only if at least one active waiver covers the meeting time and records the applied waiver IDs in the audit trail
Event Annotation in Calendar and Audit Logging
Given a waiver is approved and applied to an event When viewing the event in TimeMeld Then the event shows a "Waiver" badge with reason code and expiry for users with view permission Given a connected calendar integration is enabled When the invitation/update is sent Then the calendar description includes a standardized annotation with reason code, approver, and expiry timestamp Given any waiver lifecycle event occurs (request, approve, deny, expire) When it is processed Then an immutable audit record is created with timestamp, actor, fields changed, and related event ID
Fail-Safe Handling for Permissions and Service Failures
Given the requestor lacks override permission When attempting to submit an override Then submission is blocked with "Insufficient permissions" and no waiver is created Given a downstream service (calendar connector or policy service) is unavailable or returns an error When submitting or applying a waiver Then the system rolls back partial changes, shows an error with a correlation ID, and leaves scheduling unchanged unless an existing valid waiver covers the time Given a transient network interruption occurs while filling the form When connectivity is restored within 30 seconds Then the form state is recovered from local cache and the user can safely resubmit
Configurable Reason Codes & Policy Catalog
"As a workspace admin, I want to configure standard reason codes and approval rules so that overrides are consistent, auditable, and aligned with company policy."
Description

Deliver an admin-managed catalog of override reason codes with metadata: name, description, category, default duration limits, required approvals, and compensation presets. Policies define which roles/teams can use each code, maximum frequency, and visibility rules. Include versioning with effective dates, auditability of changes, and safe migrations so existing waivers map to the correct policy version. Expose a lightweight API for programmatic maintenance and enable localization for names/descriptions.

Acceptance Criteria
Create reason code with required metadata
Given I am an Org Admin with Manage Policies permission When I create a reason code with name, description, category, defaultDurationLimit (minutes), requiredApprovals, and compensationPresets Then the reason code is persisted with a unique ID And name is unique within the tenant (case-insensitive) And defaultDurationLimit is between 5 and 720 inclusive And requiredApprovals include only allowed approver roles And compensationPresets types are limited to {swap_ownership, extend_future_buffer, grant_focus_time} with positive numeric values And invalid payloads return 422 with field-level errors
Enforce policy roles, team scope, frequency, and visibility
Given a policy grants reason code RC1 to roles Product Manager and team Core Platform with maxFrequency 2 per person per rolling 30 days and visibility restricted When a user outside the permitted roles or teams attempts to view or select RC1 Then RC1 is not shown in the picker and API selection attempts return 403 When an eligible user has already used RC1 twice in the last 30 days Then selection is blocked with an error that includes the next eligible date And if alternative codes are configured, the UI presents them
Apply correct policy version by effective date
Given reason code RC1 has version v1 effective 2025-09-01 and version v2 effective 2025-10-01 When a waiver is created on 2025-09-15 Then v1 terms are applied and the waiver stores a reference to v1 When a waiver is created on or after 2025-10-01 Then v2 terms are applied And editing an existing waiver never changes its stored version And deprecating a version does not alter existing waivers And retrieving the policy as-of any timestamp returns the correct version
Audit trail for catalog and policy changes
Given audit logging is enabled When any reason code or policy is created, updated, versioned, published, or deprecated Then an immutable audit record is written with actor, timestamp, entity, version, and field-level diffs And audit records are queryable by entity, actor, and date range, and exportable as CSV And attempts to modify or delete audit records are rejected
Safe migration mapping for existing waivers on policy update
Given active waivers exist for RC1 under policy version v1 When an admin publishes version v2 that changes requiredApprovals and maxFrequency Then all existing waivers retain their v1 linkage and remain valid And a migration report lists counts by outcome (retained, conflicts, invalid references) And any conflicts are flagged for follow-up without blocking current waivers And designated admins receive a notification with a link to the migration report
Lightweight API with auth, idempotency, and concurrency controls
Given a valid OAuth2 access token with scope policy:write When a client POSTs a new reason code with an Idempotency-Key header Then the operation is idempotent for 24 hours and returns 201 with the created resource When a client PATCHes a policy version with an If-Match ETag Then requests with a stale or missing ETag return 412 And unauthenticated requests return 401 and unauthorized scopes return 403 And the API enforces 100 requests per minute per client with 429 on excess And the 99th percentile latency for GET /reason-codes and GET /policies is under 500 ms measured over 5 minutes
Localization of names/descriptions with fallback
Given the default locale is en-US and translations exist for fr-FR and es-ES When the UI or API is requested with Accept-Language: fr-FR Then reason code name and description are returned in French; otherwise they fall back to en-US And admins can add, update, and delete locale-specific strings without changing the base code ID And missing translations are listed in an exportable gaps report And name length is <= 120 characters and description length is <= 500 characters and both accept UTF-8 characters
Approval Workflow & Multi-Channel Notifications
"As a meeting owner, I want to receive and act on override requests with clear context and deadlines so that I can balance urgency with team well-being."
Description

Implement flexible approval routing based on policy (e.g., meeting owner, team lead, or on-call approver) with SLA timers and escalation paths. Provide actionable notifications in-app, email, and Slack with one-click approve/deny and required rationale on denial. Surface full context (reason code, waiver duration, affected participants, ergonomic impact) and reflect decision state in real time across TimeMeld and calendar annotations. Persist approval outcomes with timestamps and approver identity.

Acceptance Criteria
Policy-Based Approval Routing Selection
Given an override request with a policy requiring approval by the meeting owner or, if unavailable, the team lead, and otherwise the on-call approver When the request is submitted Then the system routes the approval request to the first available approver per policy and records the selected approver and policy path And if the primary approver has an out-of-office event overlapping the waiver window, the system skips to the next approver in the policy And the routed approver count and identities are visible in the request details And no more than one active approver is assigned at a time unless the policy explicitly requires multiple approvers
SLA Timers and Escalation Path
Given an approval request with a 30-minute SLA and an escalation path to the team lead When the SLA timer starts at submission time Then the timer is visible to requester and approver with remaining time And if no action is taken by SLA expiry, the request auto-escalates to the team lead and the original approver is notified And all SLA start, pause (if any), expiry, and escalation events are timestamped and stored And if the escalated approver acts, the timer stops and logs the approver who acted
Multi-Channel Actionable Notifications
Given an approval request is created When notifications are dispatched Then the requester and current approver receive actionable notifications in-app, by email, and via Slack within 15 seconds And each channel presents Approve and Deny actions as one-click options And actions taken from any channel update the request exactly once (idempotent) and reflect in all channels within 10 seconds And notification delivery status (sent/succeeded/failed) is logged per channel
Denial Requires Rationale
Given an approver chooses to deny an override request When the approver initiates the Deny action from in-app, email, or Slack Then the system requires a rationale entry before submission And denial cannot be completed without at least 10 characters of rationale And the rationale is stored with timestamp and approver identity and shown to the requester in the request details And the requester receives a denial notification including the rationale summary
Context Visibility in Approval UI
Given an approver opens the approval notification or modal When the approval view is rendered Then it displays reason code, waiver start/end time, affected participants list, ergonomic impact score and highlights, and proposed compensation options And links to the impacted calendar event and participant time zones are available And all values match the underlying request payload and policy at time of render
Real-Time Decision State Sync and Calendar Annotation
Given an approval decision (approve or deny) is recorded When the decision is saved Then the request status updates across TimeMeld UI for requester and approver within 10 seconds And the associated calendar event gains or updates an annotation reflecting Approved/Denied, approver identity, and timestamp And equity metrics and meeting ownership rotation are recalculated if approved and visible on the scoreboard within 60 seconds And stale notifications are marked resolved across all channels
Audit Trail Persistence and Queryability
Given any approval lifecycle event occurs (submission, reroute, approve, deny, SLA escalation) When the event is stored Then the audit record includes event type, timestamp (UTC), actor identity, channel of action, policy version, and request ID And records are immutable and retrievable by request ID and date range via admin audit view And export to CSV includes all fields with consistent headers
Compensation Suggestion Engine
"As a team lead, I want the system to suggest fair compensation options when an override is used so that the burden is distributed and focus time is protected."
Description

When an override is proposed or approved, compute ergonomic debt and generate ranked compensation options such as rotating meeting ownership, extending future quiet-time buffers, or scheduling make-up focus blocks. Show predicted equity impact and calendar feasibility, allow selection of one or more options, and apply them automatically on approval (including calendar updates and reminders). Provide policy hooks to require compensation for certain codes and guard against double-compensation.

Acceptance Criteria
Compute Ergonomic Debt on Override Proposal
Given an override is proposed or approved with a meetingId, scheduled datetime, participants, and a reason code When the Compensation Suggestion Engine is triggered Then it calculates an ergonomic debt score using the configured policy and current participant contexts And persists the score and inputs as an immutable record linked to the overrideId and meetingId And exposes the score via UI and API within 2 seconds And the computation is deterministic for identical inputs
Ranked Compensation Options Generation
Given an override has an ergonomic debt score When the engine generates compensation options Then it produces a ranked list including, if feasible, at least one option from each category: ownership swap, future quiet-time buffer extension, make-up focus block And each option includes a predicted equity delta (numeric), feasibility status, and earliest applicable time window And options are sorted by descending equity benefit, then feasibility score, then deterministic tiebreaker And if fewer than three options are feasible, the engine still returns all feasible options with rationale codes
Display Impact and Feasibility in Override Modal
Given compensation options have been generated for an override When a user opens the override modal Then each option displays the predicted equity delta, a feasibility indicator, and the earliest application window And hovering or expanding an option reveals conflict reasons, if any And the list order in the UI matches the engine’s ranking And values are updated in the UI within 2 seconds of any input change
Multi-Select Compensation With Compatibility Validation
Given the user is viewing suggested compensation options for an override When the user selects one or more options Then the system validates compatibility rules and prevents mutually exclusive combinations with an explanatory message And it displays a combined compensation preview showing total predicted equity delta and affected calendars And the Confirm button remains disabled until validation passes
Automatic Application on Approval
Given the user has selected valid compensation options and approves the override When the approval action is submitted Then the system applies all selected options atomically: updates equity metrics, creates/updates calendar events/blocks/invites, and schedules reminders And all calendar changes are reflected on participants’ calendars within 10 seconds And the operation is idempotent on retried submissions and emits a single audit log entry And on partial failure, no changes persist and a clear error is surfaced with retry guidance
Policy Hooks Enforcing Required Compensation by Reason Code
Given a reason code is configured as requiring compensation with a minimum equity delta or specific option types When a user attempts to approve an override without satisfying the configured policy Then approval is blocked with a message specifying unmet requirements and suggested options to satisfy them And when the policy is updated via the admin API, enforcement reflects the new configuration on the next evaluation without service restart
Double-Compensation Guard and Deduplication
Given an override for a meetingId already has compensation applied or scheduled When a new override is proposed for the same meetingId or overlapping participant/time window within the configured deduplication horizon Then the engine excludes already-applied compensation from suggestions and prevents double counting toward equity metrics And attempts to reapply the same option are blocked with a clear deduplication message And idempotent retries of the same approval do not create duplicate calendar items or equity updates
Equity Scoreboard Adjustment & Visibility
"As a team member, I want the equity scoreboard to reflect overrides and compensations so that I can see that late/early burdens are tracked and rotated fairly."
Description

Extend the shared equity scoreboard to account for overrides and applied compensations, updating fairness metrics (e.g., off-hours load, ownership rotation, buffer integrity) at individual and team levels. Display clear annotations for override-driven changes, include filters by time range, reason code, and team, and prevent gaming via caps and normalization rules. Provide drill-down to the underlying events and expose read APIs for BI tools.

Acceptance Criteria
Override Adjustments Reflected in Equity Scoreboard Within 5 Minutes
- Given a user applies an override with a valid reason code and selected compensation, When the override is saved, Then the individual and team fairness metrics (off-hours load, ownership rotation, buffer integrity) are recalculated and visible on the equity scoreboard within 5 minutes (p95). - Given the same override event is processed more than once, When recalculation runs, Then metrics remain consistent and are not double-counted (idempotent). - Given the recalculation fails, When the user views the scoreboard, Then a non-blocking "pending recompute" indicator appears with last computed timestamp and the system retries within 1 minute until success. - Given an audit log is requested, When the override ID is queried, Then the audit log shows previous metric values, new values, compute time, and the actor ID.
Annotated Scoreboard Entries for Overrides and Compensations
- Given a scoreboard row affected by an override, When the row renders, Then an annotation badge is displayed with reason code, waiver window, compensation type(s), actor, and timestamp via tooltip and accessible label. - Given a user toggles "Show override annotations" off, When the scoreboard renders, Then annotations are hidden without affecting metric values. - Given the scoreboard is exported (CSV) or fetched via API, When the affected rows are included, Then annotation fields are present (override_id, reason_code, compensation_types, waived_until). - Given multiple compensations are attached to a single override, When the annotation is displayed, Then all compensation types are listed and totals are correctly reflected.
Filter Scoreboard by Time Range, Reason Code, and Team
- Given a user selects a custom date range, reason code(s), and team(s), When Apply Filters is clicked, Then the scoreboard results reflect the intersection of all selected filters and the summary totals match the filtered set. - Given no results match the selected filters, When the scoreboard loads, Then an empty state is shown and exports return an empty dataset with headers only. - Given a dataset of up to 5,000 events in the filtered range, When the scoreboard loads, Then first render completes within 2 seconds on a median laptop over a standard broadband connection. - Given browser refresh, When returning to the scoreboard, Then the last-used filters persist for the user.
Caps and Normalization Prevent Gaming Behavior
- Given an individual accumulates compensation credits from overrides, When credits exceed 2 units in a rolling 30-day window, Then further credits are capped and the scoreboard displays a capped indicator with the overage amount. - Given a single override would increase off-hours load contribution beyond 2x the team median for the selected period, When metrics are computed, Then the contribution is winsorized to 2x and an annotation indicates normalization applied. - Given a user triggers more than 3 convenience overrides within 14 days, When compensation would normally be awarded, Then the compensation is withheld and the event is flagged for review with a visible note on the scoreboard. - Given an admin updates cap and normalization thresholds, When saved, Then changes are applied to subsequent recomputes and the change is written to the audit log with effective timestamp.
Drill-Down from Scoreboard to Underlying Events
- Given a user clicks an individual's score, When the drill-down panel opens, Then it lists underlying events with columns: event_id, datetime (with timezone), reason_code, compensation, ownership, and impact deltas. - Given more than 50 events match, When the panel loads, Then results are paginated (50 per page) with sortable columns and search by event_id. - Given the user has Viewer permissions, When opening the drill-down, Then personal calendar details are redacted; with Admin permissions, full details are shown. - Given the user clicks "Export events", When the file is generated, Then the CSV contains exactly the events in the current filtered view within 10 seconds.
Read API Provides Equity Metrics and Annotations for BI Tools
- Given a BI tool issues GET /equity/scoreboard with team, date_range, and reason_code parameters, When the request is authorized, Then the response includes aggregate metrics and per-user rows with annotations (override_id, reason_code, compensation_types) in a documented schema (OpenAPI) and HTTP 200. - Given a client provides If-None-Match with the last ETag, When no data has changed, Then the API returns HTTP 304 within 500 ms. - Given a large result set (>10,000 rows), When the client uses cursor-based pagination (cursor, limit), Then each page returns within 1 second with a next_cursor until completion. - Given invalid parameters or unauthorized access, When the request is processed, Then the API returns appropriate errors (400, 401, 403, 429) with machine-readable error codes.
Override Limits, Cooldowns, and Guardrails
"As an ops manager, I want limits and cooldowns on overrides so that urgent exceptions don’t become the norm."
Description

Enforce policy-defined ceilings for overrides per user/team per timeframe, with warning thresholds and cooldowns. Offer soft blocks with justification prompts and hard blocks for non-exempt roles or exceeded limits, with admin override capability. Provide real-time feedback during scheduling, summarize current quota usage, and surface trends to admins to identify hotspots and policy tuning opportunities.

Acceptance Criteria
Per-User Rolling Quota With Warning Threshold
Given tenant policy: user_override_limit=5 per rolling_30_days and warning_threshold=80% And user U has used 3 overrides in the last rolling_30_days When U initiates an override in the scheduler Then the override is permitted And the UI shows "2 remaining (60% used)" with no warning banner And an audit event "override_attempt" is recorded with used=3, limit=5, threshold_crossed=false Given tenant policy: user_override_limit=5 per rolling_30_days and warning_threshold=80% And user U has used 4 overrides in the last rolling_30_days When U initiates an override in the scheduler Then the override is permitted And a non-blocking warning "Override quota nearly reached" is shown And an audit event is recorded with used=4, limit=5, threshold_crossed=true Given tenant policy: user_override_limit=5 per rolling_30_days And user U has used 5 overrides in the last rolling_30_days When U initiates an override in the scheduler Then the scheduler transitions to guardrail_block state And the decision engine evaluates soft vs hard block based on role and exemptions
Per-Team Rolling Quota Enforcement
Given tenant policy: team_override_limit=20 per rolling_30_days and warning_threshold=75% And Team T has used 15 overrides in the last rolling_30_days When any member of Team T attempts an override Then the override is permitted And the team usage widget shows "5 remaining (75% used)" with a warning banner And an audit event records team_used=15, team_limit=20, team_threshold_crossed=true when usage >= 75% Given tenant policy: team_override_limit=20 per rolling_30_days And Team T has used 20 overrides in the last rolling_30_days When any member attempts an override Then the scheduler transitions to guardrail_block state And block reason includes "team_limit_reached"
Cooldown Between Overrides
Given tenant policy: user_cooldown=48h between overrides And user U completed an override 12h ago When U attempts another override Then a soft block modal is shown indicating "Cooldown 36h remaining" And proceeding requires selecting a reason code and submitting a justification And an audit event "cooldown_bypass_requested" is recorded with remaining_cooldown=36h Given tenant policy: user_cooldown=48h between overrides And user U completed an override 0h ago And role=non_exempt When U attempts another override Then a hard block is enforced with action disabled And message "Cooldown active (48h remaining). Contact admin for override." is displayed
Soft Block With Justification And Time-Bound Waiver
Given limit reached or cooldown active And role is exempt OR tenant policy allows soft_block_on_limit=true When the user attempts an override Then a modal requires: - selection of a reason_code from the configured list - entry of free-text justification (minimum 20 characters) - confirmation of waiver_expiry within policy bounds (<= 7 days) And the modal displays at least one compensation suggestion (swap ownership, extend buffer, make-up focus time) with a preselected default And on submit, the override is scheduled And the audit log stores reason_code, justification_hash, waiver_expiry, selected_compensation And equity metrics are updated per selected compensation
Hard Block For Non-Exempt Or Exceeded Without Waiver
Given user or team limit is exceeded OR cooldown is active And role=non_exempt When the user attempts an override Then scheduling actions to confirm override are disabled And a hard block banner explains the violated guardrail and next steps And a "Request admin override" control is available And no meeting is scheduled until an admin approves
Admin Override Capability And Auditability
Given a hard block has been triggered for an override attempt And an admin with override_permission opens the request When the admin approves with a reason_code, waiver_expiry within policy bounds, and a selected compensation option Then the override is scheduled immediately And user/team counters are updated according to policy (counted_with_waiver=true) And equity metrics update is applied And a complete audit trail is recorded including approver_id, timestamp, prior_usage, post_usage, and policy_snapshot And the affected user receives a notification summarizing the override and compensation
Real-Time Feedback And Admin Insights
Given the scheduler is open for a user in a tenant When the user selects a time that requires an override OR toggles "Require override" Then the quota usage panel updates within 300 ms to show: user used/limit/remaining/percent, team used/limit/remaining/percent, cooldown remaining, and block state (none/warning/soft/hard) And all values reflect the latest persisted events within 1 second of any new override action Given an admin opens the Override Insights dashboard When data loads Then the dashboard shows: top 10 users and teams by override rate (last 30 days), trend of overrides per day with soft vs hard breakdown, distribution by reason_code, hotspots where warning_threshold crossed > N times/week (configurable), and CSV export control And data freshness is no older than 15 minutes
Audit Trail & Compliance Exports
"As a compliance officer, I want a complete audit log of overrides and approvals with export capabilities so that we can satisfy audits and internal reviews."
Description

Capture an immutable, searchable log of override lifecycle events (request, edits, approvals, expirations, compensations applied), including who, when, what changed, policy version, and communication artifacts. Support scoped access via RBAC, retention controls, and PII minimization. Provide CSV/JSON exports and signed webhooks for SIEM/BI ingestion, enabling SOC 2–friendly evidence collection and incident postmortems.

Acceptance Criteria
Immutable Override Lifecycle Audit Logging
Given an override lifecycle action (request, edit, approve, expire, compensation-apply) is committed When the operation completes Then an append-only audit event is written with fields: event_id (ULID), event_type, override_id, actor_user_id, actor_role, affected_user_ids, timestamp_utc (ISO 8601), policy_version_id, change_diff (JSON Patch), reason_code, communication_artifact_refs[], request_id, source_ip, user_agent, event_hash, prev_event_hash Given an audit event exists When any update or delete of that event is attempted via API, UI, or database interfaces Then the mutation is rejected, no original data is altered, and a tamper_attempt event is recorded with actor_user_id and context Given a sequence of K lifecycle actions for override_id=X When querying audit events by override_id=X Then exactly K events are returned in ascending timestamp order and the hash chain validates end-to-end Given storage corruption or a hash mismatch is detected When the affected event is read Then integrity_status=failed is returned, the event is excluded from default exports, and an alert is sent to org admins within 5 minutes
Audit Log Search, Filtering, and Latency
Given a user with permission View Audit Logs submits a query filtered by date range (<= 90 days), event_type, actor_user_id, override_id, reason_code, and policy_version_id When the query executes over up to 10,000 matching events Then the first page of results (page_size<=100) returns within 2 seconds and includes total_count, page, page_size Given a query contains no matches When executed Then 200 OK is returned with an empty results set and total_count=0 Given a result row is returned When inspected Then it includes all required fields and omits masked PII fields by default (see PII policy) Given a sort order is specified (timestamp_utc asc|desc) When the query executes Then results are deterministically ordered and stable across repeated queries with the same parameters
RBAC-Scoped Access and PII Minimization
Given a user with Role=Org Auditor When accessing audit logs Then they can view events for their organization scope with actor_user_id and affected_user_ids displayed as stable IDs; emails and full names are redacted unless the View PII permission is granted Given a user with Role=Team Lead When accessing audit logs Then they can only view events for teams they manage and cannot view communication content bodies—only artifact references (e.g., message URLs, message_ids) Given a user without scope to an event When attempting access Then access is denied with HTTP 403 (or UI equivalent), and a denied_access audit event is recorded Given PII minimization is enabled by default When events are stored Then direct PII values (emails, phone numbers, message bodies, meeting descriptions) are not stored in cleartext; emails are stored as salted hashes, message bodies are not stored—only references; exports and webhooks inherit the same masking rules unless View PII is granted
Retention Policy and Legal Hold Controls
Given an org-level retention policy is set between 30 and 1825 days (inclusive) When an event ages beyond the configured retention period Then it is purged from hot storage within 24 hours and excluded from searches, exports, and webhooks Given a legal hold is placed on an override_id, actor_user_id, or date range When retention would otherwise purge matching events Then those events are retained until the hold is released; all hold create/release actions are themselves auditable events Given an event is purged When reconciliation is performed Then a non-PII tombstone record (event_id, purge_timestamp, purge_reason) remains for 90 days to support audit counts without revealing content
CSV/JSON Export Integrity and Schema Compliance
Given a user with permission Export Audit Logs requests an export (CSV or JSON) with filters (date range <= 90 days, event_types, actor_user_id, policy_version_id) When the export is generated for up to 1,000,000 events Then a file is produced within 5 minutes, available via a signed URL expiring in 24 hours, and includes a manifest (export_id, schema_version, generated_at_utc, record_count, SHA256 checksum) Given a CSV export is downloaded When inspected Then it is UTF-8 encoded with a header row matching the documented schema, uses RFC 4180 quoting, and has exactly record_count data rows Given a JSON export is downloaded When inspected Then it is newline-delimited JSON (NDJSON) with each object conforming to schema_version; the manifest checksum matches the file content Given the same export parameters are used again without new events When a new export is requested Then the record_count and checksum are identical, and rows are sorted by timestamp_utc asc
Signed Webhook Delivery for SIEM/BI Ingestion
Given a webhook destination is configured with endpoint URL and shared secret When a new audit event is created Then a POST is sent within 5 seconds containing the event JSON body and headers X-TimeMeld-Timestamp and X-TimeMeld-Signature (HMAC-SHA256 over timestamp||payload); the event includes an Idempotency-Key header Given the destination responds with HTTP 2xx When processing Then the delivery is marked delivered and no retries occur Given the destination responds with 5xx or times out in 10 seconds When processing Then retries are attempted with exponential backoff and jitter up to 10 times over 24 hours (at-least-once delivery); duplicate deliveries carry the same Idempotency-Key Given a secret rotation is initiated When webhooks are sent during the rotation window Then signatures using either old or new secret are accepted for 1 hour, and a test delivery endpoint verifies signatures on demand Given repeated 4xx errors (>=10 within 10 minutes) When monitoring Then the endpoint is auto-disabled and an alert is sent to org admins
SOC 2 Evidence Pack and Timeline Reconstruction
Given an auditor requests an evidence pack for period [start, end] When generation is initiated Then the pack includes: export manifest (hashes, counts), RBAC configuration snapshot, retention policy snapshot, webhook delivery summary (success/failure counts, retry logs), and 30 randomly sampled override audit trails with full lifecycle coverage; the pack is delivered as a ZIP with a signed manifest (SHA256) within 10 minutes Given an evidence pack is provided When validation is performed Then every sampled trail contains the required lifecycle events (request, approval/denial, edits, expiration, compensation), each with integrity-verified hash links and policy_version_id present Given evidence generation detects missing or corrupt records When assembling the pack Then generation fails atomically with a detailed error report; no partial pack is released; an alert is sent to org admins Given a pack is generated successfully When accessed Then it is retrievable via a one-time URL valid for 7 days and retained under legal hold for 30 days

Drift Radar

Surfaces attempted and actual guard breaches by team, timezone, and hour. Sends early alerts when risk rises and recommends schedule or policy tweaks to realign, so maker hours stay intact as calendars and priorities evolve.

Requirements

Guard Breach Detection Engine
"As an ops lead, I want accurate detection of attempted and actual guard breaches across timezones so that I can quantify drift and intervene before focus time erodes."
Description

Implements a unified guard policy model (maker hours, no‑meeting windows, meeting caps, working hours, and per‑team exceptions) and a detection pipeline that ingests scheduled events and proposed invites. Normalizes all timestamps to participant local timezones, classifies events as attempted vs. actual breaches, assigns severity and reason codes, and persists results for analytics. Supports near‑real‑time processing, idempotent replays, backfill from calendar history, and performance at org scale.

Acceptance Criteria
Timezone Normalization for Multi‑Participant Events
Given a scheduled event or proposed invite with attendees across at least two IANA timezones (including one with DST and one with a 30/45‑minute offset) When the event is ingested by the detection engine Then start and end times are computed per participant’s local timezone using the correct tz rules effective at the event time And guard evaluation uses the participant’s local calendar day and working hours And events crossing local midnight are evaluated against the correct day’s policies on both sides And events on DST transition days (skipped or repeated hours) retain the intended wall‑clock time without off‑by‑one‑hour errors And the persisted record includes UTC timestamps plus per‑participant local timestamps and tzid
Attempted vs. Actual Guard Breach Classification
Given a proposed invite not yet added to participants’ calendars that violates any guard for any participant When processed Then it is classified as Attempted with the violating participants and guard types recorded Given a calendar event with status confirmed/accepted that violates any guard When processed Then it is classified as Actual with the violating participants and guard types recorded Given an event or invite is cancelled or withdrawn When processed Then any open breach records for its (event_id, sequence) are marked resolved and excluded from active analytics
Policy Precedence and Per‑Team Exception Handling
Given org‑level guard policies and a team‑level exception for a participant When evaluating a time window Then the exception overrides the org default for that participant and guard type And evaluation order is: team exception > team policy > org policy; first match applies And a breach is recorded if any applicable guard is violated for a participant unless an explicit exception exempts that guard for the evaluated time window And policy version effective_at timestamps are honored so historical events use the policy version in force at the event time
Severity and Reason Code Assignment
Given one or more violated guards for an event or invite When assigning severity Then severity is determined by the highest applicable rule across all violations and participants: - S1 Critical: any no‑meeting window violation OR maker‑hours overlap ≥ 30 minutes for any participant - S2 High: maker‑hours overlap > 0 and < 30 minutes OR daily meeting cap exceeded by ≥ 2 for any participant - S3 Medium: daily meeting cap exceeded by 1 OR working‑hours violation > 30 minutes outside maker hours - S4 Low: working‑hours violation ≤ 30 minutes outside maker hours And each violation includes at least one machine‑readable reason code from {G01_MAKER_HOURS, G02_NO_MEETING_WINDOW, G03_MEETING_CAP, G04_WORKING_HOURS} and a human‑readable message And the persisted record lists impacted participants, per‑participant overlaps in minutes, and the final severity level
Streaming Processing Guarantees (Latency & Idempotence)
Given creation, update, or cancellation events arriving from calendars and invite proposals When processed under steady‑state load of 500 events/second system‑wide (≤ 20 events/second per org) Then end‑to‑end detection latency (ingest to persisted breach record) is p95 ≤ 2s and p99 ≤ 5s with error rate < 0.1% Given duplicate deliveries or replays of the same event identified by (event_id, sequence) When processed any number of times in any order Then exactly one breach record exists per unique (event_id, sequence, participant, guard_type); later higher sequence supersedes earlier; equal/lower sequences are deduplicated without changing outcomes And all operations are retriable without side effects (idempotent) and carry a stable correlation_id for traceability
Historical Backfill Accuracy and Completeness
Given a backfill request for a time range (e.g., past 90 days) for an org When executed Then 100% of calendar events in scope are evaluated and breach records are produced consistent with the policy versions effective at each event time And backfill is partitioned to support at least 50,000 users and 30M events with progress checkpoints and restartable jobs And the engine produces identical results between backfill and streaming for the same events (hash equality on normalized breach payloads)
Result Persistence and Queryability
Given a detected breach (attempted or actual) When persisted Then the record includes: org_id, team_id (if available), event_id, sequence, participant_id, attempted_or_actual, violated_guard_types[], reason_codes[], severity, utc_start/end, local_start/end, tzid, overlap_minutes_by_participant, detection_timestamp, policy_version, processing_version, correlation_id, and resolution_status And querying breaches grouped by team, timezone, and hour for the last 30 days completes in p95 ≤ 200 ms for orgs up to 5,000 users and 5M breach records with correct aggregates And soft‑deleted/resolved breaches are excluded from active analytics and retained for at least 400 days for audit
Timezone Heatmap & Drilldowns
"As a product manager, I want to see where guard breaches cluster by timezone and team so that I can target fixes where they matter most."
Description

Provides an interactive dashboard that visualizes breach density by hour and timezone with side‑by‑side attempted vs. actual counts. Offers filters for team, meeting type, severity, date range, and organizer, plus trend lines and week‑over‑week deltas. Enables drill‑down to affected meetings and participants, exports (CSV/JSON), and an analytics API endpoint. Optimized for fast loading and accessibility (keyboard nav, color‑safe palette).

Acceptance Criteria
Heatmap Side-by-Side Attempted vs Actual by Timezone and Hour
Given a user opens Drift Radar > Timezone Heatmap with a populated dataset for the selected date range, When the page loads, Then a 24xN grid renders where N equals the distinct timezones in scope, with each hour/timezone showing Attempted and Actual breach densities side-by-side with clear labels. Given the default view, When the user hovers or focuses a cell, Then a tooltip or focus detail shows timezone, hour (local), attempted count, actual count, and top severity for that cell. Given the selected date range and filters, When totals are computed, Then the sum of all cell attempted counts equals the backend attempted total and the sum of actual counts equals the backend actual total for the same scope with no discrepancy. Given a user toggles the time base between Local and UTC, When toggled, Then hour labels and cell mappings update accordingly without altering total attempted/actual counts.
Filter Combination Updates Visualization and Metrics
Given filters for team, meeting type, severity, date range, and organizer, When the user applies any combination (including multi-select), Then the heatmap, side-by-side counts, totals, and trends update to reflect only the filtered scope. Given filters are applied, When the page reloads or a shareable link is opened, Then the selected filters are restored via URL parameters and the view matches the saved state. Given a filter yields no results, When applied, Then an informative empty state appears and all totals/exports/API responses reflect zero results for the same scope. Given filters are cleared, When the user selects Reset, Then the view returns to the default unfiltered state and URL parameters are cleared.
Drill-Down from Heatmap Cell to Meeting and Participant Details
Given a user clicks or presses Enter on a heatmap cell, When activated, Then a drill-down panel opens listing affected meetings grouped by Attempted and Actual with columns: Meeting ID/Title, Organizer, Participants count, Time (local and UTC), Timezone, Severity, Meeting Type. Given the drill-down list, When the user sorts by any column, Then results reorder correctly and the sort state persists until changed. Given more than 50 results, When displayed, Then results are paginated (50 per page by default) and page controls navigate correctly without losing the applied filters or grouping. Given a listed meeting, When clicked, Then the meeting detail opens in a drawer or new tab per spec, and closing it returns the user to the same drill-down state and scroll position.
Trend Lines and Week-over-Week Delta Accuracy
Given the Trend section is visible for the current filters and date range, When loaded, Then it displays attempted and actual breach trend lines with weekly aggregation and a week-over-week delta (absolute and percent) for the most recent complete week. Given filters or date range change, When applied, Then trend lines and deltas recompute to match the new scope and the timestamp of last refresh updates. Given a backend reference dataset for the same scope, When comparing values, Then trend point totals and deltas match backend calculations within rounding to one decimal place.
Data Export and API Delivery of Current View
Given the current view (heatmap aggregate or drill-down details) and filters, When the user selects Export CSV, Then a file downloads within 5 seconds containing only data for the current scope and level of detail with a header row and fields appropriate to the view; for heatmap: timezone, hour, attempted_count, actual_count, top_severity, date_range, filters_metadata; for drill-down: meeting_id, title, organizer_id, participants_count, timezone, start_time_utc, start_time_local, severity, meeting_type, attempted_or_actual. Given the current view and filters, When the user selects Export JSON, Then a JSON file downloads within 5 seconds using the documented schema and matching row counts to the CSV for the same scope. Given a valid API token, When a GET request is made to /api/analytics/heatmap with query params team[], meeting_type[], severity[], organizer_id[], tz[], start, end, granularity=hour, Then the API returns 200 with attempted and actual counts per timezone-hour and a trends object; unauthorized requests return 401. Given a request within documented limits (e.g., date range ≤ 90 days, ≤ 100 teams), When executed, Then the API responds within 1.5s p95 and 500ms p50 and returns totals consistent with the UI for identical filters.
Performance and Load Time Targets
Given a dataset with up to 200 timezones and 12 months of data, When the dashboard initial load occurs on a standard network (≥50 Mbps) and mid-tier laptop, Then first contentful paint ≤ 1.5s and interactive heatmap render ≤ 2.5s p50 and ≤ 4.0s p95. Given a filter change or drill-down open, When executed, Then visual update latency (from action to rendered state) is ≤ 300ms p50 and ≤ 700ms p95, with a skeleton/loading state shown if rendering exceeds 200ms. Given an export of up to 100,000 rows, When requested, Then the file begins download within 10 seconds or a background job link is provided within 3 seconds with an email/download notification. Given API queries within documented limits, When executed under normal load, Then p95 latency ≤ 1.5s and 24-hour error rate < 0.5%.
Accessibility and Keyboard Navigation Compliance
Given only a keyboard, When navigating the dashboard, Then all interactive elements (filters, toggles, heatmap cells, drill-down controls, export buttons) are reachable in a logical tab order with visible focus indicators and Escape closes modals/drawers returning focus to the invoking element. Given a screen reader (NVDA/JAWS/VoiceOver), When reading the heatmap, Then each cell exposes an accessible name announcing timezone, hour, attempted count, actual count, and severity using appropriate ARIA roles and labels for actionable cells. Given the color-safe palette, When evaluated against WCAG 2.1, Then non-text contrast for critical states and adjacent density swatches meets AA and color is not the sole means of conveying severity (pattern or icon used in addition to color). Given a user presses Enter or Space on a focused heatmap cell, When invoked, Then the same drill-down opens as mouse click and focus is trapped within the drawer until dismissed, after which focus returns to the originating cell.
Early Risk Scoring & Forecasting
"As an engineering manager, I want a forecast of upcoming breach risk so that we can adjust schedules before meetings land in maker hours."
Description

Calculates a forward‑looking risk index per team/timezone/hour for the next 14–30 days by combining invite pipeline signals, historical seasonality, on‑call rotations, PTO/holiday calendars, and release calendars. Uses heuristic or ML models with calibrated thresholds, confidence bands, and backtesting. Exposes scores to the dashboard and alerting system and supports configuration of risk appetite by team.

Acceptance Criteria
Generate 14–30 Day Risk Index by Team/Timezone/Hour
Given TimeMeld has active teams with historical calendar and guard-breach data When the forecast job runs on schedule Then it generates a risk index in the range [0,100] for every team×timezone×hour cell for each day in the next 21 days by default And it supports configuring the forecast horizon between 14 and 30 days And each forecasted point includes 80% and 95% confidence bands, a model_version, input_sources, and generated_at timestamps And all scores are refreshed at least nightly and within 60 minutes of material input changes
Ingest Multi-Source Signals with Fallback Handling
Given connectors for invite pipeline, historical seasonality, on-call rotations, PTO/holiday calendars, and release calendars are configured When the data ingestion job executes Then each source is updated with a maximum freshness lag of 4 hours and recorded with source_status and last_updated And if any source is unavailable or stale, forecasts are still produced using remaining sources with deterministic fallback weights and a degraded=true flag And all times are normalized to IANA timezones with DST adjustments verified by unit tests across at least 5 DST transition regions
Configure and Enforce Team Risk Appetite Thresholds
Given a team admin opens Risk Settings When they set a numeric risk appetite threshold between 0 and 100 and save Then the value is validated, persisted, audit-logged with actor, timestamp, old_value, and new_value And the threshold takes effect in dashboard coloring and alert triggers within 10 minutes And a default threshold of 60 is applied to teams without an explicit setting
Backtest Forecasts and Calibrate Confidence Bands
Given at least 90 days of historical attempted/actual guard-breach outcomes When nightly backtesting runs over a rolling 60-day window Then the model’s 80% confidence band covers 75%–85% of realized outcomes and the 95% band covers 92%–98% And the Brier score improves by at least 10% versus a seasonality-only baseline And precision and recall for high-risk alerts (above team threshold) each meet or exceed 0.60 over the last 30 days And if coverage deviates beyond ±5%, a calibration routine is triggered and a status alert is raised to ops
Expose Risk Scores and Confidence on Dashboard
Given an authorized user views Drift Radar When they filter by team, timezone, and date range up to 30 days Then the grid displays per-hour risk scores with 80%/95% confidence visualization, threshold markers, and a last_updated timestamp And hovering a cell reveals contributing factors with relative weights and source freshness And the view loads in under 2 seconds for 3 teams over 21 days on a standard broadband connection And all visual elements meet WCAG 2.1 AA color-contrast for risk states
Trigger Early Alerts with Recommendations
Given alerting channels (Slack and email) are configured for a team When any forecasted hour in the next 7 days is projected to exceed the team’s risk appetite threshold Then an early alert is sent with at least 24 hours lead time, including risk score, confidence band, top contributors, and recommended schedule/policy tweaks And alerts are deduplicated to at most one per team×hour per 24-hour period and support snooze durations of 1, 3, or 7 days And acknowledgments are recorded with actor and timestamp and stop further alerts for that instance And all alerts are logged and visible in an alert history view
Proactive Alerts & Routing
"As a team lead, I want concise, actionable alerts during work hours so that I can respond quickly without notification noise."
Description

Delivers early alerts when risk or breach thresholds are crossed via Slack, email, and in‑app notifications. Supports routing by team/role, quiet hours based on user timezone, digest vs. real‑time modes, deduplication, escalation rules, and per‑channel templates with actionable context (top drivers, impacted hours, quick links). Provides user‑level preferences and unsubscribe controls.

Acceptance Criteria
Digest vs Real-Time Delivery Configuration
- Given a user with delivery mode set to Real-Time and a Drift Radar risk or breach threshold is crossed, when the event is detected, then a notification is delivered to the user’s enabled channels within 60 seconds of detection. - Given a user with delivery mode set to Digest (daily) at a configured local time, when one or more qualifying events occur before the digest time, then a single digest is sent at the configured time containing a grouped summary by team, guard, and hour; and no real-time notifications are sent for those events. - Given a user changes delivery mode from Real-Time to Digest mid-day, when subsequent qualifying events occur, then those events are included only in the next digest and are not sent real-time; previously sent notifications remain unchanged. - Given an organization default delivery mode is set, when a user has no explicit preference, then the default is applied and reflected in audit logs.
Routing by Team and Role with Fallback
- Given routing rules exist mapping specific teams and roles to destinations (Slack channel, Email group, In‑app audience), when a qualifying event is raised for a matching team/role, then the alert is delivered only to the highest‑priority matching destination. - Given multiple routing rules could apply, when priorities are defined, then the rule with the highest priority is applied; when priorities are equal, then the most specific rule (team+role) is applied. - Given no routing rule matches an event, when the event is raised, then the alert is delivered to the organization default destination and the routing decision is recorded in logs. - Given a role‑based route (e.g., On‑call Engineer), when the current assignee list is resolved, then only active assignees receive the alert and resolution is logged for traceability.
Quiet Hours by User Timezone and Deferred Delivery
- Given a user has quiet hours configured (per weekday) in their profile timezone, when an alert targets that user during their quiet hours, then real‑time delivery to that user is suppressed and the alert is queued. - Given quiet hours end, when queued alerts exist for the user and their delivery mode is Real-Time, then a single bundled notification labeled “Deferred During Quiet Hours” is delivered within 5 minutes after quiet hours end, containing the suppressed items. - Given quiet hours end, when the user’s delivery mode is Digest, then suppressed items are included only in the next digest and not delivered immediately. - Given alerts are routed to shared team destinations (e.g., public Slack channels), when any member’s quiet hours are active, then quiet hours do not suppress delivery to the shared destination (quiet hours apply to individual recipients only). - Given a user profile lacks a timezone, when quiet hours are evaluated, then the organization default timezone is used and a warning is logged.
Alert Deduplication and Coalescing
- Given a deduplication key composed of {team_id, guard_id, hour_bucket, event_type(risk|breach), route_target}, when multiple qualifying events with the same key occur within a 15‑minute window, then only one real‑time notification is sent for that key to that target. - Given additional events are deduplicated, when the original notification supports updates (Slack or in‑app), then the original message is updated or threaded within 2 minutes to reflect the new count and latest context; when the channel is Email, then duplicates are suppressed and counts appear in the next digest. - Given the 15‑minute window elapses or the hour bucket changes, when a new event occurs, then a new notification may be sent. - Given deduplication suppresses a notification, when viewing audit logs, then suppression reason and counts are recorded for the event batch.
Escalation Rules and Acknowledgment Workflow
- Given an alert requires acknowledgment, when sent to the initial tier, then if no acknowledgment is received via supported actions (Slack button/link, in‑app action, email link) within 15 minutes of delivery, the alert escalates to the next configured tier; escalation stops when an acknowledgment is recorded or after the final tier. - Given the next tier recipient is in quiet hours, when escalation is triggered, then delivery is deferred until their quiet hours end and the escalation timer excludes deferred time from SLA measurement. - Given an alert is acknowledged at any tier, when escalation would otherwise trigger, then escalation is canceled and all recipients see the acknowledged status within 60 seconds. - Given an alert escalates, when delivered to the next tier, then the full actionable context and prior attempts/elapsed time are included in the message.
Per-Channel Templates with Actionable Context
- Given a Slack delivery, when an alert is sent, then the message includes: team, guard, event type (risk/breach), impacted hours in the recipient’s local time, top 3 drivers with percentages, and quick links to View Drift Radar, Propose Schedule Tweak, Adjust Policy, and Mute; all placeholders render with non‑empty values or safe defaults. - Given an Email delivery, when an alert is sent, then the subject follows: "[TimeMeld Drift Radar] {Team} {Guard} {Risk|Breach}", and the body includes the same context plus deep links with correct query parameters; links open to the filtered view. - Given an In‑app notification, when an alert is sent, then the notification panel displays the same context and links, and opens the detailed view within the app without a full page reload. - Given any channel template, when required data is unavailable, then default text is rendered and the send does not fail; the missing fields are logged for telemetry.
User-Level Preferences and Unsubscribe Controls
- Given a user opens Preferences, when they toggle channels (Slack DM, Email, In‑app), delivery mode (Real-Time vs Digest), and quiet hours, then changes persist immediately and are enforced on subsequent alerts. - Given a user clicks "Unsubscribe" in Email or sends "stop" as a DM command to the bot, when the request is confirmed, then all future Drift Radar alerts to that user are stopped within 1 minute and the change is auditable. - Given an unsubscribed user is part of a role route, when an alert targets that role, then the user is excluded from delivery while other role members still receive it. - Given a user re‑subscribes via Preferences or "start" command, when confirmed, then delivery resumes per their current settings.
Realignment Recommendations
"As a scheduler, I want concrete recommendations I can apply in one click so that I save time and protect maker hours."
Description

Generates prescriptive suggestions to reduce breach risk: shift recurring meeting windows, rebalance the equity scoreboard rotation, auto‑insert protected focus blocks, or adjust guard policies within safe bounds. Includes a what‑if simulator showing forecast impact, conflict checks, and one‑click apply with rollbacks. Captures rationale and outcomes for continuous learning and future tuning.

Acceptance Criteria
Risk-Triggered Realignment Suggestions
Given Drift Radar detects a team risk score above a configured threshold or >3 guard breaches in the last 7 days When the user opens Realignment Recommendations for that team Then at least one recommendation is returned within 2 seconds And each recommendation is typed as one of: shift meeting windows, rebalance equity rotation, insert focus blocks, adjust guard policies And each recommendation includes an estimated breach-risk reduction percentage and a confidence score between 0.0 and 1.0 And each recommendation lists scope (teams, timezones), meetings/users affected count, and earliest effective date And recommendations that would violate hard guardrails are excluded; soft-guard tradeoffs are explicitly flagged
What-If Simulator Forecast and Conflict Checks
Given a candidate recommendation is selected When the user adjusts parameters (time offsets, rotation assignments, focus block durations) and clicks Simulate Then the simulator displays forecasted risk delta by hour and timezone, and projected maker-hours preserved (numeric values) And a visual diff of current vs proposed schedule is shown And calendar conflicts are computed with total count and a list of conflicting participants/events And parameter tweak responses render within 500 ms; first-run simulation renders within 2 seconds And if any blocking conflicts remain, Apply is disabled and auto-resolve options (e.g., shift ±15 minutes) are presented
One-Click Apply with Safe Rollback
Given an approved recommendation with no blocking conflicts When the user clicks Apply Then calendar updates to recurring meetings are sent with updated times and ICS notifications, focus blocks are created as Busy, and guard policy values are adjusted within configured bounds And all changes commit atomically; if any sub-operation fails, the entire operation rolls back and an error summary is shown And a rollback action is available for 30 days; when invoked, all changes revert and affected invites are corrected within 60 seconds And an activity record is created containing change set ID, actor, timestamp, and affected objects
Equity Scoreboard Rebalance Fidelity
Given a rotation rebalance recommendation When simulated for the selected team and period Then fairness metrics (mean ownership per person and variance) move toward target or stay within ±5% of target And no individual receives more than one additional consecutive ownership slot beyond baseline in the next 4 rotations And personal constraints (unavailable times, core hours) are honored with zero violations And predicted attendance probability increases by at least 5% or projected risk reduces by at least 10%, otherwise the recommendation is marked low impact
Protected Focus Blocks Auto-Insertion Rules
Given team guard policies define focus block duration and windows When the system proposes auto-inserted focus blocks Then blocks do not overlap immovable events and maintain a minimum contiguous length of 90 minutes And total focus-block time does not exceed 20% of a member’s weekly working hours And blocks are placed within local core hours with at least a 15-minute buffer from adjacent meetings And recurring series include an end date per policy and are labeled "Protected Focus" with the correct calendar category And any conflicts are listed with counts, and the simulator allows ±15-minute nudge options
Rationale, Audit, and Outcome Capture
Given a recommendation is applied Then the system stores rationale including detected breach patterns, selected levers, forecast metrics, approver, timestamp, and before/after policy/schedule deltas And records are immutable and queryable by team, timeframe, lever type, and change set ID When the 14-day observation window elapses Then actual outcomes (breach counts, attendance rates, maker-hours preserved) are computed and linked to the change record And PII is masked per policy; exports are available in CSV and JSON; data retention defaults to 12 months with admin-triggered hard delete supported
Integrations & Access Controls
"As a security‑conscious admin, I want granular permissions and audited integrations so that Drift Radar remains compliant and trustworthy for our organization."
Description

Provides secure integrations with Google Workspace and Microsoft 365 calendars, Slack, and SSO (OAuth/SAML) using least‑privilege scopes. Implements role‑based access (admin, lead, member), team scoping, data residency controls, encryption at rest/in transit, audit logs for policy changes and recommendations applied, and data retention/deletion policies. Supplies webhooks for breach events and risk updates.

Acceptance Criteria
Least-Privilege Calendar OAuth for Google Workspace and Microsoft 365
Given an org admin initiates calendar integration setup When the OAuth consent screen is displayed Then the requested scopes are limited to reading availability and creating or updating calendar events and basic OpenID profile information, and do not include mail, drive or storage, contacts, or directory scopes Given the integration is connected When an API call is attempted against a non-authorized resource Then the provider returns insufficient_scope and the attempt is logged in the audit log Given the admin revokes access at the provider When TimeMeld attempts to refresh tokens Then the integration status changes to Disconnected within 5 minutes and the admin receives a notification
Slack Integration with Minimal Scopes and Team-Scoped Alerts
Given a workspace owner installs the Slack app When the permission screen is shown Then the app requests only chat write, channels read for selection, and users read for mapping, and does not request channel or DM history scopes Given a Drift Radar alert is generated for Team A When TimeMeld posts to Slack Then messages are delivered only to the configured channels or DMs for Team A members and are not visible to other teams Given an API attempt to read channel message history occurs When the call is executed Then it fails due to missing scope and the event is recorded in the audit log
SSO and RBAC Mapping Enforcement
Given SAML or OIDC is configured with an identity provider When a user signs in via SSO Then an account is provisioned only if the email domain is on the allowlist and a valid group or role claim maps to admin, lead, or member Given a signed-in user with role member When attempting to access org-wide settings, integrations, or retention policies Then access is denied with 403 and an audit log entry is created with actor, action, and resource Given a user with role lead assigned to Team B When viewing Drift Radar risk and audit logs Then only Team B data is accessible and data for other teams is not retrievable
Data Residency Selection and Encryption Controls
Given an org admin selects a data region during setup, US or EU When data is persisted or processed Then customer data and backups remain in the selected region and cross-region storage is not used Given application traffic is initiated When connections are negotiated Then TLS version 1.2 or higher is enforced and weaker protocols are refused Given data at rest is stored When inspecting storage configuration Then encryption at rest is enabled using industry-standard algorithms and keys are managed by a KMS with rotation enabled
Audit Logging for Policy Changes and Recommendations
Given a policy change or a Drift Radar recommendation is applied When the action is saved Then an immutable audit log entry is recorded containing actor, role, team, timestamp in UTC, source channel UI or API, IP, resource identifier, and before and after values Given an auditor queries logs by date range, actor, team, and action type When 10,000 matching entries exist Then the query returns within 2 seconds and results can be exported as CSV and JSON Given a request attempts to modify or delete an audit entry via API When processed Then the request is rejected and the attempt is itself logged
Data Retention and Deletion Policy Enforcement
Given an admin configures retention periods for risk telemetry and audit logs When records exceed their configured retention Then they are purged from primary storage immediately and from backups within 30 days and the purge is logged Given a user deletion request is submitted When processing completes Then personally identifiable and calendar-derived data for that user is deleted or irreversibly anonymized within 30 days and a deletion certificate is available for download Given a data export is generated after deletion When the export is inspected Then the deleted user’s data is absent
Webhooks for Breach Events and Risk Updates
Given an admin creates a webhook subscription for guard breach attempted, guard breach actual, and risk score updated events When an event occurs Then a POST is delivered within 10 seconds including event id, org id, team id, event type, and timestamp, and an HMAC SHA256 signature header computed with the shared secret Given the receiver returns a non-2xx status When delivery is retried Then up to 3 retries occur with exponential backoff and duplicate deliveries carry the same event id for idempotency Given 10 consecutive delivery failures occur When the threshold is reached Then the webhook is auto-disabled and an admin notification is sent

Drift Heatmap

An interactive grid that visualizes show‑rates by region, day, and hour so you can instantly spot underperforming windows. Hover to see trends, compare cohorts, and jump straight to recommended fixes—eliminating guesswork and speeding confident adjustments.

Requirements

Heatmap Data Pipeline & Show-Rate Metric
"As a data-driven PM, I want a trustworthy, up-to-date show-rate metric by region/day/hour so that I can base scheduling changes on accurate and statistically meaningful insights."
Description

Implement a reliable data pipeline that ingests meeting metadata and attendance outcomes from connected calendars, normalizes timezones, and computes show-rates aggregated by region, day of week, and hour of day. Define a canonical “show-rate” metric (attended/scheduled) with clear rules for attendance, cancellations, reschedules, and no-shows. Bucket events into 7x24 hourly windows using the meeting’s effective region and local time. Support configurable lookback windows (e.g., last 4–12 weeks), rolling updates (hourly/daily), and backfilling. Enforce minimum sample-size thresholds and outlier handling to ensure statistically meaningful cells, masking or annotating low-confidence data. Persist pre-aggregated tiles for fast rendering and expose query APIs that support filters (region, team, meeting type, cohort). Ensure data quality monitoring, idempotent reprocessing, and auditability to guarantee accurate, timely, and trustworthy inputs for the Drift Heatmap and downstream recommendations.

Acceptance Criteria
Ingest and Normalize Calendar Events Across Timezones
- Given connected Google and Microsoft calendars are authorized, when the hourly ingestion job runs, then events created or updated within the lookback window are fetched with fields: provider, calendar_id, event_id, recurrence_id/occurrence_id, organizer, attendees (required/optional), meeting_type, team, cohort tags, start_time, end_time, timezone, created_at, updated_at, status, cancellation/reschedule flags, and outcome. - Given an event is fetched multiple times, when reprocessing occurs, then the pipeline produces a single canonical record per (provider, calendar_id, event_id, occurrence_id) and no duplicates are created (idempotent upsert). - Given an event’s source timezone and IANA identifier, when normalization occurs, then UTC and local timestamps are stored and DST is handled correctly so that local wall-clock time is preserved. - Given a successful source API response, when ingestion completes, then new/updated events are available to downstream aggregation within 60 minutes (p95) and 90 minutes (p99). - Given transient provider failures, when retries are applied, then at least 3 retry attempts with exponential backoff are performed before surfacing an alert, and the backlog is caught up within the next successful run. - Given malformed or missing required fields, when validation runs, then the event is quarantined with a reason code and excluded from aggregates until corrected.
Canonical Show-Rate Metric and Outcome Rules
- Given a filtered event set, when computing show-rate, then show_rate = attended_meetings / scheduled_meetings, rounded to two decimals, and counts (attended_meetings, scheduled_meetings) are included. - Given event.outcome in {attended, no_show, canceled, rescheduled}, when classifying, then scheduled_meetings includes outcomes {attended, no_show} only; canceled >= 60 minutes before start are excluded; rescheduled prior to start are excluded and attributed to the new slot only. - Given a cancellation < 60 minutes before start, when classifying, then it is treated as no_show. - Given conflicting updates (e.g., rescheduled then attended), when finalization runs, then the latest outcome as of aggregation time is used and original slot is excluded from denominator. - Given multi-attendee meetings, when deriving meeting-level outcome, then attended requires organizer present and at least one required attendee present per normalized outcome; otherwise classify as no_show. - Given recurring meetings, when an occurrence is skipped (canceled in series), then that occurrence is excluded from both numerator and denominator.
7x24 Bucketing by Effective Region and Local Time
- Given an event with effective_region and timezone, when bucketing, then the event is assigned to exactly one cell defined by (region, day_of_week, hour_of_day) using the event’s local time in that timezone. - Given DST transitions, when local time repeats or skips, then bucketing uses wall-clock hour labels; repeated hours create distinct cells per occurrence and skipped hours produce no cells. - Given ISO-8601 week rules, when computing day_of_week, then Monday=1 through Sunday=7 is applied consistently across all regions. - Given region precedence rules, when both organizer region and explicit meeting region are present, then explicit meeting region takes precedence; otherwise organizer region is used. - Given 7 days and 24 hours, when building aggregates, then each region yields 168 cells per lookback cohort with correct counts summing to the regional totals.
Configurable Lookback, Rolling Updates, and Backfill
- Given a configuration parameter lookback_weeks ∈ [4,12], when aggregation runs, then only events within the trailing lookback_weeks are included. - Given hourly incremental updates, when source events change, then aggregates reflect changes within 60 minutes (p95) from the source update time. - Given a daily full recompute at 02:00 UTC, when the job completes, then aggregates exactly match recomputed results for the same filters (checksum equality of counts). - Given late-arriving events or outcome changes, when backfill is triggered for a date range, then aggregates are updated idempotently without duplicate records and version metadata is advanced. - Given a backfill up to 52 prior weeks, when executed, then job completion produces a run report with processed windows, counts ingested, and discrepancies vs prior snapshot (if any).
Sample Size Thresholds, Outliers, and Confidence Masking
- Given a configurable minimum_n (default 30), when a cell’s scheduled_meetings < minimum_n, then the cell is masked from the heatmap’s primary color scale and labeled low_confidence=true with N displayed. - Given minimum_n is met, when computing show_rate, then the value is displayed and included in recommendations. - Given regional distributions, when a cell’s show_rate has |z-score| > 3 relative to its region’s distribution for the same lookback, then the cell is annotated outlier=true but not masked if N ≥ minimum_n. - Given configuration for outlier handling, when winsorize=true, then cell show_rate values are clamped to the regional 5th–95th percentile bounds for display-only and raw counts remain unchanged. - Given suppressed cells, when computing regional totals, then suppressed cells are excluded from weighted averages unless include_suppressed=true is specified in the query.
Pre-Aggregated Tiles and Filterable Query API
- Given pre-aggregation, when the tile builder runs, then it persists tiles keyed by (region, day_of_week, hour_of_day, lookback_weeks, team?, meeting_type?, cohort?) including fields: show_rate, attended_meetings, scheduled_meetings, low_confidence, outlier, last_computed_at, version. - Given the Heatmap queries tiles via GET /api/heatmap/tiles, when filters region, team, meeting_type, cohort, and lookback_weeks are provided, then only matching tiles are returned and response p95 latency ≤ 300 ms for up to 10 regions. - Given masked cells, when returned, then cells include low_confidence=true and do not include show_rate in the primary value unless include_masked=true is set. - Given ETag support, when the same query is repeated with If-None-Match and tiles are unchanged, then the API returns 304 Not Modified. - Given pagination parameters limit and cursor, when querying large result sets (>1000 tiles), then results are paginated consistently with stable ordering.
Data Quality Monitoring, Idempotent Reprocessing, and Auditability
- Given pipeline SLAs, when monitoring runs, then freshness for hourly aggregates is < 90 minutes since last successful run (p95) and alerts fire to #data-alerts if breached. - Given source-to-target reconciliation, when daily checks run, then event-level completeness differs by < 0.5% from provider counts per region; larger deltas open an incident automatically. - Given schema contracts, when an unknown outcome/status is encountered, then the event is quarantined and an alert with sample payload is generated; aggregates skip quarantined events. - Given reprocessing by date range, when the same window is recomputed with identical inputs, then output aggregates (counts and rates) are identical (checksum match) and previous versions are soft-deleted with lineage retained. - Given audit requirements, when any ingestion, aggregation, or backfill job runs, then an immutable audit log records actor, parameters, code version, start/end times, row counts, and result location with retention ≥ 400 days.
Interactive Drift Heatmap Grid
"As a scheduling lead, I want an intuitive grid that lets me scan underperforming windows and interact with cells quickly so that I can pinpoint problem times without digging through raw data."
Description

Deliver a responsive, accessible heatmap UI that visualizes show-rates across a 7x24 grid with a clear color scale and legend, tooltips on hover, and keyboard navigation. Support filtering by region, timeframe, team, meeting type, and cohort, with stateful URLs for deep-linking. Allow single and multi-cell selection, brushing/lasso to select ranges, and quick actions from the selection. Provide empty/error states, loading skeletons, and a persistent legend with clear thresholds. Optimize for performance with pre-fetched tiles, client-side caching, and <2s initial render on typical org datasets; ensure interactions (hover, select, filter) respond within 200–500ms. Ensure WCAG AA contrast, tooltip focus management, and screen reader labels for all interactive elements. Render consistently on desktop and tablet, with graceful mobile read-only support.

Acceptance Criteria
Responsive Rendering & Performance SLAs
Given a typical org dataset and a cold cache, When the user opens the Drift Heatmap route, Then the heatmap grid and persistent legend render within 2000 ms at p95. Given a warm cache and pre-fetched tiles, When the user switches any filter (region, timeframe, team, meeting type, cohort), Then the grid re-renders within 500 ms at p95 and previously fetched tiles are reused. Given the user hovers a new cell or moves keyboard focus, When the hover/focus changes, Then the tooltip content and highlight update within 200 ms at p95. Given the user selects one or more cells, When the selection is changed (click, brush, lasso), Then the selection highlight and count update within 200 ms at p95. Given adjacent timeframe navigation is available, When the user navigates to an adjacent period that has been pre-fetched, Then render completes within 300 ms at p95. Given the user reloads the same state, When data has not changed, Then no tile network requests are made (served from client cache) and the view renders within 1000 ms at p95. Given a desktop (≥1280px) or tablet (≥768px and <1280px) viewport, When the page loads, Then the grid fits within the viewport with no horizontal scrollbar and text is readable without zoom. Given a mobile viewport (<768px), When the page loads, Then the heatmap renders in a read-only mode where tap acts as hover to reveal a tooltip, multi-select/brush/lasso are disabled, and performance targets above are still met.
Keyboard Navigation & Screen Reader Accessibility (WCAG AA)
Given focus enters the heatmap grid, When the user presses Arrow keys, Then focus moves cell-by-cell in the corresponding direction and announces the new cell. Given focus is on a cell, When the user presses Enter or Space, Then the cell toggles selection and the selection count is announced. Given focus is on a cell, When the user presses Shift+Arrow, Then the selection extends to include the cell in the pressed direction. Given focus is within the grid, When the user presses Escape, Then the current selection (if any) clears and focus remains in the grid. Given a screen reader user, When a cell receives focus, Then it announces region, day, hour, show-rate percentage, and sample size. Given any interactive control (filters, lasso toggle, quick actions), When it is focused, Then it exposes a role, accessible name, and state via ARIA and is reachable by Tab order. Given any text in the heatmap UI, When evaluated for contrast, Then it meets WCAG AA 4.5:1 for text and 3:1 for non-text/graphical indicators; focus indicators have a 3:1 contrast ratio. Given a tooltip is triggered via keyboard, When it opens, Then it is programmatically associated with the focused cell, is dismissible with Escape, and focus returns to the invoking cell on close.
Filtering Controls & Stateful Deep Links
Given the user changes any filter (region, timeframe, team, meeting type, cohort), When the filter value changes, Then the URL query string updates to reflect the full current state without a page reload. Given a copied/shared URL containing heatmap state, When the page loads from that URL, Then filters, timeframe, and visible grid state are restored exactly. Given the user navigates browser Back/Forward, When the URL state changes, Then the heatmap restores the corresponding filters and view without a full reload. Given the user clears a specific filter, When cleared, Then the corresponding query parameter is removed and defaults are applied. Given the URL contains invalid or unsupported parameters, When parsed, Then safe defaults are applied and the URL is sanitized to valid parameters without breaking navigation. Given a large multi-select filter (e.g., regions), When multiple values are selected, Then the URL encodes them deterministically and the same ordering reproduces the identical state on reload.
Tooltip Content & Hover/Focus Behavior
Given the user hovers a cell on desktop/tablet, When the pointer rests on the cell, Then a tooltip appears within 200 ms showing: show-rate percentage, attended/total counts, delta vs previous comparable period (pp), cohort comparison delta, and the cell's region/day/hour labels. Given the user navigates cells via keyboard, When a cell receives focus, Then the same tooltip content is displayed and remains until focus changes or Escape is pressed. Given the tooltip would overflow the viewport, When positioned, Then it flips or repositions to remain fully visible with a minimum 8px margin from edges. Given quick pointer movements across adjacent cells, When hover changes rapidly, Then the tooltip updates without flicker (no hide/show within 100 ms) and tracks the active cell. Given mobile read-only mode, When the user taps a cell, Then the tooltip appears with the same content and a second tap outside dismisses it.
Selection, Brushing/Lasso, and Quick Actions
Given the user clicks a cell, When the cell is unselected, Then it becomes selected; clicking again deselects it. Given the user holds Shift/Cmd (Ctrl on Windows) and clicks additional cells, When clicking, Then multi-select adds/removes cells accordingly. Given the user click-drags in brush mode, When a rectangle is drawn, Then all enclosed cells become selected upon release. Given the user enables Lasso mode, When a freeform polygon is drawn and closed, Then enclosed cells become selected; pressing Escape cancels the lasso. Given a filter change occurs, When selected cells are no longer in view, Then only still-visible selected cells remain selected; others are dropped. Given one or more cells are selected, When selection exists, Then a quick actions bar appears within 300 ms offering at minimum: Apply as Filter, View Recommended Fixes, and Copy Deep Link to Selection. Given keyboard users, When selection exists, Then Ctrl+Enter opens the quick actions bar, Tab navigates actions, and Enter activates the focused action. Given Copy Deep Link to Selection is invoked, When activated, Then the clipboard receives a URL that restores filters and the selected cell set on load.
Legend, Color Scale, and Thresholds
Given the heatmap is visible, When the page loads, Then a persistent legend is displayed explaining the color scale with labeled numeric thresholds (min, mid/neutral if applicable, max) and units (%). Given filters or timeframe change, When the underlying data domain changes, Then the legend thresholds update to match the new domain and the color mapping remains consistent with the legend. Given colorblind-safe requirements, When the palette is evaluated, Then the chosen colors meet contrast guidance and are distinguishable in common color vision deficiencies. Given a user hovers or focuses the legend info icon, When activated, Then an explanation of how colors map to show-rate and thresholds is displayed and is accessible via keyboard and screen reader. Given printed or exported screenshots, When reviewed, Then the legend alone is sufficient to interpret the heatmap scale without external documentation.
Loading Skeletons, Empty, and Error States
Given initial data load, When the route is opened, Then a loading skeleton appears within 150 ms and remains until data renders to avoid layout shift. Given the selected filters yield no data, When the response is empty, Then an empty state is shown with a clear message and a CTA to adjust filters/timeframe; the grid area is not collapsible to zero height. Given a recoverable network error or timeout, When the request fails, Then an error state with a Retry action is displayed; clicking Retry re-requests and, on success, replaces the error with the heatmap. Given partial data, When some cells have no data, Then those cells render with a distinct no-data pattern and tooltips indicate "No data" without implying zero. Given consecutive retries, When three attempts fail, Then the error state persists and exposes an error code for support while remaining accessible and navigable by keyboard.
Cohort Comparison & Segmentation
"As a RevOps manager, I want to compare show-rates between customer segments and my internal team so that I can see which windows work best for each cohort and tailor scheduling rules accordingly."
Description

Enable side-by-side and overlay comparisons of show-rates across selected cohorts (e.g., teams, roles, internal vs. external, customer segment, region). Provide cohort filters, a delta view that highlights improvements/regressions, and significance annotations when differences are likely non-random. Allow saving and sharing of cohort configurations as named views, with URL state and permission-aware access. Support up to two overlays or a split grid for clarity, with synchronized hover tooltips and legends. Maintain performance by reusing pre-aggregations and limiting high-cardinality dimensions via curated lists.

Acceptance Criteria
Cohort Filter Selection & Curated Dimensions
Given the Drift Heatmap is open and the user has access to cohort filters When the user opens the filter panel and selects up to two cohorts from curated lists for Team, Role, Customer Segment, and Region Then only values from curated lists are selectable, search returns matching curated values within 200 ms, and non-curated values are disabled with an unavailable state Given no cohort is selected When the user applies filters Then the baseline “All” cohort is applied by default and comparison controls remain disabled until at least one cohort is selected
Side-by-Side and Overlay Modes with Two-Cohort Limit
Given two cohorts are selected When the view mode is switched to Overlay Then both cohorts render on a single heatmap with a merged legend, distinct cohort labels, and adding a third cohort is prevented with an explanatory message Given two cohorts are selected When the view mode is switched to Split Grid Then two heatmaps render side-by-side with aligned axes, synchronized zoom/scroll, and a shared color scale domain Given only one cohort is selected When the user switches modes Then only valid modes are enabled and no empty placeholder grids are shown
Delta View for Improvements and Regressions
Given two cohorts are selected and the Delta toggle is on When the heatmap renders Then each cell shows absolute delta (percentage points) and relative delta (%), colored green for improvements and red for regressions, with ±0 within a neutral band Given the user hovers a cell in Delta view When the tooltip appears Then it displays cohort A value, cohort B value, absolute delta, relative delta, and sample sizes for both cohorts Given delta thresholds are set to ±1.0 percentage points When a cell’s absolute delta is below the threshold Then the cell is visually deemphasized and excluded from Top Changes summaries
Significance Annotations and Thresholds
Given minimum per-cell sample size is set to n ≥ 30 per cohort When two cohorts meet the sample requirement and a two-proportion z-test at α = 0.05 indicates significance Then the cell is annotated with a significance marker and the tooltip reports p-value, test type, and sample counts Given multiple cells are tested for significance When annotations are applied Then Benjamini–Hochberg FDR correction at q = 0.10 is applied before marking significant cells Given a cell fails minimum sample size When rendering Then the cell displays an n < 30 indicator and is excluded from significance annotations
Synchronized Hover Tooltips and Legends
Given Overlay or Split Grid mode is active with one or two cohorts When the user hovers any cell Then the hover highlight is synchronized across all visible grids and the tooltip presents values for all visible cohorts plus delta if toggled Given the user navigates via keyboard When arrow keys move focus within the heatmap Then the synchronized tooltip updates accordingly and focus order is cell-by-cell, supporting WCAG 2.1 keyboard operability Given the legend is visible When the user toggles between Absolute and Delta scales Then the legend updates to reflect the active scale, color domain, and units
Save, Share, and Permission-Aware Views with URL State
Given the user has Editor permissions When they save the current cohort configuration as a named view Then the view is persisted with a unique name per workspace and a shareable URL encodes filters, mode, delta, and date range Given a Viewer opens the shared URL When the page loads Then the heatmap restores the exact saved state and save/overwrite controls are disabled Given an unauthorized or unauthenticated user opens the URL When access is checked Then an appropriate permission error is shown without revealing the view name or settings Given an Editor updates a named view When Save is clicked Then the URL remains stable and the view’s updated_at timestamp changes
Performance and Pre-Aggregation Utilization
Given up to 12 months of data and two cohorts selected When the heatmap loads with a warm cache Then time to first interactive render is ≤ 1.2 seconds and hover latency is ≤ 75 ms on a standard laptop Given a cold cache When the same view is loaded Then time to first interactive render is ≤ 3.0 seconds and backend queries are ≤ 3 leveraging pre-aggregations Given a filter change such as Region When the view updates Then the update completes within ≤ 400 ms for warmed data Given high-cardinality dimensions exist When filters are opened Then only curated lists (≤ 100 entries per dimension) are shown and typeahead search returns results within 200 ms
Hover Insights & Trends Tooltip
"As an engineering manager, I want instant trend context when I hover a cell so that I can judge whether a low show-rate is a blip or a persistent issue before making changes."
Description

Augment heatmap cells with rich hover tooltips that display sample size, show-rate, week-over-week and month-over-month deltas, a mini trend sparkline over the selected lookback, and confidence indicators based on sample size thresholds. Include contextual metadata (typical invitee count, common meeting types) and call out anomaly flags when sudden drifts are detected. Ensure tooltips are accessible, fast to render, and respect privacy masking for small samples. Provide localization for date/time formatting aligned to the selected region or viewer settings.

Acceptance Criteria
Tooltip Displays Core Metrics Quickly and Accurately
Given a user hovers or focuses a heatmap cell When the tooltip opens Then it shows sample size (n), show-rate (%), week-over-week delta (pp), month-over-month delta (pp), and contextual metadata (typical invitee count, common meeting types) And all metric values match the backend payload for that cell within ±0.1 percentage points for rates/deltas and exact integer for n And the tooltip’s first content appears within 150 ms (P95) and full content (including sparkline and badges) within 300 ms (P95) on supported browsers/devices And if any metric is unavailable, it displays "—" for that field without causing cumulative layout shift > 0.02
Sparkline Renders Correct Trend for Selected Lookback
Given a lookback period is selected (e.g., 8 weeks or 30 days) When the user opens the tooltip Then a sparkline renders values for that cell across the lookback using the selected aggregation granularity And the number of points equals the number of intervals in the lookback, and the last point equals the current cell’s show-rate And the sparkline has an accessible name "Trend" and an aria-label summarizing direction (up/down/flat) and last three values And if fewer than 3 data points are available, the sparkline is replaced with the text "Insufficient data"
Confidence Indicator Reflects Sample Size Thresholds
Given the cell’s sample size n When the tooltip renders Then it shows a confidence badge with level Low if n < 10, Medium if 10 ≤ n < 50, High if n ≥ 50 And each level includes an icon and label text and meets color contrast ≥ 4.5:1 against the tooltip background And the badge’s title/tooltip reads "Confidence based on sample size n" with the actual n inserted
Privacy Masking for Small Samples
Given masking threshold T = 5 When n < T Then the tooltip masks sensitive fields: show-rate and n display as "Masked (<5)" and WoW/MoM deltas are omitted And contextual metadata (typical invitee count, common meeting types) is omitted when n < T And a note "Limited data — privacy protected" is exposed to screen readers via aria-live polite When n ≥ T Then all fields render normally without masking
Anomaly Flag Appears on Sudden Drift
Given the backend marks the cell with anomaly=true and provides drift_delta_pp and optional rationale When the tooltip opens Then it displays an "Anomaly detected" badge with the delta (e.g., "−22 pp WoW") and an alert icon And activating (clicking or focusing + Enter) the badge reveals the rationale text if provided; otherwise shows "Significant change detected" And when anomaly=false, no anomaly badge or copy is displayed
Tooltip Accessibility and Keyboard Interaction
Given the heatmap is navigated via keyboard When a user tabs to a heatmap cell Then the cell is focusable (role="gridcell") with aria-label including region, day, hour, and show-rate (or "Masked" when applicable) And pressing Enter or Space opens the tooltip, Esc closes it, and the tooltip remains open while focus is within And screen readers announce the tooltip via aria-describedby only once; all interactive elements are reachable with visible focus; no keyboard traps exist
Localized Date/Time and Regional Formatting
Given the viewer’s locale/region is set (or a region is selected in-app) When the tooltip renders date/time and numeric values Then formatting matches the locale: en-US uses 12-hour time and MM/DD/YYYY; en-GB uses 24-hour time and DD/MM/YYYY; fr-FR uses 24-hour time and DD/MM/YYYY with localized month names where shown And weekday/hour labels reflect the selected region’s timezone And numeric separators follow locale conventions (e.g., 1,234.5 for en-US; 1 234,5 for fr-FR) And switching locale updates formatting within the same render cycle
One-Click Recommended Fixes
"As a product ops lead, I want to jump from a bad time slot to recommended alternatives and apply them in one click so that I can reduce no-shows without manual trial-and-error."
Description

From selected underperforming cells, generate ranked recommendations that adjust scheduling windows and rules to higher-performing alternatives by region and cohort. Present expected impact (projected show-rate lift, affected meetings), rationale, and confidence, with a one-click action to open the TimeMeld scheduler pre-populated with proposed changes. Support bulk selection across multiple cells, preview diffs, require confirmation, and log changes for auditability. Enforce permissions, provide rollback, and post-change monitoring links to validate outcomes. Deep-link back to the heatmap state after applying fixes to streamline iterative adjustments.

Acceptance Criteria
Single-Cell Ranked Recommendations Generation
Given a user selects one underperforming heatmap cell (specific region, day, hour, and cohort) When the user clicks "Recommended Fixes" Then the system returns a ranked list within 2 seconds containing at least one recommendation And each recommendation displays: proposed window/rule change, target region/cohort, projected show-rate lift (%) with confidence (Low/Med/High), affected meeting count (next 30 days), and a one-sentence rationale And recommendations are sorted by Impact Score = projected_lift_percent × affected_meetings (descending) And all proposed times fall within the region’s working hours configured in org settings
Bulk Selection Aggregation and Conflict Resolution
Given a user multi-selects two or more underperforming cells across regions and/or cohorts When the user clicks "Recommended Fixes" Then the system aggregates opportunities, deduplicates overlapping windows, and resolves conflicts so that no meeting or rule is adjusted twice And the result displays a selection summary (cells N, regions M, cohorts K, unique windows H) and a combined ranked recommendation list And if no viable alternatives exist, the system shows "No viable recommendations" with reasons (e.g., constraints, data sparsity) and a link to adjust filters
One-Click Apply Opens Pre-Populated Scheduler
Given the recommendations panel is visible and the user selects one or more recommendations When the user clicks "Apply in Scheduler" Then TimeMeld Scheduler opens within 2 seconds in a new tab/window And the scheduler is pre-populated with the selected recommendations (windows/rules, regions, cohorts) as a pending change set with a unique Change Request ID And the deep-link contains the heatmap context (filters, date range, selected cells) encoded in URL parameters
Diff Preview, Confirmation, and Audit Logging
Given a pre-populated change set is open in the scheduler When the user clicks "Review & Confirm" Then a diff view shows current vs proposed values per rule/window and the count of affected upcoming meetings with IDs And the user must explicitly confirm (checkbox + Confirm button) before changes are applied And upon confirmation, an audit log entry is created with user ID, timestamp, change set diff, source heatmap context, recommendation IDs, and outcome status
Permissions Enforcement for Applying Fixes
Given organization roles and permissions are configured When a user without "Apply Fixes" permission views recommendations Then apply/confirm controls are disabled with an explanatory tooltip and server-side checks prevent direct-link application (HTTP 403) And when a user with "Apply Fixes" permission performs the same actions Then the user can proceed to confirm and apply, and the action is recorded with their identity in the audit log
Rollback and Post-Change Monitoring Links
Given a change set has been successfully applied When the user clicks "Rollback" within the configured rollback window (default 24 hours) Then prior rules/windows are restored exactly and affected meetings are reverted or updated accordingly, with notifications sent to impacted organizers And an audit log entry records the rollback with a reference to the original Change Request ID And a monitoring link is provided that opens a post-change performance view (heatmap/report) scoped to impacted regions/cohorts and next 14 days
Deep-Link Back to Preserved Heatmap State
Given a user applies or cancels from the scheduler When they return via the "Back to Heatmap" link or automated redirect Then the heatmap restores the exact prior state (filters, date range, cohort comparison, scroll position, and selected cells) And a dismissible banner summarizes applied actions with a link to the Change Request details And the preserved state remains valid for at least 30 minutes via URL parameters
Permissions, Privacy & Governance
"As a security-conscious admin, I want strict access controls and privacy safeguards on heatmap data so that we can gain insights without exposing sensitive information."
Description

Implement role-based access controls so org admins can see org-wide data, team leads see their teams, and individuals see only aggregated views that protect privacy. Enforce minimum-N masking, region-based data residency rules, and redaction of PII in tooltips, exports, and shared links. Provide expiring, permission-aware share URLs for views and comparisons. Log access and configuration changes for audits and support data retention controls aligned with organizational policies. Ensure SSO integration and adherence to security standards to safeguard sensitive scheduling and attendance data.

Acceptance Criteria
RBAC: Admin, Lead, Individual Visibility in Drift Heatmap
Given an Org Admin is authenticated via SSO, When they open Drift Heatmap, Then they can select All Teams and view org-wide aggregates unless min-N masking applies. Given a Team Lead of Team A is authenticated, When they attempt to view Team B or All Teams, Then the UI displays "Insufficient permissions" and the API responds 403, and no data is rendered. Given an Individual Contributor is authenticated, When they open Drift Heatmap, Then the team filter is disabled and only aggregates at or above min-N are shown; no user-level drilldowns are available. Given any user attempts to access a heatmap view outside their scope via direct URL, When the request is made, Then the server returns 403 and the response omits whether the resource exists; an audit log entry is created.
Privacy Masking: Minimum-N Aggregation Enforcement
Given org minN is configured to 5, When a heatmap cell’s sample size is less than 5, Then the cell displays "—" and the tooltip shows "Insufficient sample size"; raw counts are hidden. Given a user hovers or clicks a masked cell, When requesting details, Then the API returns 200 with masked=true and no counts; drilldown panels do not render individual records. Given an export is generated for a view containing masked cells, When the CSV/JSON is downloaded, Then all masked cells are represented as null and include reason="minN". Given an admin updates minN from 5 to 8, When saved, Then the change propagates within 5 minutes and is reflected in UI and exports; the change is recorded in the audit log.
Data Residency: Regional Storage and Processing
Given org residency=EU, When Drift Heatmap loads, Then all data queries are served from EU endpoints and audit logs record region=EU for each request. Given a share link or export is requested by an EU org, When generated, Then the URL host and storage are located in EU; cross-region transfer attempts are blocked with 403 and logged. Given a view combines EU and US teams, When a user attempts to load raw comparative data, Then cross-region raw joins are prevented; only aggregated results that meet both regions’ minN are returned; otherwise 403 region policy violation is returned. Given an admin initiates residency change EU→US, When migration is in progress, Then the Heatmap remains read-only with banner "Data migration in progress"; all accesses and changes are logged with pre/post region.
PII Redaction Across UI, Tooltips, Exports, and Links
Given any user role, When viewing tooltips or hover details, Then no PII (emails, full names, phone numbers, calendar subjects, meeting URLs) is displayed; only aggregates and anonymized labels (e.g., Team A, Region EU). Given an export is generated, When inspected, Then it contains no PII fields and no values matching PII regexes (email, phone) and event subjects are blank or hashed; a data dictionary is included without PII. Given a shared link is created, When inspecting its URL and response payload, Then it contains no PII or stable identifiers; IDs are ephemeral and scoped to the share; counts are masked by min-N as applicable. Given a client requests unredacted details via undocumented fields, When the API receives the request, Then it returns 400 and logs a redaction policy violation.
Permission-Aware, Expiring Share URLs for Views and Comparisons
Given a user with Share permission, When generating a share URL, Then they can set expiry datetime (default 7 days, max 90 days) and scope (current view, filters, and optional comparison); creation is logged. Given a recipient opens the share URL, When RBAC is evaluated, Then the data returned is limited to their permissions; unauthorized teams are excluded or masked; forbidden access returns 403. Given the share URL is expired, When accessed, Then the server returns 410 Gone and the UI shows "Link expired"; access attempt is logged. Given an owner revokes a share, When revoked, Then subsequent accesses return 403; share cannot be listed or guessed (unguessable token length >= 128 bits); links are hosted in the org’s residency region.
Audit Logging and Retention Controls
Given any access to Heatmap, sharing, export, or settings change, When the action occurs, Then an immutable audit log entry is created with user_id, role, action, entity, timestamp (UTC), IP, region, result, and diff where applicable. Given an admin sets log retention to 180 days, When the retention job runs, Then log records older than 180 days are purged within 24 hours; purge events are themselves logged. Given an admin exports audit logs, When the export completes, Then the file respects residency, contains no PII fields, and includes a checksum; the export event is audited. Given an integrity check is requested, When run, Then the system reports pass/fail for tamper-evidence; any failure blocks exports and raises an alert.
SSO Integration and Security Standards Enforcement
Given SSO is enabled, When users authenticate via SAML or OIDC (Okta, Azure AD, Google Workspace), Then JIT provisioning assigns default roles; password login is disabled; SCIM sync (if configured) updates roles within 15 minutes. Given session management policies, When a session is idle for 60 minutes, Then it expires; IdP-initiated revocations take effect within 5 minutes; sensitive actions require re-auth within 15 minutes. Given transport and storage security requirements, When inspecting the service, Then TLS 1.2+ is enforced with HSTS and CSP headers; data at rest uses AES-256; no critical/high vulnerabilities are present in the latest scan and pen test. Given a security incident drill, When simulated, Then access to PII remains blocked, audit trails are intact, and rotation of share tokens and session keys completes within SLA (60 minutes).

Adaptive Baselines

Automatically learns each team’s normal attendance by region and season, adjusting for holidays and quiet weeks to prevent false alarms. You get timely, trustworthy drift alerts that reflect reality—not one‑size‑fits‑all thresholds.

Requirements

Regional Attendance Baseline Engine
"As a product manager, I want accurate, regional and seasonal attendance baselines so that I can trust drift alerts and avoid chasing normal fluctuations."
Description

Automatically compute per-team attendance baselines segmented by region, role, and local working hours, capturing weekday patterns and seasonal trends from rolling historical calendar signals. The engine ingests attendance outcomes for recurring meetings, applies recency-weighted decay, and produces expected attendance percentages for each meeting archetype and time window. Baselines are stored in a versioned feature store and exposed via API to TimeMeld’s meeting-window scorer and alerting service, ensuring scheduling and alerts reflect realistic team behavior.

Acceptance Criteria
Baseline Computation by Region, Role, and Local Working Hours
Given a team with at least 12 weeks of historical recurring meeting attendance labeled with region, role, and meeting local start time When the engine runs on its daily schedule at 02:00 UTC Then it computes per-team expected attendance percentages segmented by region, role, and local working-hour buckets (e.g., 09:00-12:00, 13:00-17:00 local time) for each weekday And published baselines only include segments with at least 20 occurrences or 6 weeks of data; otherwise a parent-level fallback (missing dimension rolled up) is produced and flagged with fallback=true And each baseline record contains fields: team_id, region, role, weekday, local_hour_bucket, expected_attendance_percent (0-100), sample_size, data_window_start, data_window_end, computation_time And the daily job finishes within 15 minutes for a team with <= 10,000 recurring-event instances
Recency-Weighted Decay Applied to Attendance Signals
Given historical attendance events spanning at least 26 weeks When computing baselines Then the engine applies an exponential decay with a default half-life of 8 weeks (configurable per team) so that events at t weeks ago have weight 0.5^(t/8) And weights are normalized to sum to 1 per segment before computing expected_attendance_percent And a unit test varying the last 4 weeks attendance by +20% changes the baseline by at least +10% while holding prior weeks constant And the configuration endpoint rejects half-life values outside 2-16 weeks with HTTP 400 and code=invalid_half_life
Seasonality and Local Holiday Adjustment
Given a region’s official public holiday calendar and detected company-wide shutdowns When computing baselines Then attendance events on a public holiday in that region are excluded from baseline calculations (weight=0) unless explicitly overridden And the engine identifies seasonal quiet weeks when weekly meeting volume drops >= 40% vs the prior 8-week median for that region; attendance in those weeks is down-weighted by 80% (weight=0.2) And baseline metadata includes seasonality_adjustments entries with {type, period_start, period_end, weight_rule} And a test dataset containing a holiday week and a quiet week produces baselines that differ from the unadjusted baseline by at least 5 percentage points for the affected segments
Meeting Archetype and Time-Window Baseline Output
Given meeting events labeled with archetype and local start times When computing baselines Then the engine produces expected_attendance_percent per combination of archetype, weekday, and 30-minute local time window And if archetype is unknown for >= 30% of events in a segment, a generic archetype baseline is produced and unknown events are included there And baseline output conforms to schema v1.0 with fields {archetype, weekday, local_time_window_start, local_time_window_end, expected_attendance_percent, sample_size, version_id} and validates against JSON Schema with zero errors And expected_attendance_percent values are numeric with one decimal precision and bounded within [0.0, 100.0]
Versioned Feature Store Persistence and Retrieval
Given a new baseline computation run When writing to the feature store Then records are written under a new immutable version_id following pattern baseline_{yyyy-mm-dd}_{run_id} and marked status=active And a read for (team_id, region, role, weekday, local_hour_bucket, archetype) with as_of_date returns the latest active version whose data_window_end <= as_of_date And rewrites with the same version_id are idempotent with no duplicate records, while publishing a newer version atomically flips prior active versions to status=superseded And at least 365 days of versions are retained and retrievable
Baseline API for Scorer and Alerting Services
Given the feature store contains active baselines When the GET /v1/baselines endpoint is called with team_id, region, role, weekday, local_time (ISO-8601 with timezone), and archetype Then it returns 200 with expected_attendance_percent, version_id, sample_size, and effective_period And if no segment baseline exists, the API returns the closest available fallback (dropping dimensions in the order: role -> local_hour_bucket -> archetype -> region) and includes fallback=true and fallback_dimensions And 99th percentile latency under 100 RPS is <= 200 ms with cache hit rate >= 80% for repeated queries And requests without valid auth tokens return 401; malformed parameters return 400 with error codes
Drift Signals Respect Adaptive Baselines (False-Alarm Prevention)
Given an alerting service requests a baseline for a meeting occurrence during a flagged quiet week or on a local holiday When comparing observed attendance to expected_attendance_percent Then no drift alert is issued unless deviation exceeds the team’s configured alert_threshold_percent (default 15%) after seasonal adjustments And the baseline response includes seasonality flags {holiday: true|false, quiet_week: true|false} for traceability And regression tests show a synthetic dataset with a holiday week reduces false positive alerts by at least 80% compared to an unadjusted baseline And baselines older than 24 hours are not served; the API returns 503 with code=baseline_stale until a fresh run completes
Holiday and Quiet-Period Awareness
"As an operations lead, I want baselines to account for holidays and quiet weeks so that expected dips don’t trigger false alarms."
Description

Integrate public holiday calendars by country/region, company-wide closure schedules, user-declared PTO, and auto-detected quiet weeks to dynamically adjust attendance baselines. The system maps each participant to a locale, applies holiday and quiet-week modifiers, and suppresses baseline expectations when reduced availability is expected. Admins can define custom calendars and overrides, ensuring baselines and alerts remain faithful to real-world availability across distributed teams.

Acceptance Criteria
Locale-Based Public Holiday Suppression
Given a meeting occurrence on 2025-11-27 16:00 UTC with participants mapped to locales {Alice: US, Bob: DE, Chandra: IN} and US public holiday "Thanksgiving Day" on 2025-11-27 When attendance baselines are computed for that occurrence Then the expected attendance excludes Alice and decreases by exactly 1 from the non-holiday baseline And no drift alert is generated if actual attendance equals the adjusted expected attendance And the holiday is sourced from the configured US public holiday calendar with a refresh timestamp within the last 24 hours And if the holiday feed is unavailable, the system uses the last known good calendar for that locale, retries per exponential backoff, and emits no alerts solely due to the feed outage
Company Closure Calendar Application
Given an admin-defined company closure from 2025-12-24 00:00 to 2025-12-26 23:59 in company timezone America/Los_Angeles and a recurring team meeting on 2025-12-25 18:00 UTC When baselines are computed for that occurrence Then the expected attendance is set to 0 for that occurrence And no drift alerts or low-attendance notifications are emitted for that occurrence And the closure takes precedence over public holidays and user PTO (baseline remains 0 regardless of other signals) And the closure window is applied using the company timezone boundaries even when participants are in other timezones
User-Declared PTO Adjustment and Latency
Given user Bob declares PTO from 2025-07-01 09:00 to 2025-07-05 18:00 in Europe/Berlin and there is a meeting on 2025-07-02 10:00 Europe/Berlin When the PTO is saved Then Bob is excluded from the expected attendance for any meeting overlapping the PTO window And baseline recomputation and any pending drift-alert predictions reflect the change within 5 minutes of the PTO save And for partial-day PTO (e.g., 2025-07-03 09:00–13:00), Bob’s attendance weight is reduced proportionally (>=50% reduction for a half-day block) And if an admin applies a per-occurrence force-include override for Bob, the override supersedes the PTO and the rationale records "override > PTO"
Quiet Week Auto-Detection and Damping
Given the last 4-week weekday baseline for the team for Thursdays is 10 expected attendees and the current week has >=50% of participants marked OOO (PTO+public holiday+custom closure) for at least 3 of 5 weekdays across >=2 regions When the system computes the baseline for the current Thursday Then the expected attendance is reduced to baseline × (1 − OOO_rate) = 10 × (1 − 0.5) = 5 And no drift alert triggers if actual attendance ≥ the damped baseline (5) And if global OOO_rate <30% and the OOO concentration is isolated to a single region, no quiet-week modifier is applied And the quiet-week flag automatically clears the following week when global OOO_rate drops below 20%
Admin Custom Calendars and Precedence
Given an admin creates a custom calendar event "Engineering Hackday" with reduced availability 50% for group Engineering on 2025-09-15 When baselines are computed for 2025-09-15 Then expected attendance for Engineering-only meetings is reduced by 50%, and for cross-functional meetings only Engineering participant weights are reduced And precedence order is enforced: per-occurrence admin override > company closure > admin custom calendar > user PTO > public holiday > quiet-week damping And on a day with company closure + custom calendar + PTO for Alice, the expected attendance is 0 and the rationale shows "company closure" And if an admin force-includes Alice for a specific occurrence, Alice is counted despite other signals and the rationale shows "override"
Mixed-Locale Meeting Adjustments and Alert Behavior
Given a meeting with 8 participants across locales {US:3, UK:2, IN:2, AU:1} and the occurrence date is a UK bank holiday only When the baseline is computed Then the expected attendance is reduced from 8 to 6 by excluding the 2 UK participants And if actual attendance is 6 or 7, no drift alert is sent; if actual attendance ≤5, one drift alert is emitted within 10 minutes post-meeting referencing the adjusted baseline And for the next occurrence where an AU public holiday affects 1 participant, the expected attendance is reduced by 1 accordingly And participant-locale mapping prioritizes user-declared locale over calendar timezone; if no user-declared locale exists, calendar primary timezone is used
Audit Log and Retroactive Recompute
Given baseline adjustments occur due to any signal (PUBLIC_HOLIDAY, COMPANY_CLOSURE, PTO, CUSTOM_CAL, QUIET_WEEK, OVERRIDE) When the baseline is computed for an occurrence Then an audit entry is stored with fields {occurrence_id, participant_id, reason_code, delta_before_after, source_id, timestamp} And when an admin adds a missed holiday retroactively and triggers recompute for the past 30 days Then past baselines and alerts are recalculated within 15 minutes for a team ≤100 participants and a changelog of alert differences is available And the UI/API exposes before/after expected attendance and reason trails for each affected occurrence
Drift Detection with Adaptive Thresholds
"As a meeting owner, I want adaptive drift alerts based on meaningful deviation so that I only act when attendance truly changes."
Description

Continuously compare actual attendance for recurring meetings against the context-aware baseline using confidence intervals that adapt to sample size, seasonality, and recent variance. Generate actionable drift alerts only when deviations are sustained and statistically meaningful, with cooldowns, duplicate suppression, and channel routing (Slack/email) managed by team preferences. Alerts are automatically muted during known holidays and quiet periods to minimize noise.

Acceptance Criteria
Baseline Learns by Region and Season
Given team regions and historical attendance per recurring meeting instance When the baseline job runs daily at 02:00 UTC Then it computes per-meeting, per-region baseline attendance for the next 8 weeks using rolling windows aligned to weekday and local season Given dates marked as holidays or quiet periods in the team calendar When computing baselines Then those occurrences are excluded from training windows and from n (sample size) Given at least 6 past eligible occurrences exist for a region–weekday pair When computing baselines Then the baseline is marked "stable"; else it is marked "warming" and flagged for wider confidence intervals downstream Given months representing the same local season as the target occurrence When weighting historical samples Then same-season samples receive weights >= 2x non-season samples
Adaptive Confidence Intervals and Small-Sample Handling
Given baseline mean and variance per region–meeting and sample size n When computing confidence intervals Then a 95% CI is produced using t-distribution for n < 30 and normal approximation for n >= 30 Given n < 6 or coefficient of variation > 0.5 When computing the CI Then the interval width is multiplied by a configurable inflation factor f (default f = 1.5) Given n = 0 eligible history for the region–meeting When detection runs Then drift is not evaluated, no alert is emitted, and result code "insufficient_history" is logged
Sustained Drift Detection with Cooldown
Given sustained_window = 3 occurrences and cooldown_hours = 72 (configurable per team) When actual attendance falls below the lower CI bound in at least 3 consecutive eligible occurrences Then a single "downward_drift" alert is emitted and cooldown starts for 72 hours Given cooldown is active When subsequent detection runs see the same drift condition Then no new alert is emitted until cooldown expires Given cooldown has expired When the drift condition holds for at least 1 new eligible occurrence Then a new alert is emitted with incremented sequence number (e.g., #2) Given only 1 of the last 3 eligible occurrences is outside the CI When detection runs Then no drift alert is emitted
Holiday and Quiet Period Muting
Given a meeting occurrence falls on a date marked as holiday or within a configured quiet period When detection executes Then alerts are suppressed and the occurrence is excluded from sustained_window counting and baseline updates Given a quiet period ends When the next eligible occurrence happens Then detection resumes and only eligible (non-muted) occurrences are considered for sustained_window history Given a make-up meeting during a quiet period has "override alerts" enabled by the owner When detection executes Then detection runs and may alert despite the quiet period; the override is logged
Duplicate Suppression and Alert Consolidation
Given multiple detection jobs run within 24 hours for the same meeting and drift key (direction + affected regions set) When a subsequent alert would be emitted Then it is suppressed and the original alert is updated with a cumulative evidence counter Given separate region-specific drifts are detected for the same meeting within 24 hours When alerts are emitted Then they are consolidated into a single message listing all affected regions with their statistics Given the drift direction flips within 24 hours (e.g., from downward to upward) When evaluating duplicate suppression Then a new alert is allowed with a new drift key, and the previous cooldown is closed
Preference-based Channel Routing and Delivery
Given team preferences specify Slack channel "#ops" and fallback email "alerts@company.com" When an alert is emitted Then a Slack message is posted to #ops including: meeting name, drift direction, magnitude (% vs baseline), CI bounds, n, affected regions, sustained_window, and link to inspect baseline Given Slack delivery fails (non-2xx response) or channel not found When retrying up to 3 times within 5 minutes Then on final failure an email with equivalent content is sent to the fallback within 2 minutes of the last retry Given user-level opt-out preferences When routing emails Then opted-out recipients do not receive the alert and the routing decision is logged
Alert Explainability and Audit Trail
Given an alert is emitted When the alert detail endpoint is queried Then it returns inputs (time range, n, mean, variance, CI method, thresholds, sustained_window evidence), decision rationale, and baseline version used Given detection runs without emitting an alert When audit logs are queried for that run Then a record exists with outcome and reason code (e.g., within_CI, insufficient_history, muted_holiday, cooldown_active) Given the same historical dataset and configuration are replayed in a dry-run When detection re-executes Then it produces the same alert/no-alert decisions and timestamps within ±1 second
Explainable Alerts and Baseline Visualization
"As a team lead, I want clear explanations of what changed and why an alert fired so that I can quickly diagnose and address attendance issues."
Description

Provide a dashboard and inline meeting view that explains why an alert triggered by showing baseline values, recent actuals, confidence bands, seasonality factors, and applied holiday/quiet-week adjustments. Highlight top contributing segments (e.g., region or time-of-day) and display change history so users can understand trends over time. Expose this context in TimeMeld’s Team Health and meeting details to build trust and accelerate corrective actions.

Acceptance Criteria
Team Health Alert Panel Explains Baseline, Actuals, Bands, and Adjustments
- Given a drift alert is visible in Team Health for a team, when the user opens the alert details panel, then the panel displays the baseline value with units for the alerted metric. - Given the alert details panel is open, when rendering recent performance, then at least the last 12 data points with timestamps are shown and are queryable via tooltip values. - Given the alert date is selected, when bounds are calculated, then the 95% confidence band lower and upper bounds are displayed numerically and visually on the chart. - Given seasonality and adjustments are applied, when computing expected, then the seasonality factor and each applied holiday/quiet-week adjustment are listed with names, regions, and numeric deltas. - Given the alert trigger condition, when the page renders, then a "Trigger reason" sentence states actual vs expected and bound (e.g., "Actual 62% fell 7pp below the 95% lower bound 69%").
Inline Meeting Details Show Alert Context and Contributors
- Given a meeting detail drawer is opened from a flagged meeting, when the content loads, then P95 load time is <= 1500 ms on a 10 Mbps connection. - Given the meeting is flagged, when computing expectation, then the displayed expected attendance incorporates region mix, time-of-day weighting, and any applicable adjustments, with a "View calculation" tooltip exposing terms used. - Given the meeting is flagged, when contributors are shown, then the top 3 contributing segments are listed with contribution % and absolute impact, and their cumulative contribution is displayed. - Given data is shown, when displaying freshness, then a "Last updated" timestamp appears in viewer local time and UTC.
Top Contributing Segments Ranking and Drill-Down
- Given a drift alert details view, when the "Top contributors" list renders, then items are sorted by absolute contribution descending. - Given contributors are listed, when a user clicks a segment, then the chart filters to that segment and a filter chip appears; clicking multiple segments enables multi-select; filters can be cleared individually or all at once. - Given contributions are computed, when totals are displayed, then the sum of segment contributions is within ±5% of the model-attributed deviation, or an explanation banner is shown. - Given no segment contributes >= 10% individually, when the list renders, then a "No dominant segments" message is displayed.
Change History Timeline and Audit Trail
- Given the user opens Change History, when entries are loaded for a selected date range, then baseline retrains, seasonality updates, holiday calendar imports/edits, quiet-week windows, and threshold changes are listed chronologically. - Given a change entry is shown, when details expand, then timestamp (UTC and local), actor (user or system), change type, and before/after values are visible. - Given filters are applied, when selecting change types, then the list updates without full reload within 300 ms. - Given user role permissions, when a non-admin views history, then actor identities are anonymized; admins see full details. - Given export is requested, when the user clicks "Export CSV", then a CSV with the visible entries is downloaded and matches the current filters. - Given retention policy, when querying beyond 180 days, then older entries are not shown and a "Retention limit" notice appears.
Holiday and Quiet-Week Adjustment Visibility and Alert Suppression
- Given an alert date overlaps a recognized holiday or declared quiet week for any team region, when the explanation renders, then a badge shows the event name, region(s), and numeric adjustment applied. - Given adjustments move the actual within the confidence band, when evaluating alerting, then the alert is marked as "Suppressed" and appears in history with "Suppressed by <event>". - Given a multi-region team, when multiple regional adjustments exist, then the UI shows up to 5 regions plus a "View all" link that reveals the full list. - Given an adjustment references an unknown calendar source, when rendering, then an "Unmapped event" tag with a link to resolve calendar mapping is shown.
Confidence Band Transparency and Interactive Controls
- Given the alert details view is open, when the user opens the confidence control, then options for 90%, 95%, and 99% are available, with the team default preselected. - Given the user switches the confidence level, when bounds recompute, then chart bounds and numeric values update within 200 ms and the trigger reason recalculates accordingly; no settings are saved by this action. - Given the confidence control is hovered, when the tooltip appears, then it explains the bound calculation and terms used.
Data Freshness, Timezones, and Units Consistency
- Given any explanation view is open, when metadata renders, then "Last updated" time is shown in both user local timezone and UTC. - Given data is fetched, when recency exceeds 15 minutes, then a warning banner "Data may be stale" is displayed. - Given values are displayed, when numerics render, then all values include correct units (%, attendees, days) and use the user's locale formatting for numbers and dates. - Given timezone weightings are shown, when tooltips open, then the team's target time window is displayed in the team timezone and converted to the viewer's timezone.
Feedback Loop and Model Tuning
"As a product manager, I want to label alerts and see accuracy improve so that noise decreases and I can rely on the system."
Description

Enable users to mark alerts as helpful or false alarm, add context, and suggest corrections to region/holiday mappings. Capture feedback as labels for offline evaluation and use it to adjust thresholds and feature weights per team, improving precision over time. Provide periodic accuracy reports so stakeholders can see reductions in false positives and the impact of their feedback.

Acceptance Criteria
Inline Alert Feedback: Helpful vs False Alarm
Given a user views an attendance drift alert in-app or via email When the user clicks "Helpful" or "False Alarm" Then the selection is persisted within 2 seconds and a success confirmation is displayed Given a previously labeled alert When the same user relabels it within 15 minutes Then the prior label is replaced, the change is logged, and after 15 minutes the label becomes read-only Given duplicate clicks on a label action within 10 seconds When processed Then only one label record is stored (idempotent) with userId, teamId, alertId, timestamp, and label
Add Context to Feedback Submission
Given the user marks an alert as "False Alarm" When the feedback modal opens Then the user must select at least one reason tag from [Holiday, Quiet Week, Region Mis-mapped, Data Issue, Other] and may add a note up to 500 characters Given the user submits context When saved Then the context is attached to the feedback record and visible in alert details and the audit log Given notes contain obvious PII patterns (e.g., emails) When stored Then the system masks the PII while retaining readability and indicates that redaction occurred
Suggest Region/Holiday Mapping Corrections
Given a user views an alert with reason "Region Mis-mapped" or selects "Suggest mapping fix" When the user opens the suggestion form Then the form allows specifying affected member(s), correct region(s), and holiday calendar source (provider or URL) with field validation Given a suggestion is submitted When an Admin reviews it Then the Admin can Approve or Reject; upon approval, mapping updates apply within 24 hours and impacted baselines are recalculated; the requester and team are notified Given a substantially duplicate suggestion exists in the last 30 days When a new identical suggestion is attempted Then the system prevents duplicate submission and links to the existing request
Per-Team Threshold and Feature Weight Tuning From Feedback
Given a team has ≥20 labeled alerts in the past 30 days When the weekly tuning job runs Then per-team thresholds and feature weights are re-estimated using labels and saved as a versioned model configuration Given the candidate configuration underperforms the current baseline on offline validation (precision decreases by >1% or false positive rate increases by >1%) When evaluated Then deployment is blocked and the prior configuration remains active Given a new configuration is deployed When active Then the change log shows version, deployment time, validation metrics deltas, and author "Auto-tuner"
Periodic Accuracy Reports With Feedback Impact
Given it is Monday 09:00 in the team’s primary timezone When report generation runs Then each team receives an in-app dashboard update and email including last 4 weeks vs prior 4 weeks: precision, recall, false positive rate, alert volume, and feedback count, plus an estimate of false positives avoided due to tuning Given a stakeholder downloads the CSV for the report period When compared to the metrics API for the same filters Then metric values match within 1% relative difference Given there were zero alerts in the period When the report is generated Then the report states "No alerts this period" and suppresses trend indicators
Feedback Data Capture and Auditability
Given a feedback event is submitted (label and optional context) When ingested Then an immutable record is written to the analytics warehouse table feedback_events with fields [eventId, alertId, teamId, userId, label, reasons[], note_redacted, createdAt] within 5 minutes for 99.5% of events measured monthly Given multiple events with the same eventId arrive When processed Then exactly-once semantics are enforced and no duplicates appear downstream Given an auditor filters by teamId and date range in the audit log When viewing results Then they see submitter, label, reasons, redacted notes, timestamps, and links to the originating alert, and can export to CSV
Admin Controls and Baseline Overrides
"As a workspace admin, I want controls and overrides for baselines and alerts so that I can handle edge cases and maintain reliability during transitions."
Description

Offer administrative controls for minimum data requirements, cold-start defaults for new teams, baseline freeze during org changes, manual overrides for exceptional periods, and configuration of alert channels and frequencies. Include audit logging and role-based access so only authorized users can alter baselines and notification behaviors. Provide export/import of baseline snapshots for governance and continuity.

Acceptance Criteria
Configure Minimum Data Requirements
Given I am an Org Admin on Admin > Adaptive Baselines settings When I set per-region minimum weeks_of_data to 4 and min_meetings to 20 and click Save Then teams/regions not meeting both thresholds have drift alerts automatically paused and display "Insufficient data" with current counts And if cold-start defaults are configured for the scope, those defaults are applied until thresholds are met And when thresholds become met, drift alerts resume within 15 minutes And an audit log entry records user, timestamp, scope, and before/after threshold values
Apply Cold-Start Defaults for New Teams
Given a team has not met the configured minimum data thresholds When an Admin assigns cold-start defaults (region, working hours, target attendance %, seasonality setting) to that team Then baseline calculations and drift alerts for that team use the cold-start defaults And the UI shows a Cold Start badge with the configured defaults And when thresholds are subsequently met, the system switches to the learned baseline within 15 minutes and writes an audit event And an Admin can end cold-start early, which takes effect immediately and is logged
Schedule Baseline Freeze During Org Changes
Given I select one or more teams/regions and schedule a baseline freeze with a start and end time When the freeze is active Then auto-learning updates are blocked and skipped updates are recorded in the audit log And drift comparisons continue against the frozen baseline values And the UI displays a Frozen badge with the freeze window And unfreezing re-enables auto-learning within 15 minutes and is logged
Manual Baseline Override for Exceptional Periods
Given I am an Admin and provide scope, date range, target baseline values/deltas, and a required reason When I create the manual override Then the override baseline takes precedence over both frozen and learned baselines for the specified date range And alerts and ergonomic window proposals reflect the override during its active period And overlapping overrides for the same scope are rejected with a validation error And upon override end, the system reverts to the prior state (frozen or learning) and records an audit entry
Configure Alert Channels and Frequencies
Given I configure alert channels (Email, Slack, Webhook) and frequencies (Immediate, Daily Digest) per team/region When I save valid targets and options, including quiet hours and timezone Then a confirmation is shown and a test notification can be sent successfully to each configured channel And delivery respects the configured quiet hours and digest schedule And configuration changes propagate to the alerting service within 5 minutes and are captured in the audit log
Enforce Role-Based Access Controls
Given roles exist (Owner, Admin, Analyst, Viewer) When a user without Owner/Admin role attempts to create, edit, freeze, override, import, or change alert configurations Then the action is blocked with an authorization error and a security audit event is recorded And Owners/Admins can perform these actions successfully, with required reason fields on freeze/override/import and full before/after values logged
Export/Import Baseline Snapshots
Given I am an Admin on Admin > Baseline Snapshots When I export a snapshot Then the file contains effective baselines, thresholds, freeze windows, overrides, and alert configs for the selected scope in JSON and CSV formats with a checksum and version And when I import a snapshot using Dry Run first Then schema and permission validation runs, conflicts are listed, and no changes are applied And when I import with Apply and choose Merge or Overwrite Then changes apply atomically, produce an audit record, and a rollback snapshot is created automatically
Data Privacy and Compliance Safeguards
"As a compliance officer, I want attendance modeling to protect personal data and meet regulatory requirements so that we can safely adopt the feature across regions."
Description

Aggregate and pseudonymize attendance signals so only team-level metrics are stored and displayed, with encryption in transit and at rest and strict role-based access to detailed views. Apply regional data residency rules and configurable retention to meet GDPR and similar regulations. Provide auditable consent and deletion workflows integrated with TimeMeld’s existing privacy controls.

Acceptance Criteria
Team-Level Aggregation and Pseudonymization for Adaptive Baselines
Given a team with 5 or more active members in the selected period When Adaptive Baselines computes or updates attendance metrics Then only aggregated team-level metrics (e.g., count, percentage, mean, variance) are persisted and displayed And no user_id, email, calendar_id, IP address, or device identifier fields are stored in any persistent datastore And any transient processing artifacts containing individual events have a TTL <= 24 hours and are automatically purged Given a cohort (team/region/seasonal slice) with fewer than 5 contributing members When a request is made to view or export attendance metrics Then the metrics are suppressed (no values returned) and the UI displays "Insufficient sample size" And no small-n cohort metrics are exported via API Given an engineer queries production datastores for fields matching identifiable attendee attributes When the query is executed Then zero records are returned for identifiable fields in persisted datasets related to attendance metrics
Encryption In Transit and At Rest for Attendance Metrics
Given any HTTP(S) endpoint handling attendance signals or metrics When a client connects Then TLS 1.2 or higher is enforced and HSTS is enabled (max-age >= 15552000) And connections using HTTP or TLS < 1.2 are rejected Given attendance metrics or transient attendance signals are stored When data is written at rest (databases, object storage, backups) Then AES-256 encryption at rest is enabled using KMS-managed keys And key rotation occurs at least every 90 days and is auditable Given an attempt is made to read encrypted storage without appropriate KMS permissions When the request is executed Then access is denied and the event is logged with user, resource, and timestamp
Role-Based Access Control for Detailed Attendance Views
Given organization roles {Org Admin, Privacy Officer, Team Admin, Member, Viewer} When a Member or Viewer attempts to access detailed attendance views or exports beyond team-level aggregates Then the request is denied with HTTP 403 and the event is logged Given an Org Admin or Privacy Officer is authenticated via SSO and MFA When they access detailed attendance configuration and audit pages Then access is granted And all access is recorded with user, role, timestamp, and resource Given a user's role is downgraded When the change is made in the admin console Then effective permissions reflect the change within 5 minutes across API, UI, and exports
Regional Data Residency Enforcement for EU Teams
Given a team with data residency set to EU When attendance signals are ingested and Adaptive Baselines compute runs Then storage location tags for primary and replicas are EU-only And compute jobs execute on EU-region nodes And no cross-region replication or processing occurs Given an admin attempts to export EU team metrics to a non-EU destination When the export is initiated Then the export is blocked unless a lawful transfer mechanism is recorded (e.g., SCC toggle with justification) And the transfer basis is written to the audit log Given data residency is EU When a data flow scan runs Then zero network calls are detected to non-EU endpoints for relevant data paths
Configurable Data Retention for Attendance Signals
Given an Org Admin sets retention for attendance signals to a value between 30 and 730 days (default 365) When the setting is saved Then the new retention policy is displayed in the admin UI and versioned in the audit log Given the retention is set to 180 days When the daily retention job runs Then all attendance signals older than 180 days are deleted or irreversibly aggregated And a deletion summary report (records scanned, deleted, retained) is produced and stored And no primary datastore contains records older than 180 days Given backups containing deleted records exist When the backup purge window elapses Then purged data is removed from backups within 35 days and the action is logged
Consent Capture and Right-to-Erasure Workflow
Given a new EU-based user is first processed for attendance signals When the user signs in or is first observed Then a consent prompt displays the specific purposes (attendance analytics for Adaptive Baselines) and links to the privacy policy And processing does not begin until explicit opt-in is recorded Given a user withdraws consent via Privacy Controls When the withdrawal is submitted Then new processing of attendance signals for that user stops within 24 hours And previously stored signals are deleted within 30 days And the user's contributions are excluded from the next model rebuild within 7 days Given a data deletion (Art. 17) request is received When the request is submitted via Privacy Controls or API Then an acknowledgment is sent within 72 hours And deletion is completed within 30 days across primary stores, derived datasets, and search indexes And the outcome is recorded in the audit log with request ID
Audit Logging and Export for Privacy Events
Given privacy-impacting events occur (access to detailed views, consent changes, retention updates, data exports, data deletions) When these events happen Then an immutable, append-only audit log entry is created with event_id, actor, role, action, resource, timestamp (UTC), IP, and outcome And entries are tamper-evident via chained hashes Given an Org Admin requests an audit export When filters (date range, event types, actors) are applied Then the system produces CSV and JSON exports within 60 seconds for <=100k events And a checksum of the export is provided Given an unauthorized user attempts to modify or delete audit logs When the attempt occurs Then the action is rejected and an alert is generated to security contacts

Impact Simulator

Test candidate time shifts before committing. See projected show‑rate lift, timezone burden changes, and rotation effects side‑by‑side so you can choose the most humane, high‑impact window with data—not hunches.

Requirements

Interactive Time Shift Controls
"As a remote team organizer, I want to tweak candidate meeting times and instantly see updated impact metrics so that I can quickly find a window that balances attendance and fairness."
Description

Provide an interactive UI to create and adjust candidate meeting time shifts (e.g., +/- 15/30/60 minutes, day offsets) with guardrails for participant working hours, meeting duration, recurrence rules, and organizer constraints. Recalculate key metrics (projected show-rate, timezone burden, and rotation effects) in real time as the user manipulates sliders or selects presets. Support keyboard and mouse interactions, accessibility labels, undo/redo, and reset-to-current-time. Integrate with TimeMeld’s participant profiles to respect declared core hours and with calendar availability to avoid hard conflicts. Handle both one-off and recurring meetings with preview across future instances.

Acceptance Criteria
Real‑Time Metrics Recalculation on Time Shift Adjustment
Given a scheduled meeting and the Impact Simulator is open with a visible candidate window When the user adjusts the time via slider drag, preset click, or keyboard step Then projected show‑rate, timezone burden, and rotation effects recompute and render within 500 ms after the last input event And a loading indicator appears within 300 ms if computation exceeds 500 ms and resolves within 2 seconds or shows a non-blocking error state And metric deltas are shown relative to the current scheduled time and reflect the new candidate time accurately (no stale values) And no UI element displays conflicting values for the same metric across panels
Guardrails for Core Hours, Conflicts, and Organizer Constraints
Given participant profiles with declared core hours and live calendar availability When the candidate time shift would place any part of the meeting outside a participant’s core hours Then the UI blocks commit (Apply) and displays a clear, per‑participant explanation with local‑time details And the candidate window cannot be committed if it overlaps any hard calendar conflict for any required attendee or organizer And the meeting duration and recurrence pattern remain unchanged by the shift; partial truncation is not permitted And day offsets and cross‑midnight shifts evaluate constraints in each participant’s local timezone correctly
Preset Shifts and Day Offsets Apply Correctly
Given preset controls for ±15/30/60 minutes and ±1 day When the user clicks a preset Then the candidate start time shifts by the preset amount from the current candidate value and remains within allowable bounds And consecutive preset clicks compound sequentially until Reset is invoked And the active preset state is visually indicated for 1 second after application And applying a preset immediately updates all metrics within 500 ms and re-validates guardrails
Keyboard Accessibility and Screen Reader Support
Given focus is on the time shift slider When the user presses Left/Right Arrow Then the candidate time changes by the configured step (default 15 minutes) and metrics update within 500 ms And pressing Shift+Arrow multiplies the step by 2; pressing PageUp/PageDown applies ±60 minutes And Space/Enter activates the focused preset; Tab/Shift+Tab traverse controls in a logical order with a visible focus indicator And all interactive elements expose accessible names, roles, and states; live metric updates announce concise deltas via an ARIA polite region; color is not the sole means of conveying status; contrast meets WCAG 2.1 AA
Undo, Redo, and Reset to Current Time
Given a series of time shift changes in the current session When the user invokes Undo (Ctrl/Cmd+Z) or clicks Undo Then the candidate time and all visible metrics revert to the prior state within 500 ms And Redo (Ctrl/Cmd+Shift+Z) reapplies the most recently undone change And the history retains at least the last 10 changes per session And invoking Reset returns the candidate to the original scheduled time, clears the history, and revalidates guardrails
Recurring Meetings: Future Instance Preview and Metrics
Given the meeting is part of a recurring series When the user applies a candidate time shift Then a preview displays the next 8 affected instances with local times per participant and per‑instance conflict indicators And aggregated metrics for the series (e.g., average projected show‑rate, total timezone burden change) update within 1 second And if any future instance has a hard conflict, Apply to Series is disabled until the conflict is resolved or that instance is excluded And instances spanning DST changes show correct local wall‑clock times and compute metrics using the adjusted local times
Attendance Lift Forecasting
"As a product manager, I want to see a data-backed estimate of how attendance will change for each proposed time shift so that I can choose the option most likely to improve show rates."
Description

Implement a forecasting service that projects show-rate changes for candidate time shifts using historical attendance, RSVP behavior, time-of-day/day-of-week effects, and participant reliability signals. Produce a scenario-level projected attendance percentage with a confidence band and callouts for low-data segments. Provide explainability (e.g., top drivers) and guard against bias by capping influence from outliers. Integrate with Google/Outlook calendar data via TimeMeld’s connectors, cache results for snappy UI, and expose a versioned API consumed by the Impact Simulator. Log model inputs/outputs for auditing and enable fallbacks to heuristic scoring when data is sparse.

Acceptance Criteria
Projection and Confidence Band Returned for Candidate Time Shift
Given a valid candidate time shift and sufficient historical attendance/RSVP/reliability data are available When the Impact Simulator requests a forecast via API v1 Then the response includes projectedAttendancePercent between 0 and 100 with two-decimal precision And the response includes confidenceInterval.lower and confidenceInterval.upper between 0 and 100 where lower <= projectedAttendancePercent <= upper And the response includes non-empty modelVersion and scenarioId fields And the same request payload yields identical projectedAttendancePercent within a single modelVersion (idempotent)
Explainability: Top Drivers Included Without PII
Given a forecast response is produced When inspecting explainability fields Then topDrivers contains between 3 and 5 items sorted by absoluteContribution descending And each driver includes featureName from an approved vocabulary and contributionPercent with sign (+/-) And the sum of absolute contributionPercent across topDrivers is >= 60% And no raw PII (names, emails) appears in featureName or description fields And each driver includes a shortExplanation string of <= 200 characters
Low-Data Callouts and Heuristic Fallback
Given the historical data volume for the scenario is below thresholds (e.g., <5 comparable past meetings or <3 participants with reliability scores) When a forecast is requested Then the response sets fallbackUsed = true and fallbackMethod matching pattern heuristic_v* And lowDataSegments lists the impacted segments with counts And projectedAttendancePercent and confidenceInterval are still returned And confidenceInterval width is >= 15 percentage points to reflect uncertainty And an info-level callout message is present indicating data sparsity
Outlier Influence Cap and Robustness
Given inputs that contain extreme outliers (e.g., a participant with an anomalous no-show streak or an event with abnormal RSVPs) When the model applies winsorization/capping at configured 5th/95th percentiles Then no single participant or event contributes >10% absolute weight to the final projection And comparing forecasts with and without the outlier capped yields an absolute difference <= 2 percentage points for the same scenario And modelMeta in the response exposes the capping configuration used (e.g., p5/p95)
Calendar Connector Integration and Data Freshness
Given Google and/or Outlook connectors are authorized When the forecasting service builds features Then it ingests past 12 weeks of events, attendance, and RSVP statuses per connected calendar And deduplicates events using stable IDs (eventId/iCalUID) and excludes canceled instances And data freshness (time since last successful sync) is <= 24 hours for active connectors And if a token is revoked or expired, the API returns 401 connector_auth_required with a remediation message and no PII in payload
Versioned API Contract and Cached Performance for Impact Simulator
Given the Impact Simulator calls POST /api/v1/forecast with a valid request body When the request is processed Then the response validates against JSON Schema forecast.v1.2 And the X-Api-Version response header equals 1.2 And breaking changes are only introduced under /api/v2/* endpoints And p95 latency for cached requests is <= 300 ms and for uncached (cold) requests is <= 2 s under nominal load And cache key includes candidateTime, participantIds hash, scenario options, and modelVersion with TTL = 15 minutes And relevant calendar updates invalidate affected cache entries within 60 seconds And rate limiting enforces <= 60 requests/min per org with 429 and Retry-After on exceedance
Audit Logging and Traceability of Forecasts
Given any forecast is generated When the service completes the request Then an audit record is stored with requestId, scenarioId, modelVersion, featureSummary (counts/means), projectedAttendancePercent, confidenceInterval, fallbackUsed, and a hash of topDrivers And participant identifiers are irreversibly hashed with a rotating salt and no raw PII is logged And audit records are retrievable by requestId via an internal endpoint and retained for 180 days with access control And logs include an ISO-8601 timestamp and are idempotent on retries (no duplicate records for the same requestId)
Timezone Burden Index
"As an engineering lead, I want a clear burden score by person and team for each candidate time so that I can avoid repeatedly scheduling outside someone’s core hours."
Description

Compute and display a per-participant and aggregate burden score for each scenario that reflects meeting occurrences outside core hours, severity of early/late local times, and recurrence frequency. Show deltas versus current schedule and highlight who benefits or is adversely impacted. Allow admins to configure core hours by person or team and weighting rules (e.g., heavier penalties for <6am or >9pm local). Provide visual summaries (heatmap, traffic-light badges) and exportable details. Integrate with participant timezone profiles and daylight saving time shifts to keep calculations accurate over time.

Acceptance Criteria
Per-Participant and Aggregate Burden Score Computation
Given a scenario with up to 50 participants, per-person/team core hours, and weighting rules defined When the Timezone Burden Index is computed for 52 weekly occurrences Then each occurrence is mapped to the participant's local wall time using their timezone profile and the effective DST offset on the occurrence date And band weights are applied (<06:00 heavy, 06:00-08:00 and 19:00-21:00 shoulder, >=21:00 heavy, in-core 0) unless overridden by configuration And per-participant score equals the sum over occurrences of (band_weight x recurrence_weight), rounded to 1 decimal place And aggregate sum and mean are calculated and displayed And the computation completes in <= 1 second And repeated runs with identical inputs return identical outputs
Delta vs Current Schedule Display
Given a baseline schedule is selected When a candidate scenario is loaded Then per-participant and aggregate deltas are shown as absolute and percent change vs baseline And improvements are indicated with green up arrows and regressions with red down arrows; neutral is gray And the participant list is sortable by largest absolute delta And participants with |delta| >= 10% are auto-highlighted And values update within 500 ms after any scenario parameter change
Admin Configurable Core Hours and Weighting Rules
Given an org admin is authenticated When the admin configures core hours at org, team, and person levels Then inputs accept 24h ranges, prevent overlaps, and support weekday/weekend distinctions And precedence is person > team > org for determining effective core hours And weighting rules allow numeric penalties per time band, with defaults heavier for <06:00 and >=21:00 And changes are persisted, versioned with timestamp and actor, and applied to new computations immediately And a secured API endpoint exists to read/write configuration; unauthorized requests are rejected with 401/403
Visual Summaries: Heatmap and Traffic-Light Badges
Given burden scores are computed for the scenario When the user opens the Burden view Then a heatmap renders with a visible legend and tooltips showing band counts and score components per participant And traffic-light badges show Good/Fair/Poor per participant using thresholds (default: Good <= 20th percentile, Fair >20th-<=60th, Poor >60th), which can be configured And all colors meet WCAG 2.1 AA contrast and use a color-blind-safe palette And keyboard navigation provides the same details as hover tooltips And re-render completes in <= 300 ms after configuration or scenario changes for datasets up to 50 participants x 52 occurrences
Exportable Details (CSV/JSON) with Metadata
Given a computed scenario and a selected baseline When the user exports as CSV or JSON Then the export includes per-participant fields: id, name, timezone (IANA), core-hours config version, band counts, per-occurrence timestamps (UTC and local), score, absolute delta, percent delta And aggregate metrics and configuration metadata (scenario id, baseline id, weights version, tzdb version, generated-at UTC) are included And CSV uses UTF-8 with RFC 4180 quoting and ISO 8601 timestamps; JSON adheres to a documented schema with explicit types And exports up to 10,000 rows complete in <= 5 seconds without freezing the UI And filenames include product, scenario id, and generated-at timestamp
DST and Timezone Profile Integration Accuracy
Given participants have IANA timezone IDs and profile history with effective dates When burden scores are computed across dates that include DST transitions or timezone changes Then local times reflect the correct offset per occurrence according to tzdb rules And nonexistent local times are skipped; ambiguous times are resolved to the post-transition offset by default (configurable) And past results remain stable after tzdb updates; future computations use the updated rules, recording the tzdb version in results And if a participant's timezone is missing or invalid, they are flagged and excluded from scoring with a clear error message
Rotation Equity Impact Visualizer
"As an ops leader, I want to see how a proposed time change will alter meeting ownership and fairness over the next several weeks so that we maintain a sustainable rotation."
Description

Model how each scenario affects the equity scoreboard and ownership rotation across upcoming instances. Display projected changes to cumulative burden, ownership frequency, and turn order, with alerts when a scenario violates fairness thresholds. Provide toggles to simulate different planning horizons (e.g., next 4/8/12 weeks). On commit, update the equity scoreboard and rotation plan atomically to maintain consistency with TimeMeld’s rotation engine. Include an API for downstream reporting and audit trail of changes.

Acceptance Criteria
Projected Equity Metrics Display
Given a candidate time shift scenario is selected and a planning horizon is set (e.g., 8 weeks) When the Rotation Equity Impact Visualizer renders projections Then it displays for every participant: current cumulative burden, projected cumulative burden, burden delta, current ownership frequency (count and % for the horizon), projected ownership frequency (count and %), current turn order for the next N instances, and projected turn order for the next N instances And all values are computed using the rotation engine’s timezone‑weighted rules for the selected horizon And burden delta values > 0 show a red up indicator, < 0 a green down indicator, and = 0 a neutral indicator And numeric values are rounded to one decimal place and match server calculations to that precision And the projection renders in ≤ 1000 ms for teams up to 30 participants and a 12‑week horizon
Horizon Toggle Recalculation (4/8/12 Weeks)
Given the user toggles the planning horizon between 4, 8, and 12 weeks When the horizon value changes Then ownership frequencies equal the number of meeting instances within [now, horizon) for each participant And cumulative burden values recompute for the new horizon and are non‑decreasing as the horizon length increases And the displayed turn order reflects the exact sequence of the next N instances within the selected horizon And the UI updates within ≤ 800 ms without losing the selected scenario or scroll position And the selected horizon is persisted in the session so returning to the simulator restores the last chosen value
Fairness Threshold Alerts
Given team fairness thresholds are configured (e.g., max burden variance %, max consecutive ownership count) When a simulated scenario violates any threshold Then an alert banner appears identifying each violated threshold, affected participants, and measured values vs limits And the alert includes a link or affordance to view the specific rows involved And clearing the violation (by adjusting inputs) removes the alert in real time without page reload And committing with active alerts triggers a confirmation modal summarizing the impacts before proceeding
Atomic Commit Updates to Scoreboard and Rotation Plan
Given a scenario has been reviewed and is ready to commit When the user clicks Commit Then the equity scoreboard and the rotation plan are updated in a single atomic transaction that produces a new versionId And if any part of the transaction fails, no changes are persisted and the UI shows a retriable error with correlationId And on success, the UI refreshes to show the updated scoreboard and turn order that match the last shown projections And concurrent commits are serialized; if a newer version exists than the previewed one, the commit is rejected with a non‑destructive conflict message prompting a refresh And the commit operation completes in ≤ 1500 ms for teams up to 30 participants and a 12‑week horizon
Audit Trail and Reporting API
Given a successful commit of a rotation change When the system records the event Then an immutable audit record is stored with: changeId, versionId, actorId, teamId, timestamp (UTC ISO8601), selected horizon, scenario parameters, pre‑commit metrics per participant, post‑commit metrics per participant, and fairness check results And a reporting endpoint GET /api/v1/rotation‑equity/changes exists with filters for date range, teamId, actorId, and cursor‑based pagination (limit, nextCursor) And the endpoint requires authentication; unauthorized requests return 401/403 without data And responses include a stable JSON schema with the above fields and a totalCount estimate And listing up to 100 records returns in ≤ 500 ms p95 And each record includes a SHA‑256 hash of the change payload for integrity verification
Projection Consistency with Rotation Engine
Given fixed team settings, calendar inputs, and fairness rules When the visualizer computes projections for a scenario and horizon Then cumulative burden per participant differs from the rotation engine output by ≤ 0.1, ownership frequencies match exactly, and the next N turn order positions match exactly And unit tests cover edge cases: uneven team sizes, mid‑horizon member join/leave, holiday skips, daylight‑saving transitions, and overlapping recurring series And projections for identical (scenario, horizon, inputs) are consistent across sessions within a 5‑minute window
Side-by-Side Scenario Comparison & Recommendation
"As a scheduler, I want to compare multiple candidate windows side-by-side and get a recommendation so that I can confidently pick the best option quickly."
Description

Enable creation and labeling of multiple what-if scenarios and render them in a side-by-side comparison view with sortable metrics: projected show-rate, burden index, and rotation impact. Provide a composite recommendation score with transparent weighting and allow users to adjust weights to reflect team priorities. Highlight the leading option per metric, flag conflicts, and offer a one-click Commit action that updates the meeting time and triggers TimeMeld’s invite automation. Persist user selections and record the decision rationale for future reference.

Acceptance Criteria
Create and Label Multiple What‑If Scenarios
Given a base meeting is loaded in Impact Simulator When the user creates multiple scenarios with distinct time shifts and labels Then the system allows creating at least 10 scenarios per meeting And each label is required, unique per meeting, 1–50 characters, and trimmed of leading/trailing spaces And attempting to save an invalid or duplicate label shows an inline error and prevents save And all created scenarios persist server‑side and reappear after page refresh or re-login
Side‑by‑Side Comparison with Sortable Metrics
Given 3 or more scenarios exist for the meeting When the user opens the Comparison view Then scenarios render in a grid with columns: Label, Projected Show‑Rate (%), Burden Index (0–100, lower is better), Rotation Impact (Δ fairness, higher is better), Composite Score And clicking any metric header sorts by that metric ascending/descending with a visible sort indicator And sorting completes within 300 ms for up to 50 scenarios And ties are secondarily sorted by Label A→Z
Composite Recommendation Score with Transparent Weighting and Adjustable Weights
Given the Comparison view is open with default weights applied When the user inspects the Composite Score formula Then the formula is displayed as Σ(normalized metric × weight) with per‑metric contributions visible on hover for each scenario And normalization treats higher Projected Show‑Rate and higher Rotation Impact as better, and lower Burden Index as better And the user can adjust weights for each metric from 0–100% in 1% increments, and total weight must sum to 100% And changes to weights update all Composite Scores and the Recommended badge within 250 ms And weight settings persist per user per meeting and are restored on revisit
Highlight Leaders Per Metric and Flag Conflicts
Given the Comparison grid is visible When metrics are calculated Then the leading scenario per metric is visually highlighted (max Projected Show‑Rate, min Burden Index, max Rotation Impact) And if different scenarios lead different metrics, a conflict banner appears summarizing which scenarios lead which metrics And selecting the conflict banner filters the grid to the involved scenarios And if the composite recommendation differs from any single-metric leader, an info callout explains the trade‑off with numeric weight contributions
One‑Click Commit Updates Meeting and Triggers Invites
Given the user has edit permission and a scenario is selected When the user clicks Commit Then the meeting time is updated to the scenario’s time and stored atomically with scenario ID and applied weights And TimeMeld invite automation triggers within 30 seconds, sending calendar updates to all attendees And the UI displays a success state with the new time and a link to the updated calendar event And on any failure, the system rolls back to the prior meeting time, shows a descriptive error, and offers a retry without partial state left behind
Persist Selections and Decision Rationale
Given a recommended scenario is selected When the user enters a decision rationale (up to 500 characters) and saves or commits Then the selection, applied weights, rationale, timestamp, and user are stored in the meeting’s Decision History And the most recent committed decision is labeled Current and appears at the top of the history And saved rationales are immutable after commit and visible to all users with access to the meeting
Access Control and Concurrency Safety
Given multiple users are viewing the same meeting in Impact Simulator When a user without edit permission attempts to adjust weights or commit Then those controls are disabled with a tooltip explaining required permissions And when two editors attempt to commit different scenarios concurrently Then exactly one commit succeeds; the other user receives a notice that the meeting was updated by <user> at <timestamp>, and their view refreshes to the committed scenario
Scenario Save, Share, and Commenting
"As a distributed team member, I want to share and discuss proposed meeting times with stakeholders so that we can reach alignment before committing."
Description

Allow users to save named scenario sets with metadata (owner, meeting series, created date) and share view/edit access with teammates or roles. Support inline comments, mentions, and attachments (e.g., policy links), plus version history to track changes. Provide secure, expiring share links and respect organization permission models. Integrate notifications with email/Slack to request reviews and capture approvals before committing a scenario. Store artifacts in TimeMeld for auditability and enable reloading scenarios later to re-run with updated data.

Acceptance Criteria
Save Named Scenario Set with Metadata and Initial Version
Given I have generated Impact Simulator results for a meeting series When I click "Save Scenario", enter a non-empty unique name within my org and meeting series, and confirm Then the system persists a scenario set with fields: id, name, owner=current user, meetingSeriesId, createdAt=UTC ISO-8601, version=1, and a read-only snapshot of inputs and computed metrics (show-rate lift, timezone burden, rotation effects) And Then saving a duplicate name within the same org and meeting series is rejected with a validation error and no record is created And Then the scenario appears in my scenario list within 2 seconds (p95) and is retrievable by id via API/UI And Then the API returns 201 Created with the scenario id, or 400 with field-level errors if validation fails
Share Access with Users and Roles (View/Edit) Respecting Org Permissions
Given a saved scenario set owned by me When I open Share settings and grant View or Edit access to specific users and/or roles within my org Then only principals with granted access can open the scenario; others in my org receive 403 and non-org users receive 404 And Then Viewers cannot modify scenario, comments, or permissions; Editors can modify scenario and comments but cannot delete the scenario unless explicitly allowed And Then role-based grants apply to all current members immediately and reflect membership changes within 5 minutes And Then I can revoke any grant, after which access is removed within 60 seconds and subsequent requests return 403
Secure Expiring Share Links
Given I have a saved scenario set When I generate a share link specifying permission level (View or Edit) and an expiry (24h, 7d [default], or 30d) Then the system issues a single-use tokenized URL bound to my org that requires authenticated access and enforces the selected permission And Then the link displays its creation and expiry times, and expires at the configured time; after expiry, requests return 410 Gone And Then I can manually revoke the link, invalidating the token within 60 seconds; revoked links return 410 And Then all link accesses are logged with actor, timestamp, and IP for audit retrieval
Inline Comments with Mentions, Threads, and Attachments with Notifications
Given I have at least View access to a scenario When I add a comment or reply in a thread Then the system stores the comment with author, timestamp, and version context and displays it in chronological order And Then I can edit my comment for up to 10 minutes; subsequent edits create a visible revision history And Then mentioning @users is auto-suggested; posting a mention notifies the mentioned users via Slack (if connected) or email within 1 minute and includes a deep link to the thread And Then attachments (PDF, DOCX, PNG, JPG, TXT, CSV) up to 25 MB each (max 5 per comment) are virus-scanned; infected uploads are blocked with an error And Then attempting to mention a user without access prompts to grant access; if declined, the mention cannot be posted
Review Requests and Approval Gate Before Commit
Given I have a saved scenario that requires approval before commit When I click "Request Review" and select approvers and a required approval count (default 1) Then approvers are notified via Slack/email with Approve/Request Changes actions and a deep link to the scenario And Then commit actions remain disabled until the required number of approvals is recorded and there are no open change requests And Then each approval records approver id, timestamp, scenario version, and comment; approvals are invalidated automatically when a new version is saved And Then if any approver requests changes, the scenario status reflects "Changes Requested" and notifications are sent to the owner
Version History, Diff, Restore, and Re-run with Latest Data
Given a scenario with one or more saved versions When I save changes Then a new version number increments by 1 and records author, timestamp, and change summary And Then the Version History view displays versions and a diff of inputs and computed metrics between any two versions within 2 seconds (p95) for up to 100 versions And Then choosing Restore on a prior version creates a new version that reproduces the restored inputs and notes the source version And Then selecting "Re-run with Latest Data" recomputes metrics using current org data and saves results as a new version linked to the originating version
Auditability and Export of Scenario Artifacts
Given scenarios, comments, shares, approvals, and version events are generated When an org admin queries the audit log for a date range Then the system returns a chronological record of create/edit/share/comment/approval/access events with actor, timestamp (UTC), and IP/user agent And Then admins can export a scenario set (current or a selected version) as JSON via API and UI download, with export completing within 10 seconds for scenarios under 5 MB And Then all scenario artifacts are stored in TimeMeld and remain retrievable for at least 12 months unless deleted per org retention policy

Auto Rebalance

Apply the chosen time shift to the whole series in one click. Calendars update, conferencing links persist, localized notices go out, and equity rules stay intact—with a built‑in rollback if priorities change.

Requirements

One-click Series Time Shift
"As a product manager coordinating a recurring cross-timezone meeting, I want to apply a single time shift to the entire series so that I can quickly realign schedules without manually editing each instance."
Description

Implements a bulk time-shift action that applies a selected delta or target anchor time to an entire recurring meeting series in one step. Validates the shift against TimeMeld’s timezone-weighted ergonomic rules (working-hour windows, rotation preferences, and regional holidays), preserves series exceptions, and previews the resulting schedule before confirmation. Integrates with the scheduling engine to recalculate proposed times and with the series model to ensure stable recurrence IDs. Minimizes manual edits, speeds coordination, and guarantees consistent application across all future instances.

Acceptance Criteria
One-Click Delta Shift Across Future Instances
- Given a recurring series with future instances and a selected time delta, When the user clicks Apply Shift, Then exactly all future instances move by the delta and past instances remain unchanged. - Then canceled instances remain canceled and no new instances are created or deleted. - Then each instance retains its UID/recurrenceId, conferencing link, attendees, and attachments. - Then the preview and the post-apply summary display the exact count of impacted instances and attendees. - Then instance times respect local timezone and DST transitions for all attendees.
Anchor-Time Shift With Ergonomic Validation and Preview
- Given a target anchor time is chosen, When the preview is generated, Then the scheduling engine recomputes proposed times respecting working-hour windows, rotation preferences, and regional holidays per configured rules. - Then each instance’s ergonomic score meets or exceeds the configured minimum; any violations are listed with reason tags (e.g., outside-hours, holiday-conflict, rotation-break). - Then hard-rule violations block confirmation (Confirm disabled) until resolved; soft-rule warnings allow confirmation with explicit user acknowledgement. - Then the preview shows before/after times per instance and a summary of rule outcomes.
Preservation of Series Exceptions and Per-Instance Overrides
- Given some instances have per-instance overrides (time, location, attendees, conferencing link) and some are canceled, When the shift is applied, Then those overrides persist and are not overwritten except for the base start-time offset. - Then canceled instances stay canceled and declined responses remain unchanged. - Then organizer and invitees lists are unchanged unless modified by an override. - Then no duplicate conferencing links are created; series-level links and per-instance links remain the same.
Calendar Updates and Localized Notifications
- Given the shift is confirmed, Then calendar entries for all attendees across connected providers are updated within 60 seconds at the 95th percentile and without creating duplicate events. - Then conference join URLs remain unchanged in all updated events. - Then each attendee receives a single localized notification (email/push) containing the new local time, language based on their locale, and an updated ICS; no attendee receives more than one notification for the same change. - Then notification delivery failures are surfaced with counts and retried according to the system’s retry policy.
Equity Rules Integrity Post-Shift
- Given the series uses equity rotation rules and a shared scoreboard, When the shift is applied, Then the rotation order and instance ownership assignments remain identical to the pre-shift plan. - Then per-participant equity metrics recompute for the new times but continue to satisfy configured equity constraints (no additional ownership assigned due to the shift). - Then the scoreboard view reflects updated times while preserving ownership slots and totals.
Rollback of Series Time Shift
- Given a shift was applied, When Rollback is invoked within 24 hours or before any subsequent manual edit to the series, Then all future instances revert to their exact pre-shift state (times, invites, notifications, overrides). - Then calendars reflect the rollback within 60 seconds at the 95th percentile, and attendees receive a single localized rollback notice. - Then audit logs link the rollback to the original shift via a correlation ID and capture counts of reverted instances and attendees.
Access Control, Performance, and Reliability
- Given a user without Manage Series permission attempts a shift, When they try to confirm, Then the action is blocked with a descriptive error and no changes are made. - Given a series with up to 500 future instances and up to 200 attendees, When a preview is requested, Then it completes within 5 seconds at the 95th percentile; When Apply is confirmed, Then the operation completes within 60 seconds at the 95th percentile. - Then the operation is idempotent by correlation ID, retries transient provider failures with exponential backoff, and reports a final success with counts or a failure with actionable error reasons without partial silent misapplies.
Cross-calendar Sync & Conflict Resolution
"As an engineering lead, I want the rebalance to update everyone’s calendars and resolve conflicts automatically so that attendance stays high and I don’t have to chase individual rebookings."
Description

Propagates the approved series shift to all participant calendars (Google, Outlook, iCloud) with idempotent updates, batched writes, and retries. Detects per-attendee conflicts at the new time, proposes nearest ergonomic alternatives within allowed windows, and flags hard conflicts for owner review. Maintains instance-level metadata (titles, agendas, notes, attachments) and preserves per-occurrence edits where compatible. Ensures ICS UID continuity and sends only differential updates to reduce churn and double-booking risk.

Acceptance Criteria
Idempotent Series Shift Across Google/Outlook/iCloud
Given a recurring meeting series with a stable ICS UID and attendees on Google, Outlook, and iCloud And Auto Rebalance proposes a +60 minute shift to all future occurrences When the owner approves the shift Then the system applies batched, provider-specific writes and preserves the same ICS UID for the series and occurrences And updates are idempotent such that re-running the operation produces no additional changes And all attendee calendars reflect the new start/end times within 5 minutes of approval And no duplicate events or duplicate email invites are created And failed writes are retried with exponential backoff up to 3 times per attendee before surfacing an error to the owner
Per-Attendee Conflict Detection and Alternative Proposals
Given at least one attendee is busy at the proposed new time When the sync runs after Auto Rebalance approval Then the attendee is marked as "conflict" and the owner is notified And up to 3 nearest ergonomic alternatives within the allowed scheduling window are proposed, scored by timezone ergonomics And a "hard conflict" is flagged if no viable alternative exists within the window And non-conflicted attendees remain scheduled at the approved new time And a consolidated conflict summary is posted to the series owner for review
Preserve Per-Occurrence Edits and Series Metadata
Given the series has titles, agendas, notes, attachments, and per-occurrence overrides When the series shift is applied Then series-level metadata remains unchanged except for start/end time fields And per-occurrence edits persist unless the edited field directly conflicts with the time shift, in which case only time fields are updated And previously canceled/skipped occurrences remain canceled and are not resurrected And attendee response statuses and conferencing links remain unchanged
Differential ICS Updates and UID Continuity
Given the series shift is approved When calendar updates are sent to providers via iTIP/CalDAV/Graph APIs Then the same ICS UID is used with an incremented SEQUENCE for each changed occurrence And only differential fields (time and sequence) are transmitted; no CANCEL+ADD is performed And each attendee receives at most one update notification per changed occurrence And no new invitation thread is created on Google, Outlook, or iCloud
Localized Notices and Conferencing Link Persistence
Given attendees have stored locale and timezone preferences When notices are dispatched for the approved shift Then each attendee receives a notice in their locale within 2 minutes of approval And the notice displays the new time in both organizer timezone and attendee local timezone And existing conferencing links (e.g., Google Meet/Zoom) remain unchanged in both the event and the notice And links are functional from the updated calendar entries
Rollback of Series Shift
Given the owner initiates a rollback within 24 hours of the applied shift When rollback executes Then all attendee calendars revert to the pre-shift schedule using the same ICS UID with incremented SEQUENCE And per-occurrence edits are restored to their pre-shift state And localized rollback notices are sent to all attendees within 5 minutes And the rollback is idempotent; re-running it produces no additional changes And an audit log entry records the initiator, timestamp, and affected occurrences
Conferencing Link Preservation
"As a remote engineer, I want the meeting link to remain the same after a series shift so that I can join without hunting for new dial-in details."
Description

Maintains continuity of conferencing details (Zoom, Google Meet, Teams) across the rebalance by retaining the existing meeting link, passcodes, and dial-ins while updating time and description fields. Handles provider-specific constraints (recurring vs. single-use links), regenerating links only when required (e.g., expired or revoked) and migrating security settings intact. Ensures join information stays consistent across calendar systems and notifications to prevent broken links and attendee confusion.

Acceptance Criteria
Preserve Existing Conferencing Link on Series Rebalance
Given a recurring meeting series with a valid conferencing link (Zoom/Google Meet/Microsoft Teams), passcode, and dial-ins on the organizer’s event and propagated to all instances And at least one attendee uses a different calendar system (Google, Outlook, or Apple Calendar) When Auto Rebalance shifts the entire series time without changing recurrence rules Then the conferencing join URL, meeting ID, passcode, and dial-ins remain exactly unchanged across all instances And the event start/end times and description/location fields update without duplicating or removing the join information And no new conferencing resource/meeting is created with the provider And attendee invites/updates preserve an identical join block to the pre-rebalance state
Regenerate Only When Link Invalid or Revoked
Given the existing conferencing link is detected as invalid (expired, revoked, deleted, or provider returns 4xx indicating non-existent) at rebalance time When Auto Rebalance is applied Then a new conferencing link is generated with the same provider And equivalent security settings (e.g., waiting room/lobby, passcode policy, authenticated users) are copied to the new meeting And the old join details are fully replaced atomically in the calendar event And all attendees receive an update indicating a new conferencing link is in effect And audit logs record the reason code and old/new meeting identifiers And there is no state in which recipients can access a broken link from the updated invite
Honor Provider-Specific Link Constraints
Given a Zoom scheduled meeting (non-PMI) is attached to the series When Auto Rebalance shifts the series time Then the Zoom join URL and meeting ID remain unchanged and no new meeting is created Given a Google Meet link is attached to the series When Auto Rebalance shifts the series time Then the Meet code and conferenceSolutionId remain unchanged Given a Microsoft Teams meeting is attached to the series with custom meeting options When Auto Rebalance shifts the series time Then the Teams join URL and meeting options persist unchanged
Cross-Calendar Join Info Consistency After Rebalance
Given attendees include users on Google Calendar, Outlook/Exchange (via Microsoft 365/Graph), and Apple Calendar consuming an .ics When Auto Rebalance completes and updates are delivered Then each attendee’s calendar displays the same conferencing URL, passcode, and dial-ins as the organizer’s event And no duplicate or conflicting join information appears across description, location, or conferencing fields And a single conferencing link is present in the .ics payload and renders correctly in Apple Calendar
Rollback Restores Prior Conferencing State
Given a series was rebalanced and a rollback is initiated within the supported rollback window When the rollback executes Then event times and textual fields revert to the pre-rebalance state for all instances And if the original conferencing link was valid at rebalance time, that same link is preserved after rollback And if a new link was generated due to invalidation during rebalance, that regenerated link is retained after rollback And attendees receive a single update reflecting the rollback with no broken or missing join information
Security Settings Migration on Regeneration
Given the meeting has security settings configured on the provider (e.g., waiting room/lobby enabled, passcode complexity, presenters/speakers restrictions, authenticated users required) When Auto Rebalance requires link regeneration Then the regenerated meeting inherits equivalent security settings And no setting becomes less restrictive than before And verification via provider API confirms the applied settings post-regeneration
Localized Notices & Acknowledgements
"As an ops lead, I want localized notices with quick acknowledgement options so that everyone understands the change in their own timezone and can confirm attendance promptly."
Description

Sends localized notifications to all participants with the new schedule in their local time, preferred language, and chosen channels (email, Slack/Teams). Includes a concise summary of what changed, relative time deltas, and quick RSVP/acknowledge controls. Supports delivery windows aligned to recipients’ working hours, throttling to avoid notification spam, and fallbacks for bounced or delayed messages. Updates calendar invitations and posts confirmation receipts back into the meeting thread for auditability.

Acceptance Criteria
Language and Timezone Localization of Notices
- Given a recipient with preferred language fr-FR and timezone Europe/Paris, when a series rebalance triggers a notice, then the notice renders in French and all date/times display in Europe/Paris using fr-FR locale formatting. - Given a recipient with no language preference, when a notice is sent, then the notice defaults to English (en-US) and uses the recipient's stored timezone; if none exists, UTC is used and a preference-missing event is logged. - Given a recipient with an unsupported language code, when a notice is generated, then the system falls back to the nearest supported locale or English and records the fallback locale used in telemetry. - Given recipients across multiple timezones, when the same rebalance notice is sent, then each recipient sees local times that map to the same absolute timestamp with zero drift (verified within ±1 second).
Multichannel Delivery: Email, Slack, and Teams
- Given a recipient with channels email and Slack selected, when a rebalance notice is issued within working hours, then both email and Slack messages are delivered within 2 minutes and contain equivalent content (title, old/new local times, delta, RSVP controls). - Given a recipient with Teams selected only, when a notice is sent, then exactly one Teams message is delivered and no email/Slack messages are sent. - Given channel-specific templates, when notices are generated, then links and interactive controls are functional per channel (email: actionable buttons/ICS link; Slack/Teams: interactive actions) and pass a click test with <2% template rendering error rate across supported clients. - Given per-user channel preferences updated within the last 5 minutes, when a notice is sent, then the latest preferences are honored with no stale channel deliveries.
Relative Time Delta Summary Correctness
- Given a meeting moved from 2025-10-01T09:00 to 2025-10-01T10:30 local time, when the notice is composed, then the summary includes: Was: 09:00, Now: 10:30, Change: +90m (same day). - Given a move that crosses day boundaries in the recipient's timezone, when the notice is composed, then the delta indicates day change (e.g., +30m next day or -45m previous day) and matches computed difference within ±1 minute accounting for DST. - Given DST transitions, when a series instance shifts, then the delta calculation uses absolute UTC timestamps to compute change and the displayed local times reflect correct DST offset. - Given multiple recipients in different timezones, when notices are sent, then each notice's Was/Now times differ by timezone but the numeric delta is identical across recipients.
Delivery Windows and Notification Throttling
- Given a recipient with a delivery window of 09:00–17:00 local, when a rebalance occurs at 20:00 local, then the notice is scheduled for 09:00 next business day and not delivered immediately. - Given multiple rebalances within 10 minutes for the same series, when notices are generated, then at most one notice is sent per recipient and subsequent notices are collapsed into a single consolidated update. - Given more than 3 notices queued for a recipient within 24 hours across all series, when generating notices, then additional notices are aggregated into a digest delivered at the next delivery window start with a count of collapsed changes. - Given a scheduled notice awaiting the delivery window, when the meeting start is <2 hours away, then the notice is promoted for immediate delivery and this exception is recorded in telemetry.
Bounced/Delayed Message Fallbacks
- Given an email hard bounce or a 5xx provider error, when detected, then the system retries up to 3 times with exponential backoff within 10 minutes and, if still failing, sends the notice via the recipient's next available channel (Slack or Teams) and logs the fallback. - Given a Slack/Teams delivery timeout >5 minutes, when detected, then the system retries once and, upon continued failure, sends the notice via email with the same content and marks the original attempt as failed. - Given all channels fail, when escalation completes, then the system creates an admin alert event with recipient, series, error codes, and last attempt timestamp. - Given a fallback was used, when the meeting thread receipt is posted, then it includes the original channel failure and the successful fallback channel used.
RSVP/Acknowledge Controls and State Recording
- Given a recipient clicks Yes/No/Maybe or Acknowledge in any channel, when the action is received, then the response is recorded within 60 seconds and a confirmation is shown to the user in the same channel. - Given multiple responses from the same recipient across channels, when processed, then the first response received is authoritative and subsequent responses return an idempotent confirmation showing the current recorded status. - Given a recorded RSVP, when syncing with the calendar provider, then the attendee response on the calendar event updates to match within 2 minutes without creating a duplicate event. - Given the meeting time changes again before the recipient responds, when the user attempts an old action link, then the system displays a stale-action message and provides updated controls for the latest schedule.
Calendar Invitation Update and Thread Confirmation
- Given a series time shift is applied, when notices are sent, then the corresponding calendar invitations update for all participants within 5 minutes, preserving the original conferencing link and meeting ID. - Given an update to the calendar invitation, when delivered, then the organizer and attendees see a single updated event instance per occurrence rather than duplicates in their calendars. - Given all notices for a rebalance are dispatched, when posting to the meeting thread (Slack/Teams/email thread), then a confirmation receipt is posted containing timestamp, message IDs per channel, delivery counts (sent/succeeded/failed), and any fallbacks used. - Given audit requirements, when a receipt is posted, then it is retained and retrievable for at least 90 days with immutable event metadata.
Equity Rules Preservation & Rotation Balance
"As a distributed team lead, I want the rebalance to keep fairness intact so that inconvenient time slots are shared equitably over time."
Description

Recalculates and enforces TimeMeld’s equity model during rebalance so that the shift does not disproportionately burden one region or role. Adjusts the shared equity scoreboard, enforces configured fairness thresholds, and updates future rotation ownership accordingly. Provides a pre-commit impact preview (credits/debits by cohort), prevents shifts that violate policies unless explicitly overridden, and logs changes to maintain transparency with the team.

Acceptance Criteria
Pre-Commit Equity Impact Preview
Given a proposed series time shift and an active equity policy configuration When the user opens the Impact Preview Then the preview displays, for each cohort (e.g., region, role), the projected credit/debit totals for the next 12 weeks And shows the delta versus the current plan per cohort and per participant And the sum of all credits/debits across cohorts equals zero within ±1 credit And any cohort projected to exceed a configured fairness threshold is highlighted with the specific metric and threshold value And the preview renders within 2 seconds for series with ≤ 52 occurrences And the preview includes the top 5 changes to rotation ownership that would result from the apply
Fairness Threshold Enforcement and Override
Given a proposed shift that would cause any cohort’s projected burden to exceed its configured threshold for the evaluation window When the user selects Apply Rebalance Then the system blocks the action and displays a descriptive violation message listing offending cohorts, metrics, and threshold values And the Apply control is replaced by an Override with Reason control only for users with OverrideEquity permission And entering a non-empty reason of at least 10 characters enables the Override action And on override, the rebalance proceeds and an audit entry is stored capturing the reason and permissioned user And for users without permission, no override control is displayed and the action remains blocked
Equity Scoreboard and Rotation Update on Apply
Given a successful rebalance apply When the operation completes Then the equity scoreboard updates with new credit/debit totals per participant and per cohort And future rotation ownership for the next N meetings (configurable; default 8) is recalculated and persisted And no participant is assigned more than the configured maximum consecutive inconvenient slots And updates are visible in both UI and API within 5 seconds of apply completion And meeting records reflect updated ownership annotations for the affected occurrences
Comprehensive Audit Logging and Transparency
Given any rebalance attempt (blocked, applied, or overridden) When the event occurs Then an immutable audit record is created capturing: user, timestamp (UTC), proposed shift, policy version, pre- and post- credit/debit per cohort, rotation changes, decision (Blocked/Applied/Overridden), and reason (if override) And the record is queryable via Audit API and UI within 10 seconds of the event And audit records can be exported as CSV including all captured fields And audit entries include a correlation ID linking preview → decision → apply/rollback events for traceability
Rollback Restores Equity State
Given a previously applied rebalance When a user with ManageRebalance permission initiates Rollback within 30 days of the apply Then the equity scoreboard, cohort aggregates, and rotation ownership are restored exactly to the pre-apply state And all credits/debits introduced by the apply are reversed without duplication And a rollback audit entry is created linking to the original apply via correlation ID And no participant retains any net equity change after rollback completes And the restore completes within 10 seconds for series with ≤ 52 occurrences
DST and Local-Time Ergonomics Compliance
Given a series rebalance that spans a Daylight Saving Time transition for any participant locale When impact is calculated and the rebalance is applied Then early/late burden scoring uses each participant’s local wall-clock time per occurrence And preview and post-apply credit/debit allocations reflect DST transitions correctly (no artificial gains/losses from clock shifts) And fairness thresholds are enforced against ergonomic windows defined in policy for each locale And no participant exceeds the configured monthly quota of inconvenient slots due to the DST transition
One-click Rollback with Audit Trail
"As a product manager, I want a one-click rollback if priorities change so that I can safely return to the prior schedule without causing confusion."
Description

Provides an immediate undo action that reverts the series to its previous schedule baseline, restoring calendar events, conferencing details, notifications, and equity ledger state. Supports safe rollback windows, conflict-aware reversal (with prompts if new conflicts emerged), and idempotent operations to avoid duplication. Captures who initiated the rollback, reason, timestamps, and diffs for compliance and postmortems.

Acceptance Criteria
Immediate Undo Restores Previous Series Baseline
Given a rebalanced recurring series with a captured pre-rebalance snapshot When the owner clicks "Rollback" within the allowed window Then all future instances are restored to the exact pre-rebalance start/end times, participants, recurrence pattern, titles, and descriptions And conferencing details are restored to the pre-rebalance values for each instance And the equity ledger state is restored to the pre-rebalance values And no duplicate or orphaned calendar events remain in any attendee calendar And the rollback completes within 10 seconds for series with ≤ 50 future instances or a progress indicator remains visible until completion And the UI displays a success message summarizing the number of instances restored
Safe Rollback Window Enforcement and Partial Revert
Given a configured rollback window from the last Auto Rebalance When the current time is outside the rollback window Then the "Rollback" action is disabled with a tooltip explaining the expiry and window policy When inside the window and some instances have started or completed Then only future instances are reverted and past instances remain unchanged And a confirmation modal lists the count of instances that will be reverted and the count excluded due to being in the past And the action requires explicit confirmation before execution
Conflict-Aware Reversal with User Prompt
Given TimeMeld detects new conflicts at the pre-rebalance times (created after the rebalance) When the user initiates "Rollback" Then a preflight scan identifies conflicted instances and attendees and displays a summary modal with counts and names And the user can choose to proceed, cancel, or exclude conflicted instances from rollback When the user proceeds Then rollback executes and conflicted instances are restored and marked with a conflict flag in TimeMeld And if the user cancels Then no changes are made
Idempotent and Concurrent Rollback Protection
Given a rollback for the same series and rebalance has already completed When the rollback is triggered again using the same operation context Then the system performs a no-op and returns a deduplicated response And no additional events, notifications, or audit entries are created When two rollback requests occur concurrently Then only one executes and others return a reference to the completed operation And the final series state checksum matches the pre-rebalance snapshot checksum
Audit Trail Capture and Diff
Given a rollback is executed When the audit log is queried by series ID Then it contains an immutable entry with initiator user ID, role, IP, timestamps (start/end), reason text (required), operation ID, and outcome (success/failure) And the entry includes diffs of schedule (instance datetime changes), equity ledger deltas, notification dispatch results, and counts of events restored/created/deleted And the audit entry is exportable (JSON and CSV) and viewable in the admin UI And if the rollback fails Then the audit entry includes error codes and any partial effects recorded
Localized Rollback Notifications
Given attendees have locale and time zone preferences When a rollback completes Then each attendee receives a localized notification in their preferred language with restored date/time in their local time zone And only one notification per instance per attendee is sent And the conferencing link in each notification matches the restored instance details And notification delivery status is recorded and linked in the rollback audit entry
Rebalance Permissions & Safeguards
"As a workspace admin, I want controls and guardrails on who can trigger a rebalance so that large-scale schedule changes are safe and intentional."
Description

Introduces granular permissions and safeguards around rebalancing, including role-based access control, optional approval workflows for org-wide series, confirmation gates (summary of impacts, affected attendees, equity changes), and processing locks to prevent concurrent edits. Adds observability with progress indicators, error surfacing, and recovery paths for partial failures, plus feature flags to roll out the capability incrementally.

Acceptance Criteria
RBAC: Only authorized roles can initiate Auto Rebalance
Given a user without the Rebalance:Apply permission, When they attempt to rebalance a series via UI or API, Then the action is blocked, the UI control is hidden or disabled, the API responds 403, and no series changes occur. Given a user with Rebalance:Apply permission scoped to specific series, When they attempt to rebalance a series outside their scope, Then the action is blocked as above. Given a user with Rebalance:Apply permission for the target series, When they open the series, Then the Auto Rebalance control is visible and enabled. Given any rebalance attempt, When executed, Then an audit log entry is created capturing initiator ID, timestamp, series ID, scope, pre/post equity metrics, and outcome (success/failure).
Approval workflow required for org-wide or approval-gated series
Given a series that is org-wide or configured to require approval, When a non-exempt user initiates Auto Rebalance, Then an approval request is created, the job status is set to Pending Approval, and execution is blocked until approval. Given a designated approver receives the request, When they approve, Then the rebalance transitions to Executing and the requester is notified. Given the approver rejects the request, Then no changes occur to the series, the status becomes Rejected, and the requester is notified. Given an approval request reaches its configured expiration without action, Then it auto-expires, no changes occur, and both requester and approver are notified.
Confirmation gate summarizes impacts before execution
Given an eligible user initiates Auto Rebalance, When the confirmation gate opens, Then it displays: number of occurrences affected, date range, per-timezone time shifts, impacted attendees, conferencing link retention status, and projected equity score changes for the rotation. Given required approval is detected, When showing the confirmation gate, Then the gate indicates that approval is required and who can approve. Given the user clicks Confirm, Then the rebalance starts; Given the user cancels or closes the gate, Then no changes occur and no notifications are sent. Given stale data or permission changes are detected at confirmation, When the user clicks Confirm, Then the gate re-validates and blocks execution with a clear error and next steps.
Processing locks prevent concurrent edits and rebalances
Given an Auto Rebalance is executing for a series, When any user attempts to edit the same series or start another rebalance, Then the API responds 423 Locked and the UI shows "This series is being updated" with the active job ID. Given a processing lock is set for a series, When the job completes successfully, Then the lock is released; When the job fails, Then the lock is released and failure details are recorded for recovery. Given repeated requests with the same idempotency key, When submitted during or after execution, Then only one execution occurs and subsequent requests return the original outcome without side effects. Given overlapping rebalances are attempted across series that share the same conferencing resource, When a conflict is detected, Then only the earliest lock holder proceeds and others receive a clear locked/conflict response.
Progress indicators, error surfacing, and recovery paths for partial failures
Given a rebalance has started, When the user views the job drawer, Then a step-wise progress indicator shows current phase (Validating, Scheduling, Updating Calendars, Notifying, Equity Update, Done) and percentage complete. Given a partial failure occurs (e.g., some occurrences fail to update), When viewing the job details, Then per-occurrence error messages and affected attendees are listed with actionable guidance. Given partial failures exist, When the user selects "Retry failed only", Then only failed operations are retried with idempotency and updated outcomes are reflected in the job details. Given any changes were applied by the rebalance, When the user initiates "Rollback all changes" within the retention window, Then all changes made by the job are reversed, conferencing links persist, equity is restored, and rollback notifications are sent to affected attendees.
Feature flag gates incremental rollout of Auto Rebalance
Given the Auto Rebalance feature flag is disabled for an org/workspace, When users access a series, Then Auto Rebalance controls are not visible and API endpoints return 404 or 403 with no side effects. Given the feature flag is enabled for an allowlisted cohort, When eligible users access a series, Then Auto Rebalance controls are visible and functional; ineligible users cannot access them. Given the feature flag state changes, When a user refreshes the app or makes a new API call, Then the new state is respected without deployment or app update. Given analytics are enabled, When the feature flag toggles, Then exposure and usage events are logged with org/workspace and user identifiers for auditability.

Cohort Lenses

Slice drift by role, team, seniority, meeting type, or internal/external cohorts to pinpoint who’s slipping and why. Target interventions where they matter most instead of blanket changes that disrupt everyone.

Requirements

Cohort Definition Engine
"As a product ops lead, I want to create dynamic cohorts based on roles, teams, seniority, and meeting types so that I can analyze scheduling drift for the right groups without manual list maintenance."
Description

Provides a rules-based builder to define cohorts using user and meeting attributes (role, team, seniority band, timezone, location, meeting type, internal vs external, organizer/attendee, product area). Supports inclusion/exclusion lists, boolean logic, dynamic membership, and custom tags. Cohorts auto-refresh as attributes change and maintain version history for reproducibility. Validates each cohort against data availability and minimum size thresholds. Exposes cohort identifiers for reuse across analytics, recommendations, alerts, and APIs.

Acceptance Criteria
Boolean Rule-Based Cohort Creation (User and Meeting Attributes)
Given a user with cohort-creation permissions And the following attributes are available for filtering: role, team, seniority band, timezone, location, meeting type, internal/external, organizer/attendee, product area When the user defines a cohort using AND/OR/NOT with parentheses across these attributes And saves the definition with a cohort name and description Then the system validates the rule syntax and returns clear, actionable errors for any invalid expression And the cohort is created with a unique cohort_id and persisted definition And the initial member list is computed and the member count matches the evaluation of the rule And operator precedence and parentheses are respected during evaluation
Dynamic Membership Auto-Refresh on Attribute Changes
Given a cohort defined by attribute-based rules And a member’s underlying attribute (e.g., role, team, timezone) changes When the attribute change event is ingested Then the cohort membership is recalculated and updated within the next refresh cycle (<= 10 minutes) And the member is added or removed accordingly with a timestamped audit entry And no manual rebuild is required by users
Inclusion and Exclusion Lists Precedence
Given a cohort with a base rule And an inclusion list and an exclusion list are specified by user identifiers When membership is computed Then users on the exclusion list are not included even if they match the base rule And users on the inclusion list are included even if they do not match the base rule And if a user appears on both lists, exclusion takes precedence And each member’s record includes a reason code (rule, inclusion_override, exclusion_override)
Minimum Size and Data Availability Validation
Given configured thresholds for minimum cohort size and attribute coverage When a user attempts to save a cohort definition Then the system estimates member count for the current data set And if the estimate is below the configured minimum size threshold, the save is blocked with a clear message and guidance to broaden criteria And if any required attribute coverage is below the configured coverage threshold, a non-blocking warning is shown identifying low-coverage fields And the user can proceed past warnings but not blocking errors
Version History and Reproducibility
Given an existing cohort When a user edits the cohort’s rule or metadata and saves changes Then a new immutable version is created with version number, editor, timestamp, and a diff of rule changes And the prior versions remain accessible and cannot be altered And users can retrieve any version’s definition and recompute membership as of that version’s timestamp for reproducibility And reverting to a prior version creates a new version entry rather than overwriting history
Cohort Identifier Exposure Across Analytics, Recommendations, Alerts, and APIs
Given a created cohort with versions When accessing analytics, recommendation engines, alert configurations, and the public API Then the cohort_id and version_id are available as selectable filters/parameters And API endpoints return consistent membership for the specified version_id or the latest version And access controls are enforced so only authorized users can query or use the cohort identifiers And identifiers are stable and unique within the workspace
Custom Tags and Catalog Searchability
Given a cohort When a user adds, edits, or removes custom tags on the cohort Then tags are saved and immediately associated with the cohort metadata And searching or filtering the cohort catalog by tag or keyword returns the cohort And tags are included in cohort metadata responses from the API
Directory & HRIS Attribute Sync
"As an IT admin, I want TimeMeld to automatically sync user attributes from our directory and HRIS so that cohorts stay accurate without manual updates."
Description

Integrates with Google Workspace, Okta/Azure AD, Slack, and HRIS systems (e.g., Rippling, BambooHR) to ingest user attributes (role, team, manager, seniority, location/timezone, employment status) and map them to calendar identities. Implements secure OAuth or key-based connections, scheduled full sync with near‑real‑time delta updates, schema mapping, and conflict resolution. Provides data lineage, backfill capability, retry logic, and alerting on schema drift. Normalizes timezones and enforces attribute validation to ensure accurate cohort membership.

Acceptance Criteria
Provider Connections via OAuth/API Key
Given an org admin initiates a connection to a supported provider (Google Workspace, Okta, Azure AD, Slack, Rippling, BambooHR), When the flow is completed, Then the system establishes the connection using OAuth 2.0 where available or API key otherwise and records connection status as Active. Given a connection is established, When credentials are stored, Then tokens/keys are encrypted using KMS, are not retrievable in plaintext, and are scoped to least-privilege permissions. Given an Active connection, When the admin views Integrations, Then the provider displays health=OK, last successful sync timestamp, and credential expiry/rotation info where applicable. Given a credential is revoked or expired, When a sync or health check runs, Then the job fails fast, health is set to Needs Attention, and a Reconnect action with a clear error is presented to the admin.
Scheduled Full Sync and Canonical Mapping
Given at least one Active connection, When the scheduled full sync window occurs (configurable daily, default 02:00 UTC), Then the system ingests all active users and maps fields to the canonical schema (role, team, manager, seniority, location, timezone, employment status, primary email, aliases, external id). Given provider field names or types differ, When mapping runs, Then values are transformed to the canonical schema, the mapping version is recorded, and records failing type/format validation are rejected with structured errors. Given the full sync completes, When audit logs are queried, Then completion event, run id, counts (ingested/updated/skipped/errored), and duration are available.
Near-Real-Time Delta Sync
Given a supported provider emits change events, When a user attribute changes, Then the change is reflected in TimeMeld within 5 minutes at P95 and within 15 minutes maximum. Given a provider without webhooks, When polling runs, Then incremental changes since the last cursor are detected and applied at least every 5 minutes. Given delta updates are applied, When concurrent updates occur, Then only changed fields are updated, each change is versioned (source, timestamp, run id), and older values do not overwrite newer ones.
Identity Resolution to Calendar Accounts
Given an ingested user record, When identity resolution runs, Then the user is matched to a calendar identity by primary email; if not found, verified aliases are attempted; otherwise the record is queued with a missing-identity error. Given multiple candidate matches exist, When resolution runs, Then selection follows deterministic precedence (exact primary email > verified alias > HRIS email) and the decision is logged with a confidence score. Given a successful match, When cohort calculations run, Then the user appears once under the correct person with a unified profile and no duplicate calendar identities.
Attribute Validation and Timezone Normalization
Given ingested attributes, When validation runs, Then required fields (role, team, manager, employment status, and either timezone or location) must be present; missing/invalid records are flagged and excluded from cohorts until corrected. Given timezone inputs in IANA, Windows, or UTC offset formats, When normalization runs, Then values are converted to IANA timezones, stored canonically, and validated against the current tzdata. Given location is present but timezone is missing, When normalization runs, Then timezone is inferred from location with an explicit inference flag; ambiguous inferences are queued for review. Given attributes pass validation, When Cohort Lenses are viewed, Then users are included/excluded deterministically based on normalized attributes for identical inputs.
Cross-Source Conflict Resolution
Given conflicting attribute values from multiple sources for the same user, When consolidation runs, Then the configured source priority (e.g., HRIS > Directory > Slack) is applied and the winning value is stored with its source tag. Given two updates of the same attribute arrive from the same source, When timestamps differ, Then the newest update wins; if timestamps are equal, Then the operation is idempotent and no flip-flop occurs. Given a conflict decision is made, When audit history is viewed, Then losing values, sources, and timestamps are visible and a manual override with reason can be applied that persists until revoked.
Resilience, Backfill, Schema Drift Alerting, and Lineage
Given transient provider errors or rate limits, When sync jobs run, Then exponential backoff with jitter is applied with up to 5 retries per batch before marking the job partially failed and queuing a retry. Given an admin triggers a backfill by date range or run id, When the job executes, Then ingestion and mapping are replayed deterministically without duplicate records and lineage is updated. Given provider schema changes (add/remove/rename/type), When detection occurs, Then an alert is sent to configured channels (email and Slack) within 10 minutes, the affected mapping is marked Degraded, and full syncs fail safe without corrupting data. Given any stored attribute, When lineage is queried, Then the system returns source system, source field, source record id, last updated timestamp, mapping version, and sync run id.
Drift & Equity Metrics Per Cohort
"As a remote team lead, I want clear metrics for each cohort so that I can see who is slipping and quantify after-hours burden and equity issues."
Description

Computes cohort-scoped KPIs including scheduling drift versus ergonomic windows, after-hours burden index, reschedule/cancellation rate, attendance and punctuality, meeting ownership equity, lead-time compliance, and timezone pain distribution. Supports daily aggregation, rolling trends, percentile views, and comparisons to org baseline. Implements metric definitions, incremental ETL pipelines, backfills, and a performant query layer with caching to power the Lens UI, alerts, exports, and recommendations.

Acceptance Criteria
Daily Cohort KPIs with Percentiles, Rolling Trends, and Baseline Comparison
Given an org with events tagged by role, team, seniority, meeting_type, internal_external, and participant timezones over the selected date range When the daily aggregation job completes for day D Then for every cohort and day in range the system produces these KPIs: scheduling_drift_minutes_avg, ergonomic_window_hit_rate, after_hours_burden_index, reschedule_rate, cancel_rate, attendance_rate, punctuality_p95_minutes, ownership_equity_index, lead_time_compliance_rate, timezone_pain_score And p50, p90, p95 percentiles and 7-day and 28-day rolling trend values are available for each KPI And each KPI includes delta_absolute and delta_percent versus the org baseline for the same period And null days are represented as null (not 0) and excluded from rate/percentile denominators And applying any combination of cohort filters recomputes totals correctly and returns results within ±0.5% of validated fixtures And values are rounded: rates to 1 decimal percent, minutes to 1 decimal, indices to 3 decimals
Incremental ETL, Late-Arriving Data Handling, and Backfill
Given new events and updates arrive continuously with event_id and updated_at timestamps When the incremental pipeline runs every 15 minutes Then end-to-end latency from ingestion to queryable metrics is ≤ 10 minutes at P95 And late-arriving or updated records within a 7-day lookback are reprocessed and affected aggregates are recomputed And processing is idempotent with exactly-once semantics ensured by primary key (event_id, updated_at) deduplication And each run records an audit log with run_id, watermark_start, watermark_end, input_count, output_count, error_count, duration And a backfill command can rebuild 365 days of history at ≥ 3 million events/hour and produces identical outputs to incremental runs (checksum match) And the job can be safely retried; partial outputs are not visible until commit
Query Layer Performance and Smart Caching for Lens UI
Given a dataset with ≥ 50k meetings/day, 200 cohorts, and 30 concurrent UI users When the Lens UI requests cohort metrics with filters, percentiles, trends, and baseline comparison Then cold query latency is ≤ 1.5 s at P95 and ≤ 600 ms at P50 And cached requests return in ≤ 200 ms at P95 with a cache hit-rate ≥ 80% under typical navigation And cache TTL is 5 minutes and keys are selectively invalidated upon successful ETL completion for affected cohort-day partitions only And results include an as_of timestamp and are consistent with export and alert endpoints (byte-for-byte equality of aggregates for identical parameters)
Timezone-Weighted Drift and After-Hours Burden Calculation Accuracy
Given ergonomic windows configured per cohort (weekday/time spans, local participant time) and a seed dataset with known expected outputs When drift and after-hours metrics are computed Then scheduling_drift_minutes_avg and ergonomic_window_hit_rate reflect participant-weighted local times with correct handling of DST transitions and cross-midnight meetings And after_hours_burden_index counts minutes outside ergonomic windows and weights by participant count and severity tiers (mild/moderate/severe) And outputs match expected fixtures within ±0.5% (rates) or ±1 minute (time metrics)
Meeting Ownership Equity Index Computation
Given organizer identity and cohort membership over the period When the ownership_equity_index is computed Then it is calculated as 1 − Gini(meetings_owned_per_member) and constrained to [0,1] And edge cases are handled: single-member cohort -> index = 1.000; no meetings -> null And metric is stable across re-ingests (identical input -> identical output) and matches fixture values within ±0.005
Cohort Metrics Exports and Alert Integrations
Given a selected cohort, KPI set, and date range When a user exports metrics Then CSV and JSON exports are available within 10 seconds, include column headers/field names, UTC timestamps, and match UI values exactly And when alert rules are configured (threshold, direction, lookback), alerts trigger within 15 minutes of breach with payload including org_id, cohort_id, kpi, threshold, actual, period, link_to_lens And alerts support Slack webhook, email, and generic HTTP webhook with retry (exponential backoff up to 6 hours)
Data Governance, Access Control, and Anonymization for Cohort Lenses
Given a user authenticated to an org When querying cohort metrics Then only data scoped to the user’s org is returned (row-level isolation) And cohorts smaller than 5 unique members are suppressed or aggregated to "Other" and exports redact such rows And no PII (names, emails) appears in metrics, exports, or alerts; only hashed IDs where necessary And all access to metrics, exports, and alerts is logged with user_id, org_id, action, parameters, and timestamp
Lens Explorer UI
"As a product manager, I want an interactive lens to slice metrics by role, team, or meeting type so that I can quickly pinpoint problem areas and share findings with stakeholders."
Description

Delivers an interactive analytics surface to filter by cohort facets, combine filters with AND/OR logic, select date ranges, and pivot by metric. Presents responsive charts and tables with drill-down to meeting lists while enforcing privacy constraints. Supports saved views, shareable deep links, CSV export, annotations, metric tooltips/definitions, empty/loading states, and keyboard navigation for accessibility.

Acceptance Criteria
Filter by Cohort Facets with AND/OR Logic
Given the Lens Explorer is open with default data When the user applies filters Role = Engineer AND Team = Growth AND Meeting Type = Standup Then the results include only meetings where at least one participant satisfies all selected conditions And the filter chip bar displays the human-readable expression exactly as applied When the user switches the operator to OR between Role and Team Then the results include meetings matching either condition and the count updates accordingly When the user groups conditions as Role = Engineer AND (Team = Growth OR Team = Product) Then the evaluation respects the grouping and produces the expected set And applying, removing, or reordering any single filter updates the results within 2s p50 and 4s p95 on datasets up to 100k meetings And clearing all filters resets the view to the default state
Date Range Selection and Timezone Handling
Given the user’s profile timezone is set When the user selects a relative range (Last 7, 30, 90 days, Quarter-to-date) Then meetings are included based on meeting start time occurring within the selected range in the user’s timezone, with the end date inclusive to 23:59:59 When the user selects a custom date range (Start, End) Then the Start and End are inclusive and the range label displays with localized dates and timezone (e.g., Jan 01–Jan 31, 2025, GMT-5) And the selected range persists while navigating within Lens Explorer and is reflected in saved views and deep links And changing the date range updates visualizations and tables within 2s p50 and 4s p95
Metric Pivot with Responsive Visualizations, Tooltips, and Annotations
Given a metric is selected (e.g., Attendance Rate) and a pivot dimension (e.g., Role) When the user changes the metric or pivot dimension Then both the chart and the table update consistently to show the same aggregated values with identical segment ordering and totals And each data point tooltip displays the metric definition, formula, and calculation window, accessible on hover and keyboard focus When the viewport width is ≥1024px Then the chart and table render without horizontal scroll and labels do not overlap When the viewport width is ≤768px Then the layout stacks vertically, legends collapse to a dropdown, and all content remains readable and operable When the user adds an annotation to a specific date or segment Then an annotation marker appears on the chart, the note is visible on hover/focus, and the annotation persists on reload and share links And users can edit or delete their own annotations; edits are versioned and reflected immediately across chart and table
Drill-Down to Meeting List from Visualizations
Given the user views a chart or table segmented by a cohort facet When the user clicks a segment (e.g., Role = Engineer) Then a meeting list opens filtered by the clicked segment plus all currently applied filters and date range And the list shows sortable columns: Start Time, Title, Organizer, Attendees (#), Meeting Type, Internal/External And the default sort is Start Time descending, with stable pagination (page size 25) And the meeting count matches the aggregate number shown on the originating segment When the user navigates back Then the Lens Explorer returns to the prior scroll position and preserves all filters and selections
Saved Views and Shareable Deep Links
Given a set of filters, date range, metric, pivot, and visualization options is configured When the user saves the view with a unique name Then it appears in the Saved Views menu and loads the exact configuration on selection And renaming or deleting a saved view updates the menu immediately and is reflected for the owner on refresh When the user copies a share link Then opening the link reconstructs the exact state (filters, logic, date range, metric, pivot, sort, annotations visibility) for authorized users And unauthorized users see a 403 error page without leaking configuration details And unsaved changes relative to a saved view show an “Edited” indicator until re-saved
Privacy Constraints and CSV Export Redaction
Given privacy is enforced with an aggregation threshold of 5 unique meetings AND 5 unique participants per segment When a segment is below threshold Then the UI replaces the metric with “Insufficient data” and excludes that segment from CSV export And deep links and saved views cannot bypass the threshold; the same redaction applies on load When the user exports CSV Then the file contains only rows permitted by privacy rules and exactly reflects the current filters, date range, metric, and pivot And PII fields (meeting title, attendee emails) are redacted for users without View PII permission and marked as “Redacted” in the CSV And exports complete within 10s p95 for up to 50k rows, with a progress indicator for long-running exports And the CSV filename includes workspace, view name (if any), metric, and date range
Accessibility, Keyboard Navigation, and Loading/Empty States
Given a keyboard-only user When navigating the Lens Explorer Then all controls (filters, operator toggles, date picker, metric selector, chart segments, table headers) are reachable in a logical tab order with visible focus And Space/Enter activate controls, Arrow keys navigate chart segments and table rows, and Esc closes popovers and menus And all interactive elements meet WCAG 2.1 AA contrast requirements When data is loading Then skeleton placeholders and an aria-live polite status announce loading within 200ms, with no layout shift exceeding CLS 0.1 When filters produce no results Then an empty state appears with the message “No meetings found for the selected criteria” and a Clear Filters action; Export and Save View are disabled until data is present
Targeted Recommendations & Nudges
"As an engineering manager, I want actionable recommendations per cohort so that I can fix issues without imposing blanket changes on everyone."
Description

Generates cohort-specific interventions when metrics degrade, such as rebalancing meeting ownership rotation, shifting recurring slots to fairer windows, tightening ergonomic windows, or proposing async alternatives. Provides rationale, expected impact, and one-click application or templated Slack/email nudges to meeting owners. Captures outcomes to learn effectiveness and feeds experimentation tags back into the metrics layer.

Acceptance Criteria
Automatic Cohort Degradation Detection & Recommendation Generation
- Given a user has selected a cohort lens (e.g., Role=Engineer, Team=Payments) and the hourly metrics job has completed, when a monitored metric for that cohort breaches its configured threshold over the trailing 14-day window (e.g., attendance rate < 85% or ownership balance Gini > 0.3), then a targeted recommendation is created and visible in the Cohort Lenses → Recommendations panel within 5 minutes. - Given multiple breaches occur for the same cohort within a 1-hour window, when recommendations are generated, then they are deduplicated and consolidated by issue type with a severity score and timestamp. - Given a recommendation is created, when viewed, then it includes: cohort identifier, degraded metric, threshold and observed value, proposed intervention type (one of: rebalance rotation, shift recurring slot, tighten ergonomic window, propose async alternative), rationale summary, expected impact range, and one-click actions (Apply, Send Nudge). - Given metrics do not breach thresholds for a cohort, when the job completes, then no new recommendation is created for that cohort. - Given a recommendation is generated, when audited, then an entry exists in the audit log capturing generator version, inputs, and time.
One-Click Apply: Rebalance Meeting Ownership Rotation
- Given a recommendation to rebalance ownership rotation for a defined meeting series and cohort, when the user clicks Apply, then the system recalculates rotation weights to target a fairness index ≤ 0.1 Gini (±0.02) effective from the next scheduled occurrence. - Given Apply is initiated, when conflicts are detected for required owners, then the system proposes the nearest feasible rotation that meets fairness within ±0.02 tolerance or blocks with a clear error explaining the constraint. - Given Apply succeeds, then calendar ownership assignments are updated, affected owners are notified, an audit record is written, and the UI displays a success state within 30 seconds. - Given Apply fails at any step, then all changes are rolled back, an error with a reason code is shown, and no notifications are sent. - Given Apply succeeds, when viewed later, then the recommendation shows status Applied with timestamp and a link to the changed series.
One-Click Apply: Shift Recurring Slots to Fair Ergonomic Windows
- Given a recommendation to shift a recurring meeting for a cohort spanning multiple time zones, when the user clicks Apply, then the system reschedules the series into a window that meets the cohort’s ergonomic constraints (e.g., local time 09:00–17:00 for ≥90% of required participants) starting next occurrence. - Given rescheduling would create hard conflicts for any required participant, when computing the new slot, then the system selects the next-best slot with ≤1 hard conflict or presents a blocking error if none exist within the next 4 weeks. - Given Apply succeeds, then the series is updated in the calendar provider, all invitees receive updated invites with a reason note, and the UI shows success within 30 seconds. - Given Apply is previewed, when the user opens the preview, then they see old vs new time, affected time zones, conflict count, and predicted impact. - Given Apply is undone within 10 minutes, when the user clicks Undo, then the series reverts to the prior time and participants are notified of the revert.
Templated Slack/Email Nudges to Meeting Owners
- Given a recommendation exists, when the user selects Send Nudge → Slack, then a prefilled message template opens with cohort, issue, proposed action, and expected impact; the user can edit content before sending. - Given a nudge is sent via Slack, then delivery status (sent, failed) is captured, the message includes deep links (Apply, Preview), and recipients are the meeting owners for the affected series. - Given the user selects Send Nudge → Email, then an email template with the same fields is available, supports CC to team leads, and records delivery status. - Given a nudge is sent, when viewing the recommendation, then the UI shows Nudge Sent with channel, timestamp, and recipients, and tracks link clicks. - Given delivery fails, then a retry option is offered with surfaced error details (e.g., missing Slack mapping, SMTP error).
Rationale, Expected Impact, and Confidence Display
- Given a recommendation is generated, when the user opens its detail, then the rationale includes: degraded metric name, observed value vs threshold, cohort definition, and trailing window used. - Given expected impact is computed, then it is displayed as absolute and relative change with a 80% confidence interval and an indication of data freshness (e.g., last updated timestamp). - Given expected impact cannot be computed due to insufficient data, then the UI displays a clear explanation and disables Apply with a tooltip indicating minimum data requirements. - Given a user reviews multiple recommendations, then each shows a comparable severity score (0–100) and confidence badge (Low/Med/High) derived from sample size and variance.
Outcome Capture and Learning Feedback into Metrics Layer
- Given a recommendation is Applied or a Nudge is sent, then an outcome tracker is created with a unique ID, capturing affected series/cohort, action type, and start of measurement window. - Given the measurement window elapses (default 14 days) or sufficient sample size is reached, when metrics recompute, then the system records observed impact on the targeted metric and labels the outcome as Improved/No Change/Worsened with effect size. - Given outcomes are recorded, when generating future recommendations for the same cohort/meeting type, then the system uses prior outcomes to adjust expected impact and confidence (e.g., downweight ineffective interventions). - Given outcomes exist, then the Cohort Lenses view supports filtering and sorting by intervention type and outcome label. - Given no measurable outcome is available by end of window, then the system marks the outcome Inconclusive and surfaces a prompt to extend or close.
Experimentation Tags Propagation and Attribution
- Given a recommendation is Applied or a Nudge is sent, then an experimentation tag (experiment_id, variant, cohort_id) is attached to the affected meetings and stored in the events stream within 1 minute. - Given tags are attached, when the metrics pipeline runs, then events with experiment tags are attributed in metric aggregations and exposed as filters in the Cohort Lenses UI. - Given a recommendation is rolled back, then its experiment tag is closed (end timestamp set) and no further events are attributed after rollback. - Given experiment tags exist, when the user exports data, then tags are included in the export schema for downstream analysis. - Given conflicting tags would overlap for the same series and metric, then the system prevents Apply and explains the conflict requiring resolution.
Alerts & Subscriptions
"As an operations leader, I want to subscribe to alerts for specific cohorts so that I’m notified when drift or attendance worsens and can act promptly."
Description

Enables threshold- and trend-based alerts on cohort metrics (e.g., after-hours index > target for 2 consecutive weeks), with delivery via Slack and email. Supports per-cohort subscriptions, weekly digests, noise controls (hysteresis, snooze, business hours), and deep links to the triggering Lens view. Respects privacy rules and minimum cohort sizes.

Acceptance Criteria
Immediate Threshold Alert - Slack and Email Delivery
Given a cohort has an alert rule with metric threshold T and immediate delivery enabled And at least one subscriber has Slack and/or email selected for this cohort And the last evaluated period P-1 was at or below T When the new period P value V exceeds T Then an alert is sent within 5 minutes to each subscriber via their selected channels And the notification includes cohort name, metric name, period label, V, T, and a deep link to the Lens And no duplicate alert for the same rule is sent within 24 hours unless the metric returns to at or below T and breaches again
Trend-Based Alert (Consecutive Periods) with Hysteresis
Given an alert rule configured as "metric > T for N consecutive periods" with hysteresis M periods (default 1) And the last period did not meet the N-consecutive condition When the latest N periods all exceed T Then an alert is sent once And no new alert is sent until the metric has been at or below T for M consecutive periods and then again exceeds the rule for N consecutive periods And the notification lists the last N period values and period labels
Per-Cohort Subscription Management and Preference Enforcement
Given a user with view access to a cohort Lens When the user subscribes to alerts for that cohort and selects channels, alert types, and frequency Then the subscription is persisted and used for routing subsequent notifications When the user unsubscribes or changes preferences Then changes take effect within 5 minutes and are reflected in subsequent notifications And subscription attempts without access are rejected with 403 and no subscription is created And a confirmation is shown in-app and via a confirmation message on the chosen channel(s)
Weekly Digest Aggregation and Delivery
Given a user has weekly digest enabled and a digest delivery window set (weekday/time, timezone) When the digest job runs within the window Then a single digest is sent per channel summarizing alerts for the last 7 days that the user is subscribed to and that have not been delivered in a digest And items previously delivered immediately are excluded if the user's preference "exclude duplicates" is true (default), otherwise included once And each item includes cohort, metric, severity rank, and a deep link to the Lens And delivery completes within the window and retries up to 3 times on transient failures
Noise Controls - Business Hours and Snooze
Given organization or user business hours are configured When an alert triggers outside business hours and is not marked urgent Then it is queued and delivered at the next business window start When a user snoozes a cohort or alert rule for duration D Then no notifications for that cohort/rule are delivered to that user during D via any channel and they are excluded from the user's digest And snooze expiration automatically resumes delivery without re-sending queued non-urgent alerts
Privacy Compliance and Minimum Cohort Size
Given a minimum cohort size K and privacy rules are configured When a cohort has fewer than K members during evaluation Then no alert is generated or delivered; the event is logged as "redacted due to privacy" And any deep link resolves to a safe, redacted Lens view or access-denied page without exposing member-level details And notifications never contain PII; only aggregate metrics and cohort labels visible to the recipient's permissions are included
Deep Link Resolution and Context Persistence
Given an alert includes a signed deep link with cohort, metric, time window, and filters When a recipient opens the link Then the Lens loads with the exact cohort, metric, time window, and filters that triggered the alert And if the cohort or metric no longer exists or the user lacks permission, a non-sensitive fallback page is shown with an explanation And the link signature prevents parameter tampering and expires after 72 hours
Privacy & Access Controls
"As a security-conscious admin, I want strict access controls and anonymization in cohort analytics so that sensitive patterns aren’t exposed while still enabling insights."
Description

Enforces role-based access to cohort analytics, k-anonymity thresholds, and masking to prevent identification in small cohorts. Applies least-privilege access, audit logging for metric views/exports, configurable data retention, and PII minimization in alerts and downloads. Integrates with SSO/SCIM for provisioning and revocation, aligning with SOC 2 controls.

Acceptance Criteria
RBAC: Cohort Analytics View vs Export Permissions
- Given a user with Role=Viewer, when accessing Cohort Lenses, then they can view aggregated metrics for authorized cohorts and cannot export or see row-level or PII data. - Given a user with Role=Analyst, when accessing Cohort Lenses, then they can view and export aggregated metrics for authorized cohorts but cannot access PII or row-level data. - Given a user with Role=Admin, when accessing Cohort Lenses, then they can configure RBAC policies and export aggregated metrics but cannot bypass k-anonymity or masking controls. - Rule: Access to a cohort slice is allowed only if the user is assigned to a permission scope that includes the dimensions used (role, team, seniority, meeting type, internal/external). - Rule: Unauthorized slices are excluded from filters and search, and deep links to unauthorized slices return HTTP 403 with no data leakage.
K-Anonymity Thresholds and Masking Enforcement
- Rule: Tenant-configurable k threshold (default 5; allowed range 3–20) applies to all Cohort Lenses visualizations and exports. - Given a cohort slice where count < k, when metrics are requested, then counts are suppressed, percentages are suppressed or rounded per policy, and the slice is labeled "Insufficient sample". - Given a near-threshold cohort where any drilldown would create subgroups with count < k, when the user attempts drilldown, then drilldown is blocked or auto-aggregated to maintain k-anonymity. - Rule: No combination of visible fields (including time granularity and filters) enables derivation of counts < k. - Rule: Exports mirror UI masking/suppression with no optional override.
Least-Privilege Defaults and Access Revocation via SSO/SCIM
- Rule: Newly provisioned users via SCIM are assigned the least-privilege role (Viewer) with export permission disabled by default. - Rule: Role elevation requires Admin approval and is captured in immutable audit logs with approver identity and timestamp. - Given a user is deprovisioned in the IdP or removed from an authorized group, when SCIM/SSO events are received, then all active sessions are revoked and access disabled within 15 minutes. - Given a deprovisioned user attempts access, then requests return HTTP 401/403 and are logged as denied. - Rule: Cohort access scopes are derived from IdP group mappings; local overrides are disallowed unless a tenant setting explicitly enables them.
Audit Logging of Metric Views and Exports
- Rule: Every cohort metric view or export writes an immutable audit record including userId, tenantId, action (view/export), slice definition (dimensions and filters), timestamp (UTC), IP address, user agent, request ID, and outcome (success/failure). - Rule: Audit records are tamper-evident and retained per tenant policy; deletion follows retention rules only. - Given an Admin requests audit logs for a date range they are authorized to view, then results are filterable by user, action, and cohort slice and can be exported as CSV without PII. - Given export volume exceeds a tenant-configurable threshold within a 24h window, then an alert is sent to designated admins containing summary metadata only (no PII).
Configurable Data Retention and Automatic Purge
- Rule: Tenant can configure independent retention periods for analytics aggregates and audit logs (30–730 days), defaulting to 365 days. - Given a record exceeds its retention period T, when the scheduled purge job runs nightly, then records older than T are irreversibly deleted and the purge is logged with counts. - Given retention is reduced, then a backfill purge completes within 24 hours to comply with the new policy and is fully auditable. - Rule: Backups and disaster recovery restores honor current retention; purged data is not reintroduced post-restore.
PII Minimization in Alerts and Downloads
- Rule: Cohort Lenses alerts and exports must not include direct identifiers (e.g., name, email, employee ID) or exact timestamps that enable re-identification in small cohorts. - Given a user generates an export, then only aggregated metrics, cohort dimension labels, and anonymized IDs (if strictly necessary) are included; any PII fields are omitted or redacted. - Given an automated alert is triggered for cohort drift, then the alert contains only cohort labels and masked metrics; no user-level exemplars or raw logs are included. - Rule: CSV headers and metadata avoid PII; schemas are documented and validated in CI to prevent regressions.
SSO-Only Access and SOC 2 Aligned Controls
- Rule: Tenant can enforce SSO-only access; password-based login is fully disabled when enabled. - Rule: Session policies align with tenant configuration within secure bounds (max session 12h, idle timeout 30m by default); enforcement is applied to web and API access. - Given SSO group assertion does not include required cohort access groups, then the user is denied access to restricted slices even if a local role exists. - Rule: Changes to security settings (RBAC, k threshold, retention, SSO-only) require Admin role and are logged with before/after values and approver identity.

Recovery Nudges

When drift persists, the right people get gentle Slack/email prompts with pre‑vetted alternate windows and one‑tap approval. Escalations and reminders keep momentum until attendance returns to baseline.

Requirements

Slack and Email Nudge Delivery
"As a remote team member, I want to receive clear, actionable nudges in my primary communication channel so that I can reschedule quickly without hunting through calendars."
Description

Implement Slack and email channels to deliver Recovery Nudges with pre-vetted alternate windows and actionable controls. Support Slack DMs and threads via OAuth-installed app, interactivity (buttons, modals), and email with secure one-tap links and fallback workflows. Include message templating, personalization, link signing, idempotent click handling, and event tracking. Ensure retries, rate limiting, and graceful degradation if a channel is unavailable. Integrate with TimeMeld’s scheduling engine and user profiles to select channel preference and locale. Log deliveries and outcomes for analytics.

Acceptance Criteria
Slack nudge: DM or thread with actionable controls
Given a nudge is generated for a recipient with Slack OAuth installed and Slack selected as preferred channel in their user profile When the nudge is dispatched Then TimeMeld posts either a DM or a thread reply (if a meeting thread_id is present) to the recipient within 60 seconds of dispatch And the message renders at least 2 pre-vetted alternate windows formatted in the recipient’s locale and timezone And the message includes interactive controls: Approve [Window X], Approve [Window Y], and a "See more" button that opens a modal listing up to 5 windows And Slack interactivity callbacks are verified using Slack signature validation; invalid signatures return 401 and are ignored without state change And the message uses template "recovery_nudge_slack_v1" with personalization tokens {first_name}, {meeting_title}, {owner_name} resolved with no missing tokens And a DeliveryAttempted and Delivered event are recorded with message_id, channel=slack, nudge_id, recipient_id
Email nudge: one-tap secure approval links
Given a nudge is generated for a recipient with email selected as preferred or fallback channel and a verified email address on file When the nudge is dispatched Then an email using template "recovery_nudge_email_v1" is submitted to the ESP within 60 seconds and includes at least 2 pre-vetted alternate windows rendered in the recipient’s locale and timezone And each approval control is a one-tap link containing a signed, expiring token bound to nudge_id, recipient_id, and window_id that expires after 24 hours And clicking a valid link applies the selection and returns a confirmation page within 2 seconds; expired or tampered links return 401 and a secure fallback page offering "Request new link" And DeliveryAttempted, Delivered, Opened, and Clicked events are logged with message_id, channel=email, nudge_id, recipient_id
Action processing: update schedule and invites
Given a recipient approves a proposed window via Slack button or email one-tap link for a nudge tied to meeting_id When the action is processed Then the scheduling engine reserves the selected window, updates the meeting record, and sends calendar invites to all required attendees within 60 seconds And conflicting windows for the same nudge are invalidated and marked as superseded And the equity scoreboard and meeting ownership rotation are updated accordingly And an ActionProcessed event with outcome=approved, meeting_id, window_id is logged; downstream attendees receive a confirmation notification per their channel preferences
Templating, personalization, locale and timezone formatting
Given a nudge is generated for a recipient with user profile fields first_name, locale, timezone, channel_preference, and team When messages are rendered for Slack and email Then the selected template versions are retrieved by key and version and all personalization tokens resolve without placeholders And date/time strings are localized to the recipient’s locale and timezone (e.g., en-US vs fr-FR formats) And if the recipient has no locale, default to workspace locale; if no timezone, default to meeting timezone And rendering failures fail the nudge before dispatch and are logged with error_type=rendering_failed
Idempotent action handling across channels
Given multiple action attempts are made for the same nudge_id and recipient_id (duplicate link clicks, repeated Slack button presses, or retries) When the first valid action is processed Then subsequent duplicate actions return 200 with message "Already processed" and produce no state change And all actions share an idempotency key composed of nudge_id+recipient_id+window_id; only the first succeeds And duplicates are logged with outcome=duplicate without generating additional notifications
Retries, rate limiting, and graceful degradation
Given transient delivery failures occur (Slack 5xx/429, ESP 5xx/deferrals) When dispatch is attempted Then the system retries with exponential backoff (2s, 4s, 8s) up to 3 attempts, honoring provider 'Retry-After' headers And if Slack fails after retries, the nudge is sent via email (if allowed by recipient preferences) within 5 minutes; if email fails, fallback to Slack similarly And if both channels fail, the nudge is queued for a retry cycle in 60 minutes and an alert is emitted to ops And all retries and fallbacks are logged with attempt counts and final outcome
Delivery and outcome analytics logging
Given nudges are dispatched and interacted with When events occur (DeliveryAttempted, Delivered, Opened, Clicked, ModalOpened, ActionProcessed, FallbackTriggered) Then each event is appended to the analytics stream with fields: nudge_id, meeting_id, recipient_id, channel, template_version, timestamp (UTC), and correlation_id And events are queryable in the analytics store within 5 minutes of occurrence for 95% of events and retained for at least 90 days And PII is limited to hashed recipient_id; no raw email addresses or Slack tokens are stored in event payloads
Recipient Targeting Engine
"As a meeting organizer, I want nudges sent only to the people who can unblock scheduling so that we minimize noise and increase response rates."
Description

Build logic to identify the right recipients for Recovery Nudges when attendance drift persists. Determine stakeholders based on meeting role (organizer, rotating owner), criticality, historical attendance, and dependency mapping. Respect user preferences, working hours, timezones, do-not-disturb, and equity rotation. De-duplicate across overlapping meetings, suppress nudges for those already responded, and include escalation recipients when needed. Integrate with calendar sources, attendance logs, and the equity scoreboard to produce a prioritized, minimal recipient list per nudge event.

Acceptance Criteria
Triggering Recipient Selection on Persistent Attendance Drift
Given the last 3 occurrences of a recurring meeting show attendance below baseline by ≥20%, And a nudge event is generated for that series, When the targeting engine runs, Then it selects candidate recipients including the meeting organizer, the current rotating owner per the equity scoreboard, and critical stakeholders as defined in the dependency map, And Then the candidate pool is limited to attendees of the affected meeting series and occurrence.
Prioritized Minimal Recipient List Generation
Given a set of candidate recipients for a nudge event, When the engine prioritizes the list, Then recipients are ordered as: rotating owner (if assigned for this cycle) > organizer > critical-path stakeholders (ascending by historical attendance rate) > optional attendees, And Then the final recipient list contains no more than 5 people and includes at least 1 representative from each affected dependency group (if present), And Then each recipient entry includes a role tag (e.g., organizer, rotating_owner, critical_path, optional) in the output payload.
Respecting Preferences, Timezones, Working Hours, and Do Not Disturb
Given a candidate recipient has active Do Not Disturb or is outside their configured working hours in their local timezone, When compiling the list for the current nudge event, Then that recipient is excluded from the current send, And Then the output payload records channel preference (Slack or email) and local timezone for each included recipient, And Then no recipient is selected more than once within a rolling 24-hour period across all meetings.
De-duplication Across Overlapping Meetings and Response Suppression
Given a recipient is a candidate for multiple meetings with start times overlapping by ≥30 minutes within a 2-hour window, When generating recipients, Then the engine includes the recipient only for the highest-priority meeting (by meeting criticality, then earliest start time) and removes them from others, And Given a recipient has responded (accept/decline/proposed alternate) to a nudge for this meeting series within the last 24 hours, When generating recipients, Then the engine excludes that recipient from the list, And Then the final recipient list contains no duplicate user IDs.
Escalation Recipient Inclusion on Non-Response
Given a nudge was sent and no primary recipient has responded within 8 business hours, When the next evaluation cycle runs, Then the engine adds escalation recipients as defined by the meeting’s escalation policy (e.g., team lead, project owner), capped at 2 additional recipients, And Then only one escalation wave occurs per meeting occurrence per 24 hours, And Then escalation recipients are not added if any primary recipient has accepted or scheduled an alternate time.
Data Integration, Fallbacks, and Error Handling
Given integrations with calendar sources, attendance logs, and the equity scoreboard are available, When the engine runs, Then it uses data timestamps not older than 15 minutes, And When any source is unavailable, Then the engine retries up to 3 times over 5 minutes and falls back to last known data not older than 24 hours; if older than 24 hours, it skips rules requiring that source and marks the run as partial in telemetry, And Then each run emits an audit record with meeting ID, selected recipient IDs, exclusion reasons, data timestamps, and ruleset version.
Equity Rotation Compliance and Fairness Caps
Given an equity scoreboard defines the current rotating owner and per-member nudge counts, When generating recipients, Then the rotating owner for the cycle is included unless they have exceeded a monthly nudge cap of 4, in which case the next eligible member by rotation is selected, And Then no individual is selected as a primary recipient more than 2 times for the same meeting series within a rolling 7-day window.
Alternate Window Generation
"As an attendee, I want suggested times that already respect my hours and the team’s fairness rules so that I can approve a slot with one tap."
Description

Generate a short list of pre-vetted meeting windows optimized for participants’ timezones, working hours, and ergonomic constraints. Use TimeMeld’s timezone-weighted algorithm, avoid repeating recently inconvenient slots, and honor rotation rules from the equity scoreboard. Pull availability from connected calendars, account for buffers and travel time, and produce 3–5 viable options with confidence scores. Expose options to the nudge payload with metadata (start/end, timezone, participant fit score, conflicts).

Acceptance Criteria
Timezone-Weighted Option Generation (3–5 Viable Windows)
Given a meeting request with 4 participants across 3 timezones and all have connected calendars and working hours configured And the lookahead window is the next 10 business days When the alternate window generator runs Then it returns between 3 and 5 unique windows And each window includes a confidenceScore between 0 and 1 And each window’s start and end are within all participants’ declared working hours And no two returned windows have identical start and end
Calendar Availability, Buffers, and Travel Time Respected
Given participants have busy events on connected calendars and personal buffer settings (e.g., 10 minutes before/after meetings) and travel time between in-person events When generating alternate windows Then no proposed window overlaps any participant’s busy events And each proposed window starts no earlier than the required buffer after any preceding event and ends no later than the required buffer before any following event for every participant And proposed windows preserve required travel time gaps between sequential in-person events for every participant
Exclude Recently Inconvenient Slots
Given the system history contains a set of slots marked as inconvenient for any participant within the last 21 days When generating alternate windows Then none of the returned windows match any recorded inconvenient slot within that lookback window And none of the returned windows fall within any exact timestamp range recorded as inconvenient
Honor Equity Scoreboard Rotation
Given the equity scoreboard designates user U3 as the next meeting owner When generating alternate windows Then each window’s metadata includes ownerId = U3 And no window assigns a different ownerId And all returned windows keep U3 within their working hours and ergonomic constraints
Ergonomic Constraints Across Timezones Applied
Given participants have ergonomic constraints configured (e.g., quiet hours, lunch break, daily meeting cap) When generating alternate windows Then no window violates any participant’s quiet hours or lunch break And no window causes any participant to exceed their daily meeting cap on that day And no window falls outside any participant’s allowed working-hours band unless their preferences explicitly permit exceptions
Nudge Payload Option Metadata Complete
Given alternate windows are generated When building the Recovery Nudge payload Then each option object includes: start (ISO 8601), end (ISO 8601), timezone (IANA), confidenceScore (0–1), participantFitScores [{participantId, score 0–1}], conflicts [{participantId, eventId, type}] And the payload validates against the defined schema And for every option, start precedes end and timezone corresponds to the intended local display zone
One-Tap Approval and Auto-Reschedule
"As a busy engineer, I want to confirm a new time instantly from the message so that I don’t have to open my calendar or a separate app."
Description

Provide secure, one-tap approval from Slack buttons or email links to confirm a proposed window, request alternatives, or decline with reason. On approval, automatically update the calendar event, notify all participants, adjust the equity scoreboard, and cancel obsolete holds. Ensure link signing, expiration, and idempotency; handle race conditions if multiple users act simultaneously; and present conflict-resolution flows when the chosen slot becomes unavailable.

Acceptance Criteria
Slack One‑Tap Approval Actions
Given a recipient views a Recovery Nudge in Slack with buttons [Approve], [Need alternatives], [Decline] When the user clicks any button Then the action is acknowledged in Slack within 3 seconds with a visible ephemeral confirmation And the system records the user, meeting ID, proposed window, and action timestamp And the message updates to reflect the action state (approved/alt requested/declined) And only users on the invite list or delegated schedulers can act; others see an authorization error
Email One‑Tap Approval via Signed Link
Given a recipient opens an email nudge containing one‑tap links for [Approve], [Need alternatives], [Decline] When the user clicks a link Then the link is verified as signed, untampered, and unexpired And the user sees a confirmation page within 3 seconds reflecting the action state And the action is recorded with user identity derived from the email recipient and link payload
Escalation and Reminder Cadence
"As a team lead, I want smart reminders that escalate only when necessary so that scheduling momentum is maintained without spamming the team."
Description

Implement configurable reminder and escalation rules that continue nudging until attendance metrics return to baseline or a stop condition is met. Support time-based reminders, channel escalation (e.g., from DM to small group to manager), and ownership escalation to the rotating owner. Enforce quiet hours, per-user rate limits, and global caps. Provide admin-level policies and per-meeting overrides, and stop automatically upon resolution to prevent over-notification.

Acceptance Criteria
Time-Based Reminder Cadence Respects Quiet Hours
Given an admin policy with reminder offsets 15m, 2h, and 24h and per-user quiet hours 20:00–08:00 local And a meeting drift event is detected at 09:00 local When the system schedules reminders Then each recipient receives reminders at 09:15 and 11:00 local and next day at 09:00 local And any reminder falling in their quiet hours is deferred to the next allowed minute after quiet hours And each send is logged with timestamp, recipient, channel, and policy version
Auto-Stop on Resolution and Stop Conditions
Given nudging is active for a meeting series due to attendance below baseline When any of the following occurs: attendance meets or exceeds baseline for 2 consecutive occurrences, a new time is accepted, the meeting is canceled, an admin or rotating owner taps Stop, or a snooze is set Then all pending reminders and scheduled escalations for that series are canceled within 1 minute And no further nudges are sent unless a new trigger occurs And a resolution event is written to the audit log with the stop reason
Channel Escalation Path DM → Small Group → Manager
Given a channel escalation policy DM -> small group -> manager with step thresholds of 2 failed nudges or 24h without response When DM nudges reach the threshold without resolution Then the next nudge posts in the designated small group channel mentioning only required participants and includes pre-vetted alternate windows with one-tap approval links And if that step also fails per threshold, the next nudge is sent to the manager via their preferred channel (Slack DM or email) And at no point does any recipient receive more than one nudge per 4h per-user rate limit And all escalation steps are recorded with timestamps and recipients
Ownership Escalation to Rotating Owner
Given an active series with a configured rotating owner roster When escalation threshold E is reached without resolution Then the current rotating owner is assigned as the recovery owner and receives a high-priority nudge with Accept and Decline And on Accept, ownership is updated in the shared scoreboard and subsequent nudges reference the owner And on Decline or no action for 4h, assignment advances to the next rotating owner And ownership escalation resets the cadence according to the policy and is logged
Quiet Hours, Per-User Rate Limits, and Global Caps
Given per-user quiet hours, a per-user rate limit R per 24h, and a workspace global cap G messages per hour When the system attempts to send a nudge Then it does not send during a recipient’s quiet hours and queues to the next allowed minute And it skips sending to recipients who have reached R nudges in the past rolling 24h and marks the attempt as rate-limited And it defers sends that would exceed the global cap G to the next hour boundary while preserving order And all queued, skipped, and sent events are visible in the audit feed with reasons
Admin Policy and Per-Meeting Overrides
Given an admin-level default policy P and a per-meeting override O When both define cadence, channels, quiet hours, or caps Then O takes precedence within bounds enforced by P such that cadence is not faster than P.minCadence and quiet hours are not narrower than P.minQuietHours And invalid overrides are rejected with a clear validation message and no changes are saved And upon save, the effective policy is computed, stored with a version ID, and displayed in the meeting settings And all changes include who, what, when in the audit log
Attendance Baseline Trigger and Recovery
Given baseline attendance is defined as the median of the last 6 completed occurrences (minimum 3) And the trigger threshold is a drop of at least 10 percentage points for 2 consecutive occurrences When the trigger condition is met Then nudging activates for the affected meeting and targeted attendees And nudging continues until attendance returns to within 2 percentage points of baseline for 2 consecutive occurrences or a stop condition occurs And metrics and state transitions are recorded and available in reporting
Drift Detection and Stop Conditions
"As an operations manager, I want nudges to activate only when attendance problems persist and stop once fixed so that we avoid unnecessary interventions."
Description

Detect when attendance has drifted from baseline to trigger Recovery Nudges and determine when to stop. Compute baselines per team and meeting series over rolling windows, define thresholds, and apply hysteresis to avoid oscillation. Ingest attendance signals (RSVPs, joins, no-shows), classify root causes (time misfit, conflicts), and emit clear trigger events to the nudge pipeline. Record recovery state and suppress nudges once metrics return to baseline.

Acceptance Criteria
Rolling Baseline Computation per Team and Meeting Series
- Rule: For a meeting series, baseline_attendance = mean attendance_rate of the last N valid occurrences (default N=8; min_samples=5). Exclude canceled or skipped occurrences. - Rule: For a team-level baseline, baseline_attendance = mean attendance_rate across the team’s meetings in the trailing 30 days with min_samples=10; otherwise mark baseline_status = insufficient_data and do not evaluate drift. - Rule: Baselines recompute on schedule (00:30 UTC daily) and on occurrence_finalized events; each computation completes in ≤2 seconds per entity. - Rule: Persist baseline value, window parameters, sample_size, computed_at, and contributing occurrence IDs.
Drift Detection and Trigger Emission
- Given a computed baseline and a finalized meeting occurrence with observed_attendance_rate, When observed_attendance_rate ≤ baseline − 10 percentage points OR observed_attendance_rate < 70%, for 2 consecutive finalized occurrences within 21 days, Then emit NudgeTrigger.DriftDetected for the entity with severity = normal. - Rule: The emitted event includes: entity_type, entity_id, occurrence_id, baseline_rate, observed_rate, delta_pp, comparison_window, consecutive_count, computed_at, cause_class (if available), confidence, recovery_state_id. - Rule: Emit at most one DriftDetected per occurrence_id (idempotent). - Rule: Team-level drift and series-level drift are evaluated and emitted independently.
Hysteresis and Stop Conditions to Prevent Oscillation
- Given the entity is in Recovering state after a DriftDetected, When three consecutive occurrences have observed_attendance_rate ≥ (baseline − 2 percentage points) and the 14-day rolling mean ≥ (baseline − 1 percentage point), Then emit RecoveryResolved and transition state to Recovered. - Rule: While in Recovering and before the stop condition is met, do not emit additional DriftDetected for the same entity unless observed_attendance_rate ≤ (baseline − 20 percentage points) for two additional consecutive occurrences (severity = high). - Rule: If no new occurrences finalize within 30 days, retain Recovering state without emitting new events and re-evaluate on the next finalized occurrence.
Signal Ingestion and Attendance Derivation
- Rule: Supported signals: RSVP(yes/no/maybe/optional), Join/Leave timestamps, Meeting start/end, Organizer cancellation, Decline reason text. - Rule: Attendance rate denominator = count of invited required participants who did not decline; numerator = count of those who joined any time before meeting end or within 10 minutes after start; optional invitees are excluded from both numerator and denominator. - Rule: Reschedules preserve occurrence_id; duplicate signals are de-duplicated by source_event_id; late arrivals are counted as attended; no join by meeting end ⇒ no-show. - Rule: Normalize all timestamps to UTC; ingestion latency p95 ≤ 60 seconds; backfill window = 24 hours; ingestion failures are logged and retried up to 3 times with exponential backoff.
Root Cause Classification on Drift
- Given a DriftDetected candidate, When classification runs, Then compute and attach primary_cause and confidence per rules. - Rule: primary_cause = time_misfit if > 40% of required invitees’ local meeting time falls outside ergonomic hours (08:00–18:00 local) OR median local start time < 07:00 or > 19:00; confidence = min(1.0, proportion/0.4). - Rule: primary_cause = scheduling_conflict if > 20% of required invitees had overlapping busy events; confidence = min(1.0, proportion/0.2). - Rule: primary_cause = invite_scope_issue if optional invitees > required invitees and required attendance is within 5 pp of the team baseline; confidence = 0.6. - Rule: primary_cause = technical_issue if a platform incident overlapped the meeting OR join-failure rate > 10%; confidence = min(1.0, proportion/0.1). - Rule: If none apply, primary_cause = unknown; confidence = 0.3.
Recovery State Recording and Idempotency
- Rule: Maintain per entity a recovery_state machine with states {Stable, Drifted, Recovering, Recovered}; allowed transitions: Stable→Drifted→Recovering→Recovered→Stable. - Rule: All state transitions are idempotent by occurrence_id and persisted with timestamps, actor=system, and prior/new state snapshots. - Rule: Query API GET /v1/recovery-state?entity_id returns current_state, last_transition_at, baseline_rate, observed_rate_last, consecutive_counts, and the last 20 transitions in ≤ 200 ms p95. - Rule: Reprocessing the same occurrence does not create duplicate transitions or duplicate events (verified by deterministic keys).
Nudge Suppression and Cooldown after Recovery
- Given the entity transitions to Recovered, When evaluating occurrences within the next 14 days, Then do not emit NudgeTrigger.DriftDetected unless observed_attendance_rate ≤ (baseline − 20 pp) AND < 60% for two consecutive occurrences. - Rule: While Recovered and within cooldown, emit only HealthStatus updates (non-trigger) that include observed_rate and baseline. - Rule: After the 14-day cooldown, resume standard drift detection thresholds and behaviors.
Notification Preferences and Compliance
"As an attendee, I want control over how and when I’m nudged so that messages are helpful and respect my preferences and privacy."
Description

Provide per-user and per-workspace controls for nudge channels, frequency, quiet hours, and opt-in/opt-out, with admin-enforced minimums for critical meetings. Include unsubscribe mechanisms in email, Slack slash commands for preferences, and audit logs. Ensure compliance with GDPR/CCPA, store consent and purpose limitation, and honor data deletion requests. Localize content and time formats based on user locale and timezone.

Acceptance Criteria
User-configurable nudge channels, frequency, and quiet hours
Given a signed-in user with default nudge settings When they open Preferences → Nudges and toggle Email and Slack channels independently Then the changes persist and are reflected on reload Given the user has only Slack enabled When a recovery nudge is triggered for them Then only Slack receives the nudge and Email is not sent Given the user sets frequency cap to 2 nudges per 24 hours When the system attempts to send a 3rd nudge within 24 hours Then the nudge is suppressed, a suppression reason is recorded, and the next send is scheduled after the cap window resets Given the user sets quiet hours to 21:00–08:00 in their timezone When a nudge would be sent at 22:30 local time Then it is deferred to the next allowed window unless the nudge is marked critical Given the user disables all channels for non-critical nudges When non-critical nudges are triggered Then no messages are delivered and the suppression is logged with reason "user opt-out"
Admin-enforced minimums for critical meetings
Given a workspace admin enables a policy requiring at least one channel for critical meetings When a user attempts to opt out of all channels for critical nudges Then the UI blocks the change, displays the policy notice, and retains at least one admin-required channel enabled Given a critical nudge must be sent during a user’s quiet hours When the admin policy allows override for critical Then one nudge is delivered during quiet hours with the minimum frequency set by policy and an enforcement event is added to the audit log Given non-critical nudges are triggered for the same user When user preferences disable all channels for non-critical Then no non-critical nudges are sent despite the critical policy Given an admin changes the critical policy When the policy is saved Then all impacted users’ effective settings recalculate within 5 minutes and are visible in an admin review screen
Email unsubscribe and preferences links
Given a user receives a non-critical nudge email When they click the Unsubscribe link Then they are immediately unsubscribed from non-critical email nudges, receive a confirmation page within 3 seconds, and no further non-critical emails are sent to them Given the same email includes a Manage Preferences link When the user clicks it and updates settings Then changes persist and are effective for subsequent sends within 60 seconds Given a user receives a critical meeting email When they click Unsubscribe Then they are shown a page explaining the admin-enforced policy, with options to adjust non-critical preferences, and no change is made to critical delivery Given a nudge email is sent Then the message includes valid List-Unsubscribe and List-Unsubscribe-Post headers and an HTTPS one-click unsubscribe endpoint that processes requests within 60 seconds
Slack slash commands for managing preferences
Given the TimeMeld Slack app is installed and the user is linked When the user enters "/timemeld prefs" Then an ephemeral interactive message displays current channels, frequency cap, and quiet hours, and saving updates persists settings immediately Given the user enters "/timemeld stop" When the command is processed Then the user is unsubscribed from non-critical Slack nudges immediately and receives an ephemeral confirmation Given the user is not linked or the app is not installed When they issue either command Then they receive an ephemeral error with steps to authenticate/install and no settings are changed Given any change is made via Slack Then an audit entry records actor, source="Slack", fields changed, and timestamp
Audit logging of preference, consent, and policy changes
Given any change to a user’s notification preferences, consent status, or an admin policy When the change is saved Then an immutable audit record is created with timestamp (UTC), actor (user/admin/system), workspace, affected user, fields before/after, source (Web/Email/Slack/API), and request metadata (IP/User-Agent where available) Given audit data is requested by an admin with the proper permission When they filter by user and date range and export as CSV or JSON Then the export completes within 60 seconds for up to 100,000 records and an export event is itself logged Given an auditor attempts to modify or delete an audit record via the UI or API When the request is made Then the system denies the action and records the attempt
GDPR/CCPA consent, export, and deletion handling
Given a user first enables nudges When consent is required by their region Then the system records time-stamped, versioned consent with declared purposes and no nudges are sent until consent is captured Given a user opts out of non-critical nudges When a nudge is triggered Then it is not sent and the suppression is attributed to opt-out; for critical nudges under admin policy, the send includes a recorded lawful-basis note in the audit log Given a user submits a data deletion request When the request is confirmed Then all personal data related to nudges and preferences is erased or irreversibly anonymized within 30 days, sending ceases within 24 hours, and a completion confirmation is provided; minimal non-identifying audit entries are retained where legally permissible Given a user requests a copy of their data When the request is submitted Then a machine-readable export including preferences, consents, and related audit entries is available for secure download within 7 days
Localization of content and time formats
Given a user has locale fr-FR and timezone Europe/Paris When a Slack or Email nudge is sent Then the message text is in French, dates/times use 24-hour format and DD/MM/YYYY, and times are converted to Europe/Paris with appropriate abbreviations Given a translation key is missing for a locale When a nudge is generated Then the system falls back to English content without exposing raw template keys and logs a localization warning Given a workspace default locale differs from a user’s locale When a nudge is sent to that user Then the user’s locale takes precedence for content and formatting Given automated localization tests run When the test suite executes Then snapshots for en-US, en-GB, fr-FR, de-DE, and ja-JP pass for both email and Slack templates

RippleGuard Rebook

Finds the nearest fair time that triggers the fewest downstream conflicts. Slipstream simulates candidate slots across all attendees’ calendars, avoids guard breaches, and chooses the option with minimal ripples—so you reschedule once, not three times, while protecting maker hours.

Requirements

Ripple Simulation Engine
"As a product manager, I want the system to simulate reschedule impacts across all attendees’ calendars so that we pick a time that minimizes downstream conflicts and avoids rebooking cascades."
Description

Implement a scoring-based simulation that evaluates candidate reschedule slots across all attendees’ calendars to quantify downstream conflicts (“ripples”). The engine builds a conflict graph from free/busy, meeting dependencies, buffer/travel times, and recurrence chains, then computes a ripple cost for each candidate. Costs factor in guardrail breaches (maker hours, no‑meeting blocks), timezone fairness, and attendance risk. The engine returns an ordered set of viable times with explanations and trace data for auditability, enabling data-driven rebooking that minimizes rework and protects productivity.

Acceptance Criteria
Conflict Graph Construction from Calendars and Constraints
Given attendees with connected calendars providing free/busy, event metadata (location, buffer/travel time, recurrence), and meeting dependency links And a target reschedule window with enumerated candidate slots When the engine constructs the conflict graph Then nodes represent all relevant events and each candidate slot within the evaluation horizon And edges represent conflicts due to time overlap, buffer/travel requirements, and explicit dependencies And recurrence chains are represented with series identifiers and occurrence indices And cancelled events are excluded; tentative holds are marked as soft conflicts And for each candidate slot, the engine enumerates conflicting events per attendee with timestamps and conflict reasons
Ripple Cost Computation with Guardrails, Fairness, and Risk
Given a constructed conflict graph and a set of candidate slots And a weight configuration for cost components When the engine computes ripple cost per candidate Then total cost equals the sum of weighted components: guardrail breaches, timezone fairness adjustment, attendance risk, number of moves, buffer/travel shifts, and dependency violations And guardrail penalties include detection of maker-hours and no-meeting blocks per attendee profile And timezone fairness adjusts cost based on local-time ergonomics and equity rotation And attendance risk increases cost for slots outside preferred hours or with historical decline/no-show indicators And the output includes a numeric cost breakdown per component for each candidate
Candidate Filtering, Ordering, and Explanations
Given N candidate slots and computed costs When producing results Then candidates violating hard guardrails are excluded with machine-readable reasons And remaining candidates are ordered by ascending total cost And the top candidate’s total cost is less than or equal to all others And ties are resolved deterministically by earlier wall-clock time, then fairness score, then stable input order And each candidate includes a human-readable explanation and a trace id referencing full details
Guardrail Protection and Fallback Behavior
Given maker-hours and no-meeting blocks configured per attendee When evaluating candidates Then any candidate breaching a hard guardrail is excluded from viable results And candidates breaching soft guardrails receive the configured penalty but remain viable And if no candidates avoid hard guardrails, the engine returns the least-breach option with explicit breach reasons and affected attendees listed And the top result flags whether any guardrail was breached
Recurrence and Dependency Sensitivity
Given a meeting that is part of a recurrence series and participates in dependency constraints (e.g., must precede another meeting) When simulating reschedule options for a single occurrence Then ripple cost accounts for impacts to future occurrences within the evaluation horizon and to dependent meetings And ordering constraints are preserved; candidates that would violate required sequencing are marked invalid And explanations identify series/dependency contributors and quantify their cost contribution
Performance and Scalability Targets
Given up to 12 attendees, 100 candidate slots, and an 8-week evaluation horizon on a baseline server (2 vCPU, 4 GB RAM) When building the conflict graph and scoring all candidates Then total computation completes within 2000 ms p50 and 5000 ms p95 And peak memory usage remains under 500 MB p95 And enabling parallel scoring does not change the ordering or costs of results
Auditability and Determinism
Given identical inputs (attendees, calendars, configuration, seed, and time normalization) When the engine runs multiple times Then it produces identical ordered candidates and identical cost breakdowns And each candidate’s trace payload includes config version, weight values, input hashes, conflict graph summary, per-component costs, and decision path And traces are retrievable by trace id for at least 30 days
Nearest‑Fair Slot Finder
"As a distributed team lead, I want RippleGuard to locate the nearest fair time that respects everyone’s working hours so that rescheduling is quick and equitable."
Description

Create an optimization layer that searches the nearest future window satisfying fairness and guardrail constraints while minimizing ripple cost. The solver respects each attendee’s working hours, time‑zone ergonomics, personal preferences, and buffer policies, and applies tie‑breakers using fairness deltas and equity rotation. The output is a single best slot and a ranked shortlist, each annotated with why it was chosen and what trade‑offs were avoided, enabling quick, equitable rebooking aligned with TimeMeld’s fairness goals.

Acceptance Criteria
Nearest Fair Slot Selection and Ranked Shortlist
Given an existing meeting with attendees, original start time T0, and duration D When the solver runs to find a rebook time Then it returns exactly 1 primary slot and a ranked shortlist of up to 5 alternatives And the primary slot is the feasible slot with the smallest non-negative time delta from T0 And all returned slots satisfy fairness and guardrail constraints with zero guard breaches And the shortlist is ordered by: (1) minimal time delta from T0, (2) minimal ripple cost, (3) minimal fairness delta, (4) equity rotation priority, (5) earliest chronological time, (6) deterministic hash as final tie-breaker
Working Hours, Time-Zone Ergonomics, and Preferences Compliance
Given attendees have configured working hours, ergonomic windows, and personal preferences (hard and soft) When candidate slots are evaluated Then for each attendee, start and end times fall within their working hours and ergonomic windows And no hard preferences are violated for any attendee And soft preferences are only violated if no candidate exists within the search horizon that honors them, and any soft violation is explicitly flagged in the slot annotation
Maker-Hour Protection and Buffer Policy Enforcement
Given organization policies define protected maker-hour blocks and per-attendee buffer requirements before/after meetings When evaluating a candidate slot Then the slot does not overlap any protected maker-hour or focus blocks for any attendee And the slot provides at least the configured buffer_before before and buffer_after after adjacent events on each attendee’s calendar And any candidate failing buffer or maker-hour checks is excluded from results
Ripple Cost Simulation and Minimization
Given access to attendees’ calendars within a configurable horizon (default 14 days) And a configured ripple cost function with weighted components (e.g., conflicts created, meetings displaced, priority weight, attendees impacted) When simulating the downstream impact of each feasible candidate Then each candidate is assigned a ripple cost with its component breakdown And the selected primary slot has the lowest ripple cost among candidates with the same minimal time delta from T0 And the shortlist includes each candidate’s ripple cost and top impacted events, if any
Tie-Breakers: Fairness Delta and Equity Rotation
Given two or more feasible candidates with identical time delta from T0 and identical ripple cost When selecting the primary slot Then the solver selects the candidate with the smallest fairness delta versus the 90-day inconvenience baseline And if still tied, selects the candidate that advances the equity rotation to the next owner in the scoreboard And if still tied, selects the earliest chronological slot; if still tied, selects deterministically by stable hash of slot metadata And the applied tie-breaker sequence is recorded in the annotation
Explainability: Annotations and Trade-Offs
Given a chosen primary slot and a ranked shortlist When generating output Then each slot includes machine-readable fields: start/end in UTC, per-attendee local times, constraints satisfied, fairness score and delta, ripple cost with components, buffers applied, and tie-breakers used And each slot includes a human-readable summary listing the top 3 reasons it was favored and the top 3 trade-offs avoided And no personally sensitive data beyond attendee names and emails is included in annotations
Performance and Determinism SLA
Given up to 12 attendees, a 30–60 minute duration, and a 14-day search horizon on standard infrastructure When the solver runs Then 95th percentile end-to-end selection time is ≤ 2 seconds and maximum is ≤ 5 seconds And peak memory usage remains ≤ 200 MB during evaluation And results are deterministic for identical inputs, calendars, and configuration
Guardrail Compliance & Maker Hours Protection
"As an engineer, I want my maker hours to be protected during rebooking so that my focus time isn’t fragmented."
Description

Enforce hard and soft guardrails during rebooking, including maker‑hours blocks, no‑meeting days, lunch windows, and focus sessions. The system must detect potential breaches, suggest compliant alternatives, and clearly label any override as an exceptional action with reason capture and audit logging. Integration with personal calendar keywords (e.g., “Focus”, “Deep Work”) and organization policies ensures consistency, prevents fragmented schedules, and maintains high‑quality focus time for engineers and other makers.

Acceptance Criteria
Hard Guardrails Block and Alternatives Suggested
- Given a rebook is initiated and organizational guardrail configuration is loaded, When the nearest candidate time violates any hard guardrail for any attendee, Then the system must not schedule that time and must present up to 5 nearest compliant alternatives ranked by proximity and ripple score. - Given compliant alternatives are available within the defined search horizon, When alternatives are displayed, Then at least 3 options are shown (or all available if fewer) and each option lists which guardrails it satisfies and any soft warnings count = 0. - Given no compliant alternatives exist within the default horizon, When results are returned, Then the system displays "No compliant slots" with the first violated hard guardrail per attendee and provides controls to expand horizon or adjust participants.
Maker Hours Protected via Keywords and Policy
- Given an attendee has calendar events matching configured maker-hours keywords and maker-hours rules are enabled, When candidate slots are generated, Then no candidate overlaps any keyword-matched block by more than 0 minutes if the rule is hard, or marks a soft warning if soft. - Given a configured minimum contiguous maker-hours block length, When the rebook would split a contiguous maker block into segments shorter than the configured minimum, Then that candidate is rejected if hard or flagged as soft with a warning count incremented. - Given a candidate slot preserves all attendees' maker-hours blocks according to policy, When alternatives are ranked, Then candidates that preserve longer contiguous focus windows are ranked higher (tie-breaker after ripple score).
Soft Guardrail Override Workflow with Reason Capture
- Given a candidate time only violates soft guardrails, When a user selects this slot, Then the UI requires explicit confirmation with a mandatory free-text reason (minimum 10 characters) and shows the list of soft guardrails impacted. - Given an override is confirmed, When the meeting is rebooked, Then the calendar event is labeled as "Exception" in-app and the invite description includes the override reason and impacted guardrails. - Given an override occurs, When audit logs are written, Then the log includes user ID, timestamp, old time, new time, impacted soft guardrails, reason text, and before/after ripple metrics.
Lunch Windows and No-Meeting Days Across Time Zones
- Given each attendee's lunch window and no-meeting days are defined in local time and synced from org policy, When generating and validating candidate slots, Then no slot overlaps a hard lunch window or falls on a hard no-meeting day for any attendee. - Given conflicts with soft lunch windows or no-meeting days occur, When alternatives are presented, Then these candidates are ranked below fully compliant options and display per-attendee soft warnings. - Given daylight saving time transitions or ambiguous local times, When validating guardrails, Then the system evaluates guardrails using attendees' canonical time zones and resolves overlaps according to local civil time without cross-timezone drift.
Ripple-Minimizing Selection Under Guardrails
- Given a set of guardrail-compliant candidate slots within the search horizon, When selecting an automatic recommendation, Then the system chooses the slot with the lowest predicted ripple score (downstream reschedules within the next configured evaluation window) and zero hard guardrail breaches. - Given two or more candidates tie on ripple score and compliance, When breaking ties, Then the system prefers the earliest chronologically nearest slot, then the option earliest in the organizer's workday. - Given the selected slot triggers any soft guardrail warnings, When auto-selecting, Then the system does not auto-book and instead requires explicit override per the override workflow.
Audit Logging and Policy Versioning
- Given any rebooking attempt is initiated, When processing completes (success, failure, or override), Then an audit record is written containing policy version IDs used, rules evaluated, number of candidates evaluated, violations per candidate, final selection rationale, and outcome status. - Given organization policy or keyword list is updated, When the next rebook occurs, Then the system fetches the latest policy (or uses cache not older than the configured TTL) and records the policy version in the audit log. - Given audit logs are queried by an admin, When reviewing a specific rebook, Then the admin can see the exact guardrails and keywords in effect at decision time and the captured override reason if applicable.
One‑Click Rebook & Smart Notifications
"As a meeting owner, I want to rebook in one click and automatically notify attendees so that I don’t have to babysit the reschedule."
Description

Provide a streamlined action to rebook an existing meeting to the selected candidate slot, preserving conferencing links, agendas, and attendees. Automatically issue updated invites and send targeted notifications via email and Slack/Teams to only affected participants. Place short‑lived soft holds on leading candidates to prevent race conditions, gracefully release holds on decision, and manage declines with auto‑fallback from the ranked shortlist. All actions are tracked with status and error handling for reliability.

Acceptance Criteria
One-click rebook preserves meeting artifacts
Given an existing meeting with title T, agenda A, conferencing link L, attendees set S, and calendar event UID U And a ranked shortlist of candidate slots is displayed When the organizer clicks Rebook on candidate slot C Then the meeting start/end time updates to C And the conferencing link remains L And the agenda remains A And the attendees set remains S And the calendar event UID remains U with an incremented sequence/version And only one event exists for UID U after the operation And the operation completes within 5 seconds at the 95th percentile
Targeted notifications via email and Slack/Teams
Given the organizer rebooks a meeting to a new time And attendees include internal users with connected Slack/Teams and external guests without chat integrations When the rebook is confirmed Then internal attendees with connected chat receive a single consolidated chat notification and an updated calendar invite And internal attendees without chat receive an updated calendar invite and a single email notification And external guests receive an updated email invite only And no users outside the attendee list receive notifications And duplicate notifications are de-duplicated per channel per recipient And all notifications are dispatched within 60 seconds at the 95th percentile And delivery status is recorded per recipient and channel
Soft holds on top candidate slots prevent race conditions
Given a ranked shortlist of candidate slots [C1..Cn] with n >= 3 And a soft-hold TTL of 15 minutes When the shortlist is presented to the organizer Then soft holds are placed as tentative events on the top 3 candidates across all attendee calendars And availability reflects Busy for those hold periods during the TTL And if the organizer confirms Ck within the TTL, holds on all other candidates are immediately released And if the TTL expires with no decision, all holds are auto-released And hold placement and release operations are idempotent under retry and concurrent requests
Idempotent, concurrent-safe rebook execution
Given two or more concurrent rebook requests are issued for the same meeting When they target the same or different candidate slots Then exactly one request succeeds and the others return a conflict error without altering the event And the meeting ends with a single definitive time And no orphan soft holds remain after resolution And retries with the same idempotency key do not create duplicate updates or notifications
Auto-fallback on decline from mandatory attendee
Given the meeting is rebooked to C1 from a ranked shortlist [C1, C2, C3] And at least one mandatory attendee declines C1 within 30 minutes of the rebook When auto-fallback is enabled Then the system selects the next available slot in order (C2, then C3) that satisfies guard constraints and attendee availability And rebooks the meeting once to that slot And notifies only participants affected by the change And limits auto-fallback attempts to 2 before requiring organizer confirmation And logs the reason and outcome for each fallback attempt
Action audit trail and step-level error handling
Given any rebook action is attempted When processing completes or fails Then an immutable audit record is created including timestamp, actor, old/new time, selected slot rank, affected attendees, notifications sent, soft holds placed/released, and outcome (success/failure) And transient failures in notification dispatch or hold placement are retried with exponential backoff up to 3 times And terminal failures surface a clear error to the organizer with remediation guidance And step-level status and error codes are recorded and exposed in UI or logs And P95 end-to-end rebook latency is under 5 seconds excluding third-party provider latency
What‑If Impact Preview
"As a scheduler, I want to preview the impact of each candidate time so that I can choose the option with the least disruption."
Description

Before committing, display a comparative preview for top candidate slots, including ripple cost breakdown, attendees impacted, guardrails triggered or avoided, fairness score change, recurrence effects, and buffer/travel implications. Allow quick adjustment of constraints (e.g., make a rule soft for this instance) and instant recompute. Present clear explanations and color‑coded risk indicators so schedulers can make confident, minimally disruptive choices.

Acceptance Criteria
Preview Top Candidate Slots Comparison
- Given a user opens the What‑If Impact Preview for a selected meeting, When the preview loads, Then display between 3 and 5 top candidate slots ranked by lowest ripple cost. - For each candidate slot, Then display the following metrics: ripple cost (integer), conflicts created (count), conflicts resolved (count), guardrails breached (count) with hard vs soft breakdown, attendees impacted (count), fairness score delta (numeric between -1.0 and +1.0 to one decimal), recurrence impact (occurrences affected count), and buffer/travel impact (minutes gained/lost). - Then the preview must render initial results within 2.0 seconds for scenarios up to 12 attendees and a 12‑week recurrence window (95th percentile), and within 4.0 seconds for up to 25 attendees (95th percentile). - When fewer than 3 feasible slots exist, Then show all feasible slots and display a notice stating "Only X feasible slots" without error. - Then sorting must apply tie‑breakers in order: highest fairness delta, fewest guardrail breaches, earliest calendar date/time.
Color‑Coded Risk Indicators and Legend
- Given candidate slots are displayed, Then each candidate shows a risk badge using colors: Green (no guardrail breaches and ripple cost ≤ 1), Yellow (only soft breaches or ripple cost 2–3), Red (any hard breach or ripple cost ≥ 4). - Then each color state must include an icon and text label; color is not the sole carrier of meaning. - Then all badges and text meet WCAG 2.1 AA contrast (≥ 4.5:1) and are announced with accessible names for screen readers. - When a user hovers or taps a badge, Then a tooltip explains the assigned risk including specific guardrails triggered/avoided and numeric thresholds. - Then a persistent legend is visible within the preview and remains synchronized with badge definitions.
Constraint Adjustment with Instant Recompute
- Given the preview is visible, When a user softens a guardrail (Hard → Soft) or adjusts constraints (meeting window, buffer minutes, attendee optionality), Then all candidate metrics recompute and refresh within 1.5 seconds at the 95th percentile without a page reload. - Then the UI preserves scroll position and focus on the previously selected element after recompute. - Then updated candidates display transient diff indicators (e.g., Δ fairness +0.2, ripple −1) for 5 seconds. - When the user clicks Undo or presses Ctrl/Cmd+Z, Then prior constraints and results are restored within 1.5 seconds and diffs are cleared. - Then all recomputations are idempotent and produce identical results for identical inputs.
Attendee Impact and Maker‑Hours Protection
- Given candidate slots are shown, Then each candidate lists per‑attendee local time and a marker indicating whether it lands within protected maker hours. - Then a candidate is marked Invalid if >20% of attendees would breach hard maker‑hour guardrails; invalid candidates cannot be committed. - When the user filters to "Impacted only", Then the attendee list updates within 500 ms to show only negatively impacted participants. - Then the details panel surfaces the top 3 most impacted attendees sorted by severity score with their individual impact explanations. - Then counts and markers must match the underlying calendar simulation within ±1 minute tolerance for time boundaries.
Recurrence Effects and Series Safety
- Given the meeting is part of a series, Then the preview shows whether changes apply to "this instance" or "entire series" and displays number of occurrences affected. - Then ripple cost is presented as cumulative (sum) and per‑occurrence average when series is selected. - When a change would shift the series template by more than ±15 minutes from its standard slot, Then show a "Series drift" warning with Yellow if ≤30 minutes, Red if >30 minutes. - When the user toggles between "this instance only" and "entire series", Then all metrics recompute within 2.0 seconds (95th percentile) and the drift warning updates accordingly. - Then the preview flags any predicted holiday/OOO collisions across the affected occurrences with counts and first occurrence date.
Actionability and One‑Click Commit
- Given candidates are visible, Then each candidate provides a primary "Schedule this slot" action that commits the selection. - When the user commits, Then a confirmation modal summarizes time, attendees added/removed, fairness delta, guardrails soft‑applied, recurrence scope, and buffer/travel changes; user can Confirm or Cancel. - When commit succeeds, Then the meeting is updated, invites are sent, and an audit log entry is recorded with timestamp, operator, constraints, and computed metrics; a success toast appears within 1.0 second. - When commit fails, Then show an error with a Retry option and the next‑best candidate suggestion; no partial state is saved (all‑or‑nothing). - Then the committed result matches the last shown preview values within specified tolerances (time ±1 minute, fairness delta ±0.1, ripple cost exact).
Calendar Connectors & Permissions
"As an IT admin, I want secure, least‑privilege calendar integration so that RippleGuard can simulate schedules without overexposing data."
Description

Deliver secure, least‑privilege integrations with Google Workspace and Microsoft 365 to access free/busy, time zones, and event metadata required for simulation. Support OAuth with granular scopes, domain‑wide delegation options, shared/resource calendars, and per‑user consent. Implement caching with configurable TTLs, robust rate‑limiting/backoff, DST normalization, and encryption in transit/at rest. Provide admin controls, audit logs, and data residency configuration to meet compliance needs while ensuring simulation accuracy and responsiveness.

Acceptance Criteria
OAuth Consent with Least-Privilege Scopes
Given a user initiates connector setup for Google Workspace or Microsoft 365 When the consent screen is presented Then only scopes required to read free/busy, attendee response status, event start/end times, organizer, meeting link, user time zone, and calendar list are requested, excluding event body/attachments and write scopes by default Given the user completes consent When API requests are executed Then calls are limited to granted scopes and any attempt beyond those scopes is blocked and recorded in audit logs Given the user revokes consent or disconnects the connector When revocation is detected via webhook or polling (≤ 5 minutes) Then all access tokens are invalidated, user-specific caches are purged, and the UI reflects a disconnected state Given the user/admin toggles an optional "Create/Update Invites" capability When enabled Then additional write scopes are explicitly requested and must be consented to before any write occurs When disabled Then no write scopes are requested and all write operations are blocked
Domain-Wide Delegation Configuration & Enforcement
Given a tenant admin configures domain-wide delegation/Application Permissions with specified scopes When impersonation is used for an in-tenant user during simulation Then only read operations necessary for free/busy and event metadata are permitted unless write capability is explicitly enabled, and impersonation is limited strictly to the selected users Given an attendee is outside the managed tenant When included in a simulation Then the system does not attempt impersonation and uses per-user consent or publicly shared free/busy endpoints where available; otherwise the attendee is treated as unknown availability Given the admin revokes or narrows delegation scopes When the next impersonated call is attempted Then impersonation stops within 5 minutes, the admin console shows an actionable error, and an audit entry captures the failing scope and user context
Shared and Resource Calendars Coverage
Given a connected account has access to shared and resource calendars When calendar discovery runs Then the system lists those calendars and allows per-user or admin inclusion/exclusion for simulation Given a resource calendar (e.g., meeting room) is included When requesting availability during simulation Then free/busy is fetched and respected for conflicts, and no event body content is retrieved Given calendar ACLs change When the next sync occurs (≤ 10 minutes) Then access reflects the new ACLs, unauthorized calendars are removed from cache, and simulations exclude them
Caching TTLs and Staleness Management for Simulation Accuracy
Given free/busy data is fetched When caching is enabled Then free/busy cache TTL is configurable per connector (default 120s, range 30–600s) with per-user overrides, and expired entries refresh on demand Given provider rate limits or transient errors occur When cache TTL has expired but staleness threshold has not (default 5 minutes, configurable) Then simulations may use cached data and mark results as stale with last-refreshed timestamps in logs/telemetry Given a user disconnects or consent is revoked When revocation is detected (≤ 5 minutes) Then all cached tokens and calendar data for that user are purged immediately Given calendar lists change infrequently When caching is applied Then calendar list TTL is configurable (default 15 minutes, range 5–1440 minutes) and respected
Rate Limiting, Backoff, and Idempotent Retries
Given the provider returns HTTP 429 or a Retry-After header When issuing subsequent requests Then the client applies exponential backoff with full jitter (base 1s, cap 64s) and honors Retry-After Given a transient 5xx error occurs When retry policy executes Then at most 5 retries are attempted before surfacing a clear, actionable error to the caller Given event create/update operations are performed When retries occur Then idempotency keys are used to prevent duplicate events across providers Given sustained rate limiting persists beyond 2 minutes When a simulation is requested Then the system uses last-known cached data per staleness rules and reports degraded mode via telemetry/UI
Time Zone and DST Normalization Fidelity
Given attendees span multiple time zones When computing candidate windows Then all times are normalized using the IANA TZ database and Windows time zones are deterministically mapped to IANA equivalents Given a DST transition day with missing or repeated local times When proposing slots Then nonexistent local times are excluded and repeated hours are disambiguated with correct UTC offsets Given tzdata updates are released When new rules become available Then the platform updates its time zone data within 72 hours and re-normalizes stored mappings Given an event crosses a DST boundary When displaying attendees’ local times Then start and end times reflect correct local wall times and provider APIs report matching UTC offsets
Security & Compliance: Encryption, Audit Logs, and Data Residency
Given any connector traffic is transmitted When requests/responses occur Then TLS 1.2+ is enforced and weak ciphers are disabled Given tokens, calendar metadata, and caches are stored When data is at rest Then it is encrypted using AES-256 or FIPS 140-2 validated cryptographic modules, with keys managed by KMS and automatic rotation at intervals ≤ 90 days Given an admin selects a data residency region When storing or processing cached calendar data and logs Then data remains within the selected region; cross-region transfers are blocked and logged with governance overrides Given calendar data is accessed (read/write/impersonation) When operations complete or fail Then an immutable audit log records actor, subject, operation, scope, timestamp, outcome, and request identifiers; logs are searchable, exportable (CSV/JSON), and retained per policy (minimum 90 days)
Equity Scoreboard Integration & Tie‑Breaking
"As a remote teammate, I want rebooking to account for past inconveniences so that meeting times remain fair over the long run."
Description

Integrate rebooking decisions with TimeMeld’s equity scoreboard to maintain rotation fairness and prevent repeated inconvenience for the same individuals or regions. Compute fairness deltas for each candidate and apply them as tie‑breakers in the selection algorithm. On confirmation, update scoreboard metrics, annotate the meeting with fairness context, and surface any accrued fairness debt to be repaid in future scheduling windows, keeping long‑term balance intact.

Acceptance Criteria
Fairness Delta Tie-Breaker Applied
Given a set of candidate slots where base_ripple_score differences are <= 0.01 When the selection algorithm evaluates candidates Then it computes total_fairness_delta for each candidate as the sum of attendee_fairness_delta weighted by role_weight and region_weight from the equity scoreboard And it selects the candidate with the lowest total_fairness_delta And if multiple candidates have equal total_fairness_delta within 0.001 Then it selects the earliest start_time in organizer local time And if still tied Then it selects the candidate with the lowest candidate_id lexicographically And it records the chosen candidate and all evaluated fairness_deltas in the decision log
Repeated Inconvenience Guard Within Rolling Window
Given an attendee has >= 1 inconvenience event in the past 14 days with inconvenience_score >= 0.7 And at least one candidate exists within 10% of the minimal ripple_cost that assigns this attendee an inconvenience_score < 0.7 When the algorithm selects a rebook slot Then it must not choose a candidate that assigns this attendee an inconvenience_score >= 0.7 Unless no candidate within 15 minutes of the target time meets ripple_cost within 10% of the minimum Then it may choose the minimal ripple_cost candidate but must append a fairness_debt entry for that attendee and region
Scoreboard Update on Rebook Confirmation
Given a rebook proposal is confirmed by the organizer When the confirmation event is processed Then the equity scoreboard is updated atomically with per-attendee rotation count, personal fairness_debt/credit adjustments, and regional aggregates And a meeting annotation is added summarizing prior_score, post_score, and fairness_delta for each attendee And an audit event equity_update.created is emitted with meeting_id and decision_key And the update is idempotent based on (meeting_id, confirmation_id) And no scoreboard changes occur for proposals that are simulated, expired, or canceled before confirmation
Fairness Debt Surfaced Post-Selection
Given a selected candidate generates non-zero fairness_debt entries When the selection result is returned Then the UI displays a fairness banner listing each attendee/region with debt > 0 and the first suggested repayment window And the API response includes fairness_debt[] with attendee_id/region_id, amount_points, and repayment_window_start/end And any attendee with amount_points >= 2.0 is labeled Repay Soon
Deterministic Outcome Under Identical Inputs
Given identical inputs (attendee set, calendars, configuration, equity scoreboard snapshot, target metadata) and a fixed random_seed When the selection algorithm runs multiple times Then it returns the same selected candidate_id and identical fairness_delta values And the decision log stores a decision_key hash of the inputs and tie-break path And no stochastic choice occurs without the provided random_seed
Explainable Decision and Audit Trail
Given a completed selection When an admin requests the fairness explanation via UI or API Then the system returns an explanation including per-attendee prior_score, post_score, fairness_delta, role_weight, region_weight, base_ripple_score, total_fairness_delta for all evaluated candidates, tie-break reason, and final rationale And the explanation and inputs snapshot are retained for at least 90 days And PII fields are redacted according to privacy settings

Equity Ledger Lock

Enforces rotation and burden limits at reschedule time with a clear preview of who gets earlier/later and how the change impacts the equity scoreboard. If a tradeoff is unavoidable, it offers auto-compensation (e.g., next-owner swap or future offset) before you confirm—preventing silent bias creep.

Requirements

Reschedule Policy Engine Enforcement
"As a remote team organizer, I want reschedules to be automatically checked against fairness and burden rules so that no one is repeatedly stuck with inconvenient times."
Description

Evaluate every reschedule action against workspace/team rotation rules and participant burden limits (max early/late minutes per period, quiet hours, protected days) before confirmation. Use attendee timezone profiles and historical load to score proposed times and generate compliant alternatives prioritized by TimeMeld’s ergonomics model. Block non-compliant choices, surface specific rule violations, and calculate tentative equity credits/debits against the Equity Scoreboard for the preview. Expose machine-readable validation results to the UI and API and support synchronous execution for organizer-initiated reschedules.

Acceptance Criteria
Block Quiet Hours and Protected Days at Reschedule
Given workspace/team policies define quiet hours and protected days per attendee, and the organizer initiates a reschedule When the organizer selects a proposed time that intersects any attendee’s quiet hours or protected day Then the engine returns decision=block and prevents confirmation And the result includes a violations array with an entry per violated rule containing: rule_code, rule_name, impacted_attendees[user_id, local_start, local_end], and evidence[timezone, local_date] And the UI/API receive at least 3 compliant alternatives within the requested scheduling horizon, sorted by ergonomics_score descending And each alternative’s attendees’ local times do not intersect quiet hours or protected days for any attendee
Enforce Max Early/Late Minutes Budget with Auto-Compensation
Given each attendee has max early_minutes and late_minutes budgets defined per rolling 7-day period and historical burden is recorded When the proposed time would cause any attendee’s early or late minutes to exceed their budget after application Then the engine returns decision=block with a violation detailing attendee_ids, before_totals, deltas, and projected after_totals And the result includes auto_compensation options: next_owner_swap and future_offset with required_minutes >= exceeded_minutes and a proposed window within the next 14 days And if the organizer selects an auto_compensation option, the follow-up validation returns decision=allow and reflects the applied compensation in the equity preview
Rotation Rule Compliance and Ownership Preview
Given a configured round-robin ownership rotation rule for the meeting series When a reschedule would break rotation order or repeat the current owner contrary to rule Then the engine returns decision=block with violation including current_owner, expected_next_owner, and rule_code=rotation And the preview payload shows before and after next_owners sequences (minimum length 3) and identifies the owner for the proposed slot And if the organizer selects the next-owner swap compensation, the revalidation returns decision=allow and the after sequence reflects the swap
Ergonomics-Scored Compliant Alternatives Generation
Given attendee timezone profiles and historical attendance/load are available When a non-compliant proposed time is evaluated Then the engine generates at least 5 compliant alternative slots within a 14-day window And each alternative includes: start_utc, end_utc, ergonomics_score in [0.0,1.0], attendance_uplift_pct, and per_attendee local_time preview And alternatives are sorted by ergonomics_score descending and all pass all active rules (zero violations)
Equity Credits/Debits Preview Consistency
Given a compliant proposed time or alternative is selected for preview When equity credits/debits are computed Then the preview includes per_attendee entries with user_id, minutes_early_delta, minutes_late_delta, credit_debit, and ownership_delta And the sum of all credit_debit values equals 0 and no ledger is committed until confirmation=true And UI tags each attendee as earlier, later, or neutral consistent with the minutes_*_delta signs
Machine-Readable Validation Result Contract
Given the Validation API is called for a reschedule evaluation When the request is processed Then the response is returned as JSON with schema_version="1.0" and fields: decision, reasons[], violations[], alternatives[], equity_preview, and timing_ms And for allow decisions, violations[] is empty and all alternatives[] (if present) are compliant; for block decisions, decision=block and violations[] has at least one entry with rule_code and impacted_attendees And the response time is <= 2000 ms at p95 for requests with up to 12 attendees and a 30-day search horizon
Synchronous Organizer Reschedule Execution and Idempotency
Given the organizer initiates a reschedule from the UI When the organizer selects a new time and requests validation Then the policy engine executes synchronously and returns a result within 1500 ms at p95 for meetings with up to 12 attendees And confirmation controls remain disabled until a decision=allow is received And if the same request_id is retried within 60 seconds, the engine returns an identical decision, reasons, and alternatives (idempotent)
Real-time Equity Impact Preview
"As an organizer, I want to see exactly how a new time affects each participant and the rotation before I confirm so that I can make an informed, fair decision."
Description

Present a live, pre-confirmation panel that shows per-attendee impact in minutes earlier/later, equity score deltas, and the next-owner rotation outcome for the proposed change. Highlight compliance status with badges (Compliant, Needs Compensation, Blocked) and annotate the specific constraints affected. Update instantly as the organizer drags a time, selects alternatives, or toggles attendees. Accessible in web and calendar add-ins, supports keyboard navigation and screen readers, and localizes time and date formats.

Acceptance Criteria
Per-Attendee Impact Preview
Given an organizer proposes a new time for an existing meeting and opens the Real-time Equity Impact Preview When the preview renders Then each included attendee shows name, ±minutes earlier/later (rounded to nearest minute) relative to their local time at the proposed date, and equity score delta (signed, one decimal) And the next-owner rotation outcome displays the next owner name and date based on the proposed change And any attendee with 0 minutes change and 0.0 score delta displays 0 with neutral styling And excluded attendees are not listed
Compliance Badge and Constraint Annotations
Given fairness constraints and burden limits are configured for the workspace When a proposed change is previewed Then the panel shows exactly one badge state from [Compliant, Needs Compensation, Blocked] And Blocked is shown if any hard rule is violated And Needs Compensation is shown if no hard rules are violated but fairness thresholds are exceeded for any attendee And Compliant is shown otherwise And the panel lists each triggered constraint with a short code and human-readable description And in Blocked state, the Confirm action is disabled and a tooltip explains which constraint blocks the change And badge colors meet WCAG AA contrast
Real-Time Update on Drag and Toggle
Given the preview panel is open When the organizer drags the proposed time on the calendar grid Then per-attendee minutes earlier/later, equity score deltas, next-owner rotation, and badge state update within 300 ms of the last input event And while the pointer is moving, the panel refreshes at least 5 times per second When the organizer toggles attendee inclusion or selects an alternative slot Then the same fields update within 300 ms of the interaction
Cross-Surface Parity (Web and Add-ins)
Given the organizer performs the same proposed change in the web app and in supported calendar add-ins When the preview is shown on each surface Then the per-attendee minutes earlier/later, equity score deltas, next-owner rotation, badge state, and constraint annotations are identical, allowing rounding differences of at most ±1 minute and ±0.1 score And all actions required to open and view the preview are available on each surface
Keyboard Navigation
Given the preview panel is open When using only the keyboard Then all interactive elements are reachable via Tab/Shift+Tab in a logical order and have visible focus indicators And attendee include/exclude toggles are actionable via Space or Enter And alternative slot selection is reachable and selectable via keyboard And Escape closes the panel without side effects And no keyboard traps are present
Screen Reader Accessibility
Given a screen reader is active When the preview panel opens Then it is exposed as a named region with an accessible name "Equity Impact Preview" And each attendee row has a role and label that includes the attendee name, minutes earlier/later, and equity score delta And the compliance badge is announced with its state and a summary of triggered constraints And when values change, a polite live region announces the updated badge and the top attendee changes And the panel conforms to WCAG 2.1 AA for semantics and non-text contrast
Localization and Timezone Handling
Given the organizer's locale and timezone are set When the preview renders Then all displayed times and dates are formatted according to the organizer's locale (including 12/24‑hour and day/month order) And per-attendee minutes earlier/later are computed using each attendee's timezone at the proposed date, accounting for daylight saving transitions And numeric formatting (minus sign, decimal separator) follows the organizer's locale And changing the organizer locale updates formats on next render
Auto-Compensation Suggestions
"As an organizer, I want the system to offer fair compensation options when perfect slots don’t exist so that I can proceed without introducing silent bias."
Description

When a compliant slot is unavailable or a slightly non-compliant time is selected, automatically propose compensation options such as next-owner swap, future offset credit/debit (minutes bank), or role-weighted burden adjustment. Simulate each option’s impact on the Equity Scoreboard, ensure hard caps aren’t breached, and default to the option that restores balance soonest. Allow one-click apply/compare, write chosen compensation as provisional ledger entries, and roll back on cancellation.

Acceptance Criteria
Non‑Compliant Selection Triggers Auto‑Compensation Suggestions
Given a user is rescheduling a meeting in TimeMeld And no fully compliant slot is available OR the selected time is within the configured soft non‑compliance tolerance When the user selects or requests that time Then the system generates compensation suggestions including next‑owner swap, minutes bank credit/debit, and role‑weighted burden adjustment when applicable And suggestions are computed and displayed within 1.5 seconds And any suggestion that would breach a hard cap is excluded from the list And if at least two valid suggestions exist, at least two are shown; otherwise a single valid suggestion is shown And each suggestion is labeled with its compensation type
Equity Scoreboard Impact Simulation and Preview
Given the suggestions panel is open for a reschedule When suggestions are shown Then each suggestion displays a preview including per‑participant delta minutes, earlier/later indication, projected equity score change, and next‑owner rotation impact And the preview includes a total equity variance change metric for the group And values in the preview match the simulated ledger outcome within ±1 minute per participant And any potential hard cap proximity (within 10% of cap) is visually indicated
Recommended Option Restores Balance Soonest
Given two or more valid compensation suggestions are available When the system ranks suggestions Then the top suggestion is marked Recommended and pre‑selected by default And the ranking minimizes time‑to‑balance across participants within the next two rotation cycles, breaking ties by lowest projected equity variance, then lowest added weekly burden, then least deviation from core hours And the ranking rationale is accessible via a tooltip on the Recommended label
One‑Click Compare and Apply Compensation
Given the suggestions panel is open When the user clicks Compare on any two suggestions Then a side‑by‑side scoreboard preview is displayed with synchronized participant ordering and metric highlighting When the user clicks Apply on a suggestion Then the selected suggestion is applied in a single click, the meeting time preview updates, and a confirmation banner appears And the apply action completes within 1 second and remains reversible until final confirmation
Provisional Ledger Entries and Rollback on Cancellation
Given a suggestion has been applied but the reschedule is not yet confirmed When the apply occurs Then provisional ledger entries are written with type=provisional, linked to the reschedule operation ID and meeting ID, and timestamped And the provisional entries adjust the simulated scoreboard but do not affect committed balances When the user cancels the reschedule Then all provisional entries for that operation are removed within 1 second and the scoreboard reverts with no residual effects And the system logs both the provisional write and rollback in the audit log
Hard Cap Enforcement in Suggestions
Given hard caps are configured in Equity Ledger Settings When generating suggestions for a non‑compliant or near‑compliant time Then any option that would breach a hard cap is not presented and is flagged in diagnostics And if no valid suggestion exists without breaching caps, the UI displays No compliant compensation available and disables Apply And the API returns 0 valid suggestions with reason codes indicating the cap(s) preventing suggestions
Policy Configuration & Guardrails
"As a workspace admin, I want to configure fairness rules and guardrails so that rescheduling enforces standards that match our team’s needs."
Description

Provide admin controls to define and version rotation cadence, max early/late budgets per person and per team, quiet hours, protected days, role-based weighting, and opt-out rules. Offer presets (e.g., Global Distributed, EU/US Overlap) and a simulator to test settings against recent meetings. Enforce effective dates, audit changes, and expose read-only policy via API to clients for consistent validation.

Acceptance Criteria
Policy Versioning, Effective Dates, and Auditing
Given an admin creates a new policy version with a future effective date, When the policy is saved, Then the system stores it as a draft with the specified effective_at timestamp and it does not affect scheduling until that timestamp. Given the current datetime is before the new policy’s effective_at, When meetings are scheduled or rescheduled, Then the previous effective policy version is applied and logged as the evaluator. Given the current datetime reaches or passes effective_at, When the next scheduling/rescheduling occurs, Then the new version becomes active and the version_id is included in decision logs and API responses. Given any policy create/update/delete action, When saved, Then an audit record is written including actor, org, before/after diff, reason, ip_address, timestamp, and policy version_id. Given an admin attempts to backdate effective_at earlier than now, When saving, Then the system blocks the change unless the actor has an explicit override permission; if overridden, a mandatory reason is captured and flagged in audit logs.
Rotation Cadence Configuration and Reschedule Enforcement
Given rotation cadence is configured (e.g., weekly, biweekly, custom sequence), When a meeting is rescheduled, Then the proposed next owner is calculated from the active policy version and cadence at reschedule time and displayed prior to confirmation. Given a rotation lock window (e.g., 24 hours pre-meeting) is configured, When a reschedule occurs within the lock window, Then ownership does not rotate, a rationale is shown, and the non-rotation is logged to the audit trail. Given a user attempts to manually pick an owner that violates the configured cadence, When confirming, Then the action is blocked unless the user has override permission and provides a justification which is recorded. Given ownership changes due to reschedule, When confirmation occurs, Then the equity scoreboard preview updates to show delta by participant and will persist the change post-confirmation.
Early/Late Budgets with Auto-Compensation on Reschedule
Given per-user and per-team early/late minute budgets are configured for a rolling window (e.g., 90 days), When generating candidate reschedule times, Then options that would exceed any participant’s remaining budget are flagged or filtered and the budget impact is shown per option. Given all feasible options exceed at least one budget, When the user selects auto-compensation, Then the system proposes compensation strategies (e.g., next-owner swap, future offset) with quantified impact and links the selected plan to the meeting upon confirmation. Given a reschedule is confirmed, When the new time is saved, Then early/late debits/credits are applied within 60 seconds to individuals and aggregated to team budgets, and the equity scoreboard reflects the changes. Given a compensation plan was applied, When the compensating event occurs (e.g., future offset executed), Then the system reconciles the planned credit and marks the plan as completed in the audit log.
Quiet Hours and Protected Days Enforcement
Given quiet hours and protected days are configured per participant timezone or locale, When generating reschedule suggestions, Then any slot overlapping a participant’s quiet hours or protected days is excluded by default and the count of excluded slots is shown. Given a user with override permission attempts to include a conflicting slot, When they proceed, Then the system requires explicit acknowledgment, captures a reason, and lists impacted participants; the confirmation writes an audit entry with participant_ids and conflict types. Given multiple participants have non-overlapping quiet hours, When suggestions are computed, Then the optimization favors ergonomic windows minimizing total quiet-hour conflicts according to policy weighting.
Role-Based Weighting, Presets, and Simulator Outcomes
Given an admin applies a preset (e.g., Global Distributed, EU/US Overlap), When saving, Then the preset parameters are materialized into the policy version and labeled with preset_id and any local overrides. Given role-based weighting is configured, When scoring candidate meeting times in the simulator, Then higher-weight roles contribute proportionally more to the ergonomic score and the score breakdown per role is displayed. Given the simulator is run against the last N meetings (default 30, configurable 1–200), When executed, Then it outputs predicted owner rotations, attendance windows, early/late budget impacts, and a delta versus the current active policy, all exportable as CSV. Given a simulator run completes, When results are viewed, Then the policy version_id, dataset window, assumptions, and timestamp are included for reproducibility.
Read-Only Policy API Access and Caching
Given a client with a valid org-scoped API token requests GET /v1/policy?version=current, When authorized, Then the server returns HTTP 200 with a read-only JSON document containing version_id, effective_at, presets, budgets, weights, quiet hours, protected days, opt-out rules, and evaluation parameters; no admin PII is included. Given a client requests a specific version via GET /v1/policy/{version_id}, When the version exists within the client’s org, Then HTTP 200 with the document is returned; otherwise HTTP 404 is returned. Given responses include ETag and Last-Modified, When the client sends If-None-Match or If-Modified-Since for an unchanged document, Then the server returns HTTP 304 with no body. Given an OpenAPI schema is published, When the API response is validated against the schema in CI, Then any schema regression fails CI and triggers an alert.
Opt-Out Rules and Eligibility Controls
Given opt-out rules can be defined per user/role/team with start/end times and reasons, When scheduling or rescheduling, Then opted-out entities are excluded from owner rotation and budget calculations for the effective period. Given a user requests a temporary opt-out, When policy requires approval, Then the request remains pending until an admin approves; upon approval the effective window is enforced and logged with approver and reason. Given an opt-out is nearing expiration, When 24 hours remain, Then the system notifies the user and relevant admins and automatically reinstates eligibility at expiration with an audit entry.
Equity Ledger & Audit Trail
"As a compliance reviewer, I want a complete audit trail of how rescheduling decisions were made so that I can verify fairness and address exceptions."
Description

Maintain an immutable ledger of reschedule evaluations, chosen slots, equity deltas, compensation entries, ownership rotations, and any overrides with reason codes. Include actor IDs, timestamps, rule versions, and before/after snapshots for traceability. Provide export (CSV/JSON), admin review filters, and anomaly alerts (e.g., repeated overrides benefiting the same person). Respect data retention settings and PII minimization.

Acceptance Criteria
Reschedule Decision Is Fully Logged
- Given a user initiates a reschedule and confirms a new slot, When the system finalizes the reschedule, Then a ledger entry is appended capturing: meeting_id, request_id, previous_slot_utc, new_slot_utc, per_participant_equity_delta (unit, value), compensation_entries (type, value, target), ownership_rotation_result, overrides (flag, reason_code, actor_id), initiator_actor_id, confirmer_actor_id, created_at_utc, evaluation_completed_at_utc, rule_version, before_snapshot, after_snapshot, and ledger_id. - Given the ledger entry is written, Then the read API returns exactly these fields and values; And ledger_id is unique across the ledger. - Given malformed or partial data, When a write is attempted, Then the API responds 400 with validation errors and no ledger entry is created.
Ledger Is Append-Only and Tamper Evident
- Given an existing ledger entry, When a client attempts to update or delete it via API, Then the request is rejected with 403; And no row is changed. - Given a direct database attempt to modify a row, Then database constraints/triggers prevent the change and log a security event. - Given an error is discovered, When a correction is needed, Then a new correction entry is appended referencing original ledger_id with correction_reason and delta-only fields; And the original entry remains unchanged. - Given N sequential entries for a meeting series, Then each stores content_hash and prev_hash; And recomputing the chain verifies integrity end-to-end.
CSV/JSON Export With Field Coverage and Filtering
- Given an admin selects date_range, team_ids, meeting_series_ids, and format=CSV, When export is requested, Then a file is generated within 60 seconds for up to 100k entries and includes all required fields with header names matching the data dictionary. - Given format=JSON, Then the export returns a JSON array with the same fields and data types. - Given PII minimization is enabled, Then exports contain actor_id only (no names, emails, or timezone strings). - Given a filter on override_reason_code in [MANUAL_EXCEPTION, URGENT_OUTAGE], Then only matching entries are included.
Admin Review Filters and Performance
- Given an admin applies filters (actor_id, beneficiary_actor_id, rule_version, equity_delta>=threshold, has_override=true, date_range), When the search is executed, Then the result count and list match the filter and return within 2 seconds for up to 10k entries. - Given pagination parameters (page, page_size), Then results are chunked deterministically and stable across pages during the same query session. - Given sort by created_at_utc desc, Then the first page contains the newest entries.
Anomaly Alerts for Repeated Beneficiary Overrides
- Given the same actor benefits from overrides >=3 times or accrues equity_delta_benefit >= 2 hours within a rolling 30 days, When the latest qualifying entry is appended, Then an anomaly alert is created with summary, actor_id, counts, time_window, and deep-link to filtered review. - Given alert destinations are configured (email, webhook), Then alerts are delivered within 60 seconds and deduplicated to at most 1 alert per actor per 24 hours per rule. - Given an admin resolves an alert, Then subsequent alerts require new qualifying activity to trigger again.
Data Retention and PII Redaction
- Given retention_days=180, When an entry’s age exceeds 180 days and no legal_hold is active, Then PII fields remain minimized (actor_id only) and snapshots are redacted of personal details; And entry remains for aggregate integrity with tombstone markers for redacted fields. - Given a legal_hold is applied to a meeting_series_id, Then no redaction/purge occurs until the hold is removed. - Given an export request outside the retention window, Then redacted fields are absent and clearly marked as null/tombstoned.
Rule Versioning and Replayability
- Given a stored ledger entry with rule_version and config_hash, When the evaluation is replayed using stored inputs, Then the output matches the stored chosen_slot, equity_deltas, and compensation entries. - Given the rule engine version changes, When new reschedules occur, Then new entries record the new rule_version; And filters by rule_version return the correct subsets. - Given missing snapshot data, When replay is requested, Then the API returns 422 with a message indicating which inputs are missing.
Calendar Gate & Participant Notifications
"As a participant, I want clear notifications about how reschedules affect me and what compensation applies so that I can consent or raise concerns promptly."
Description

Integrate with Google and Microsoft calendars to gate event updates until Equity Ledger Lock passes. Create or update invites only after a compliant or compensated decision is confirmed. Send participant-specific notifications summarizing the change, personal early/late shift, applied compensation, and a time-bound appeal/decline option. Reconcile responses back into the ledger, retry on transient failures, and fall back with organizer prompts if consent windows expire.

Acceptance Criteria
Gate Calendar Update on Equity Check Result
- Given a reschedule is initiated in TimeMeld, When Equity Ledger Lock returns Compliant or Compensated and the decision is confirmed, Then the system creates or updates the event via the connected calendar provider API. - Given a reschedule is initiated in TimeMeld, When Equity Ledger Lock returns Non-compliant and no compensation is selected, Then no calendar provider API calls are made and the Send Updates control is disabled. - Given a compliant or compensated decision is confirmed, When the calendar update succeeds, Then an audit record is stored with decisionId, providerEventId, provider, status=success, and timestamp. - Given a compliant or compensated decision is confirmed, When the calendar update fails with a non-transient error, Then no ledger state is advanced, the user is shown a blocking error, and an audit record is stored with status=failure and errorCode.
Participant Notification Personalization and Content
- Given an event change is confirmed, When notifications are dispatched, Then each participant receives a message that includes old start and end times, new start and end times in the participant's local timezone, the early/late delta in minutes relative to their local time, the applied compensation summary, and an appeal or decline link with an absolute expiry timestamp. - Given a participant is the next owner after rotation, When the notification is generated, Then the message explicitly states the ownership change and their equity scoreboard impact. - Given notifications are generated, When sent to each participant, Then no other participants' personal deltas, timezones, or compensation details are included in the message. - Given a participant's personal time does not shift, When the notification is generated, Then the message states no personal time shift and omits the appeal option.
Time-Bound Appeal and Ledger Reconciliation
- Given a participant receives an appeal or decline link, When they respond before the expiry timestamp, Then the response is recorded with participantId, decision, timestamp, and the equity ledger is updated according to policy. - Given a participant declines within the window, When the event requires their attendance, Then the event status is set to Needs Attention and the organizer is notified with options to compensate or propose alternatives. - Given a participant appeals citing burden, When an auto-compensation rule is applicable, Then the system applies the compensation, updates the ledger, and sends updated notifications within 5 minutes. - Given multiple responses arrive, When reconciliation completes, Then the equity scoreboard shows a single consolidated result per participant without duplication and the audit trail lists all responses.
Transient Failure Retry and Idempotency
- Given a calendar provider or email service returns a transient error (HTTP 429, 5xx, or timeout), When the operation is retried, Then the system uses exponential backoff with jitter for up to 5 attempts within 10 minutes. - Given retries are attempted, When an operation eventually succeeds, Then only one calendar update and one notification per participant are effected by using idempotency keys or deduplication tokens. - Given all retries are exhausted, When the operation still fails, Then the organizer receives a single consolidated failure notification containing the impacted participants or providers and a Retry Now action.
Consent Window Expiry Organizer Fallback
- Given an appeal or decline window is active, When the expiry timestamp passes with no response from a participant, Then the system prompts the organizer to choose keep as is, apply default compensation, or re-propose times before any further updates are sent. - Given required attendees remain unresponsive at expiry, When the organizer does not act within 24 hours of the prompt, Then the event is placed on hold, stale links are invalidated, and an escalation email is sent to the organizer. - Given the organizer selects a fallback option, When confirmed, Then the calendar invites, notifications, and ledger are updated consistently and previous appeal links are invalidated.
Google and Microsoft Calendar Update Compliance
- Given Google Calendar is connected, When a compliant or compensated decision is confirmed, Then the event is created or updated with correct attendees, start and end times, timezone, description including equity summary snippet, and meeting join details preserved. - Given Microsoft 365/Outlook is connected, When a compliant or compensated decision is confirmed, Then the event is created or updated with the same fidelity as Google including attendees, times, timezone, description equity summary snippet, and join details preserved. - Given updates are blocked due to non-compliance, When the organizer attempts to send from TimeMeld, Then the action is blocked and the UI displays the Equity Ledger Lock reason and required compensation before enabling Send. - Given a mixed-attendee event using cross-provider invites, When updates are sent, Then all attendees receive standards-compliant iCalendar updates reflecting the new time and the ownership change in the event description.

Quorum Soft-Hold

Puts temporary holds on top candidate times and gathers one-tap approvals from required roles via Slack/email. The first slot to reach quorum auto-confirms; if key people decline, Slipstream falls back to the next fair option—speeding alignment without calendar ping-pong.

Requirements

Role-Based Quorum Rules Engine
"As an organizer, I want to define which roles and how many approvals are required for a meeting slot so that the first acceptable time can be auto-confirmed without waiting on every invitee."
Description

Provides configurable quorum policies that define which roles (e.g., PM, Eng Lead, Ops) and how many approvals are required for a slot to be confirmed. Supports must-have vs. optional attendees, per-meeting templates, and dynamic mapping of invitees to roles. Evaluates approvals per candidate slot, respects out-of-office and delegation rules, and exposes a clear quorum state for each option. Integrates with TimeMeld’s scoring model so that quorum checks run against the highest‑ranked ergonomic windows first.

Acceptance Criteria
Per-Meeting Quorum Policy Configuration and Validation
Given a meeting template with role quorum rules (role name, must_have flag, required_count) When the template is saved Then the rules engine validates that required_count is a non-negative integer and role names are unique within the template And Given validation fails When saving Then the engine rejects the save with a list of field-specific errors and no policy is stored And Given validation passes When retrieving the template Then the stored policy matches the submitted configuration exactly
Must-Have vs Optional Enforcement and Numeric Aggregation
Given a policy that sets must-have role R1 with required_count = N and optional role R2 with required_count = M When evaluating approvals for a candidate slot Then quorum is achieved only when approvals for R1 >= N, regardless of R2 counts And Given multiple approvals from invitees mapped to R1 When approvals reach N Then additional approvals for R1 do not change quorum state but are recorded And Given zero approvals for a must-have role When evaluating Then quorum_state is "partial" and not "quorum_met"
Dynamic Invitee-to-Role Mapping and De-duplication
Given per-meeting role overrides and directory role attributes When mapping invitees to roles Then per-meeting overrides take precedence, directory roles fill remaining mappings, and unmapped invitees are classified as "no_role" and do not count toward quorum And Given an invitee mapped to multiple roles When the invitee approves a slot Then the approval is counted once toward a single role and is not double-counted across roles
Per-Slot Quorum Evaluation and State Transitions
Given multiple candidate slots under soft hold When approvals and declines are received over time Then the engine updates each slot independently and transitions quorum_state among {pending, partial, quorum_met, blocked_decline, expired} according to approvals and timeouts And Given a decline from any invitee in a must-have role for a slot with no delegate When processed Then the slot quorum_state becomes "blocked_decline" and it cannot reach "quorum_met"
Out-of-Office and Delegation Handling
Given a must-have invitee is marked out-of-office for the candidate slot and a delegate is configured for that invitee When the delegate approves Then the approval satisfies the invitee's role requirement for that slot And Given a must-have invitee is out-of-office and no delegate is configured When evaluating the slot Then the slot quorum_state is "blocked_ooo" and cannot reach "quorum_met" And Given both the invitee and their delegate approve When counting Then only one approval counts toward the role requirement
Quorum State Exposure and Role Breakdown
Given candidate slots exist When the API is queried for quorum status Then each slot response includes quorum_state and, per role, {required_count, approved_count, outstanding_count} that are numerically consistent And Given a Slack or email notification is generated for a candidate slot When rendered Then it displays the current quorum_state and explicitly lists outstanding must-have roles
Scoring Model Integration and Confirmable Flag
Given candidate slots each have an ergonomic score from the TimeMeld scoring model When the engine evaluates quorum Then it processes slots in descending score order and marks the highest-scored slot that reaches "quorum_met" with confirmable = true And Given two slots reach "quorum_met" in the same evaluation cycle with identical scores When selecting the confirmable slot Then the engine applies a deterministic tiebreaker (earliest start time, then earliest quorum_met timestamp) and marks only one as confirmable
Multi-Channel One-Tap Approvals (Slack & Email)
"As a busy attendee, I want to approve or decline proposed times with one tap in Slack or email so that I can respond quickly without opening a calendar UI."
Description

Delivers interactive Slack messages and actionable emails showing local-time candidate windows with approve/decline actions and optional "prefer" feedback. Uses signed links and Slack interactivity to attribute responses without login friction, supports mobile, and records decisions with timestamps. Includes contextual details (agenda, hold expiration) and lightweight reminders before hold expiry. Handles rate limiting, retries, and message updates as slot state changes.

Acceptance Criteria
Slack One‑Tap Approval Delivery and Recording
Given an open hold with candidate slots and a required participant mapped to a Slack user, When notifications are triggered for that participant, Then the participant receives a single Slack DM or channel message within 5 seconds containing interactive Approve, Decline, and Prefer actions for each candidate slot and showing agenda and hold expiration. Given the Slack message is delivered, When the participant taps Approve on a slot, Then the system attributes the approval to that participant and role without additional login, records a UTC timestamp to the second, updates the message to reflect the approval, and prevents duplicate approvals for that slot. Given the Slack message is delivered, When the participant taps Decline on a slot, Then the decline is recorded with a UTC timestamp, the message reflects the decline state, and the slot’s buttons are disabled for that participant to avoid repeated actions. Given the Slack message is delivered, When the participant taps Prefer on a slot, Then a non-binding preference is recorded (does not count toward quorum), is visible in the message, and can be updated by the participant by choosing Prefer on a different slot (previous preference is cleared). Given a participant repeats the same action for a slot, When a duplicate action request is received within any time window, Then the operation is handled idempotently and no additional records are created.
Email Signed-Link One‑Tap Attribution
Given an open hold with candidate slots and a participant with a valid email address, When notifications are triggered, Then the participant receives an actionable email within 60 seconds containing Approve, Decline, and Prefer buttons per slot implemented as unique signed, single-use links and showing agenda and hold expiration. Given the participant clicks an Approve link, When the signature is valid and the link is unexpired, Then the system records the approval with the participant identity and role without requiring login, stores a UTC timestamp to the second, displays a confirmation page within 2 seconds, and marks the link as consumed. Given the participant clicks a Decline link, When the signature is valid and the link is unexpired, Then the system records the decline with a UTC timestamp, displays a confirmation page, and marks the link as consumed. Given the participant clicks a Prefer link, When the signature is valid and the link is unexpired, Then the system records a non-binding preference for the slot and displays a confirmation page. Given a signed link is tampered with, expired (hold expired), or already consumed, When the link is opened, Then no new action is recorded and an informative state page (expired or already-processed) is shown within 2 seconds.
Accurate Local‑Time Rendering of Candidate Windows
Given participants reside in different time zones, When Slack messages and emails are generated, Then each candidate slot is rendered in the recipient’s local time zone with date and time labels and includes an explicit “Your time” indicator. Given the participant’s time zone is available from Slack profile or account settings, When rendering candidate slots, Then that time zone is used; otherwise a default time zone from the participant’s account is used, and if none exists, UTC is used. Given a candidate slot overlaps a daylight saving time transition for the recipient, When rendering, Then the time is shown using the correct DST offset for that date in the recipient’s IANA time zone. Given a recipient opens the email or Slack message on a device set to a different time zone than their account time zone, When a web confirmation page is displayed after a click, Then the page clearly shows both the slot in the participant’s account time zone and the device-local time to avoid ambiguity.
Mobile‑Friendly One‑Tap Interactions
Given a participant views the Slack message on iOS or Android, When they tap an Approve, Decline, or Prefer action, Then the action completes with a confirmation within 3 seconds on a 3G/slow‑LTE connection and the buttons have a minimum 44×44 px touch target. Given a participant opens the actionable email on a mobile client (Gmail, Apple Mail, Outlook mobile), When they tap any action button, Then the deep link opens in the default mobile browser and the confirmation page is responsive with readable text and tappable controls without horizontal scroll. Given a participant has dark mode enabled, When viewing the email or confirmation page, Then text maintains a minimum 4.5:1 contrast ratio and buttons remain visible and tappable. Given a participant uses a screen reader on mobile, When interacting with action buttons, Then each button has an accessible name that includes the slot local time and action (e.g., “Approve Tuesday 3 PM”).
Contextual Details and Reminder Before Hold Expiry
Given an open hold, When Slack messages and emails are generated, Then they include the meeting agenda summary and the exact hold expiration timestamp. Given a participant has not responded to any slot, When the hold has 10 minutes remaining until expiration, Then the participant receives a single lightweight reminder via their original channel (Slack or email) that includes current slot states and the time remaining. Given a participant submits any action (Approve, Decline, Prefer) on any slot, When reminder time is reached, Then no reminder is sent to that participant. Given a hold is confirmed or canceled before the reminder threshold, When reminder time would have occurred, Then no reminders are sent and prior messages are updated to show the final state.
Real‑Time Slot State Updates and Quorum Effects
Given a participant takes an action that changes a slot’s state (e.g., reaches quorum or loses a key approval), When the state changes, Then all previously sent Slack messages and the confirmation web pages reflect the new state within 10 seconds and disable actions that are no longer valid. Given a slot reaches quorum first, When auto‑confirmation occurs, Then recipients’ Slack messages and emails update to show the slot as Confirmed, all other slot actions are disabled, and late clicks on obsolete links return an already‑confirmed state page without recording new actions. Given a key participant declines a slot, When Slipstream fallback selects the next fair option, Then messages reflect the updated candidate list and any removed slot actions are disabled within 10 seconds. Given a hold expires without confirmation, When expiration occurs, Then messages show Hold Expired and all actions are disabled; clicking any prior link shows an expired state page.
Rate Limiting, Retries, and Idempotency
Given Slack API rate limiting (HTTP 429) is encountered, When sending messages or updates, Then the system honors Slack’s Retry‑After header, retries with exponential backoff up to 5 attempts, and ensures no duplicate messages via idempotency keys. Given transient email provider failures occur (5xx), When sending actionable emails, Then the system retries up to 3 times with exponential backoff and deduplicates sends via a stable message identifier to prevent duplicates. Given the action processing service experiences a transient outage, When a user clicks an action link or Slack button, Then the request is accepted, queued, processed within 60 seconds of service recovery, and the user sees a non‑blocking “processing” confirmation. Given the same action is received more than once due to retries or user double‑clicks, When processing, Then the operation is idempotent and only one decision record exists per participant per slot per action. Given any notification send or action processing attempt, When it completes, Then an audit log entry is written with participant, channel, slot, action, timestamp, and outcome (success/failure) for troubleshooting.
Calendar Soft-Hold Placement & Lifecycle
"As an organizer, I want TimeMeld to place temporary holds on the best candidate times across calendars so that those slots remain available while approvals are gathered."
Description

Places temporary, uniquely identifiable holds on top candidate slots across required attendees’ Google Workspace and Microsoft 365 calendars using tentative events or placeholders. Applies a configurable TTL, prevents duplicate or overlapping holds, and respects calendar privacy settings. Automatically extends, releases, or converts holds based on quorum outcomes while guaranteeing cleanup on expiry or cancellation. Provides visual indicators and a dedicated hold summary for organizers.

Acceptance Criteria
Soft-Hold Creation on Candidate Slots (Google & Microsoft)
Given an organizer selects at least two candidate time slots and required attendees with a mix of Google Workspace and Microsoft 365 accounts And a hold prefix and a TTL are configured for the scheduling session When the organizer initiates soft-hold placement Then a tentative placeholder event is created on each required attendee’s default calendar for each candidate slot And each placeholder reserves the time (busy/opaque or ShowAs=Tentative per provider) without sending a confirmed invitation And each placeholder contains a unique holdId and schedulingSessionId stored in provider-supported private/extended properties And if a placeholder with the same holdId already exists, it is updated in-place and no duplicate is created
Configurable TTL and Auto-Expiry Cleanup
Given holds are placed with a TTL of 2 hours When the TTL elapses without quorum and without manual or automatic extension Then all related placeholders are removed from every attendee’s calendar within 120 seconds And the organizer’s hold summary marks the session and affected slots as Expired with a timestamp And querying provider APIs for the holdId returns no remaining events
Quorum-Driven Conversion, Release, and Auto-Extension
Given required roles are defined and approvals are collected per candidate slot When the first candidate slot reaches quorum according to the role rules Then its placeholders are converted into a single confirmed meeting on all required attendees’ calendars And placeholders for all other candidate slots in the same session are removed within 120 seconds And the confirmed meeting references the original holdId and schedulingSessionId in private metadata When any candidate slot is within 10 minutes of TTL expiry and at least 80% of required roles have approved Then its TTL is automatically extended by the configured extension window and the new expiry is visible in the organizer UI and event metadata
Privacy-Respecting Hold Placement
Given some attendees’ calendar sharing is set to Private or limited details When soft-holds are placed Then other viewers of those calendars see only Busy blocks (or provider-equivalent minimal detail) with no descriptive content or attendee list And the organizer and the event owner can see the hold title and context per internal policy And holdId, roles, and session metadata are stored only in private or extended properties not exposed to other calendar viewers
Duplicate and Overlap Prevention and Idempotency
Given an attendee has overlapping candidate windows or placement is triggered multiple times for the same session When soft-hold placement runs Then no two holds overlap for the same attendee and time window within the same session And re-running placement for the same session and candidates creates no additional placeholders (idempotent) And attempts to create a duplicate or overlapping hold are skipped and recorded in the audit log with counts
Organizer Visual Indicators and Hold Summary
Given holds exist for a scheduling session When the organizer opens TimeMeld Then each candidate slot shows visual indicators including current approval count versus quorum, TTL countdown, hold state, and provider icon And a dedicated hold summary view lists each slot with holdId, expiry time, approval status by required role, and last activity timestamps And from the summary the organizer can extend TTL, release holds, or manually convert a slot, and the action propagates to all calendars within 120 seconds
Guaranteed Cleanup on Cancellation
Given an organizer cancels the scheduling session before quorum is reached When the organizer confirms cancellation Then all soft-holds for that session are removed from all attendee calendars within 120 seconds And the hold summary records the cancellation with timestamp and counts of holds removed And querying provider APIs for the session’s holdIds returns no remaining events
Auto-Confirm & Hold Revocation Orchestration
"As an organizer, I want the first slot that meets quorum to auto-confirm and all other holds to be withdrawn so that we finalize quickly and avoid confusion."
Description

When a candidate slot reaches the defined quorum, atomically converts that slot’s holds into a confirmed meeting, dispatches final calendar invites, and revokes all other active holds. Ensures idempotent operations and concurrency safety in case of near-simultaneous approvals. Sends confirmation notifications via Slack/email, updates the meeting record, and syncs with TimeMeld’s equity scoreboard to track scheduling burden and rotation.

Acceptance Criteria
Atomic Quorum Conversion and Hold Revocation
Given a candidate slot has active holds and a defined quorum threshold And no other slot is confirmed for this meeting When approvals received cause the slot to reach quorum Then the system confirms exactly that slot atomically And converts its holds to final invitations with a single meeting UID And transitions all other active holds for this meeting to revoked status And no other slot remains in held or tentative status for this meeting And all state changes share a single operationId and commit together And the end state is observable within the system within 10 seconds
Concurrency Control on Near-Simultaneous Approvals
Given two or more candidate slots receive approvals within 250 ms of each other And each would meet quorum absent locking When the system evaluates quorum under concurrent load Then exactly one slot is confirmed using a deterministic tie-breaker: earliest quorum timestamp, then lowest slotId And all other slots’ holds are revoked And no duplicate confirmations occur even under >=50 parallel approval events And external observers never see more than one confirmed slot at any point (linearizability)
Idempotent Retries and Duplicate-Safe Operations
Given an approval event is delivered multiple times due to retries or network duplication When the orchestration processes events with the same idempotency key Then the meeting remains a single confirmed event with the same meeting UID And no additional calendar events or invites are created And notifications are not re-sent more than once per recipient for the same confirmation And the final persisted state is identical regardless of 1 or many duplicate deliveries And duplicate requests return 200 OK with a reference to the original operationId
Confirmation and Revocation Notifications
Given a slot is confirmed by quorum When orchestration completes the transaction Then all required and optional invitees receive a confirmation via their configured channel(s) (Slack and/or email) And holders of other candidate slots receive a revocation/cancellation notice And messages include final date/time with timezone, conferencing link, and calendar attachment/ICS link And delivery succeeds within 60 seconds for the 95th percentile And no recipient receives more than one confirmation for the same event And notifications are sent only after the commit succeeds
Meeting Record Update and Audit Logging
Given a meeting is auto-confirmed When persistence is updated Then the meeting record shows status=confirmed, confirmedAt, finalSlotId, quorumDetails (roles/approvers), and meetingUID And an audit log entry includes operationId, actor=system, approvedBy list, revokedHoldIds, and notification dispatch results And API reads reflect these updates within 5 seconds (read-after-write) And the API returns a new version/etag so clients can detect the change
Equity Scoreboard Sync and Single-Burden Increment
Given a meeting is auto-confirmed When orchestration completes Then the equity scoreboard increments scheduling burden for the owning role/person exactly once And ownership rotation state is advanced according to policy And the scoreboard reflects the update to viewers within 10 seconds And retries do not produce multiple increments for the same operationId
Fallback Selection & Fairness Preservation
"As a cross-timezone team member, I want declined slots to trigger the next fair option automatically so that we don’t repeatedly schedule at inconvenient times."
Description

If key attendees decline or quorum becomes impossible for a held slot, automatically promotes the next best candidate according to timezone-weighted ergonomics and the equity rotation model. Reissues holds, carries forward participant preferences, and avoids repeatedly placing inconvenient times on the same individuals. Tracks attempt history, caps retry cycles, and escalates with a summary if no option can reach quorum by a defined deadline.

Acceptance Criteria
Auto-Promote Next Candidate After Decline or Timeout
Given a held slot within a Quorum Soft-Hold thread and required roles defined And at least one required attendee declines or the hold timer elapses without reaching quorum And at least one alternative candidate remains When the system evaluates fallback Then it selects the next candidate using the configured composite score (timezone-weighted ergonomics + equity rotation) And promotes it within the configured promotion SLA And reissues soft-holds and one-tap approvals via Slack/email to all required roles for the new candidate And releases calendar holds for the superseded slot per the configured hold-removal SLA And posts a reasoned update in the thread indicating decline/timeout and the promoted time
Carry Forward Preferences and Constraints to New Holds
Given participant hard constraints (work hours, DND windows, blackouts) and soft preferences captured for the thread When a new candidate is promoted Then the candidate satisfies 100% of hard constraints for all required attendees And the selected candidate’s aggregate soft-preference score is within the configured tolerance of the maximum score among remaining candidates And prior per-participant prefer/avoid choices are pre-selected in the new one-tap UI And any slot previously declined for a hard-constraint reason is never re-proposed in subsequent rounds of this thread
Fairness Preservation Across Fallbacks
Given the equity rotation model and per-attendee ergonomic score for each candidate When choosing a fallback candidate Then no attendee is assigned a time below the configured ergonomic threshold more than once within the rolling fairness window configured for this team Unless no quorum-capable candidate exists above that threshold before the deadline, in which case the selection proceeds and fairness debt is recorded for affected attendees And the selection summary includes the fairness impact and updated rotation state
Detect Quorum Impossibility and Skip
Given a held candidate and the set of required roles When |confirmed| + |pending but available| < |required roles| for that candidate Or any required role has only declines on that candidate Then the candidate is marked impossible, its holds are released within the configured hold-removal SLA, and the next candidate is promoted per fallback logic And an impossibility notice with per-role counts is posted to the thread
Retry Cap and Deadline-Based Escalation
Given a configured retry cap and quorum deadline for the thread When the number of promotions equals the retry cap without reaching quorum, or the current time reaches the deadline Then the system halts further promotions and sends an escalation summary via Slack/email to the organizer and required-role owners And the summary includes attempt history, reasons for each fallback, current fairness debt, and the top remaining viable options (if any) And the thread state is marked Escalated
Attempt History and Audit Trail
Given any fallback event (promotion or impossibility) When the event occurs Then an immutable history entry is stored with timestamp, candidate time (ISO 8601 with timezone), composite score components, quorum counts, reason code, notifications sent, holds applied/removed, and fairness impact And the history is retrievable via API and in-thread UI for at least 30 days And entries are ordered chronologically and cannot be edited, only appended
Conflict Detection & Live Recalculation
"As an organizer, I want TimeMeld to detect new conflicts while holds are active and adjust candidate slots automatically so that we avoid last-minute surprises."
Description

Continuously monitors calendars for changes during the hold window and invalidates candidate slots that gain conflicts for must-have attendees. Recalculates the candidate set and quorum viability in near real time using push notifications and periodic polling, updating participants and organizers as state changes. Ensures that approvals tied to invalidated slots are clearly communicated and redirected to the next viable option.

Acceptance Criteria
Invalidate Held Slot on Must‑Have Conflict
Given an active hold window with candidate slots and defined must‑have roles And a candidate slot S_k is currently viable and accepts approvals When a new busy event overlapping S_k is added to any must‑have attendee’s calendar Then the system detects the conflict via push within 20 seconds or via polling within 60 seconds And marks S_k as Invalid with reason "Must‑have attendee conflict" And blocks further approvals on S_k and prevents auto‑confirm for S_k And updates Slack/email hold cards and the organizer dashboard to reflect the invalid status within 10 seconds of detection
Redirect Approvals from Invalidated Slot
Given approvals have been recorded for slot S_k prior to invalidation When S_k becomes invalid due to a newly detected conflict Then all prior approvals for S_k are preserved with status Superseded (read‑only) in the audit log And approvers receive a one‑tap prompt to re‑apply their approval to the next viable slot as determined by the recalculation engine And no superseded approval counts toward quorum for any slot until explicitly re‑applied by the approver And the organizer is notified of the redirection status and remaining quorum gap for the suggested slot
Auto‑Recalculate Quorum and Confirm First to Quorum
Given a defined quorum by required roles and a set of candidate slots under hold When any approval, decline, conflict addition/removal, or availability change is processed Then the engine recalculates slot viability and rankings within 5 seconds And if any slot satisfies quorum with all must‑have roles conflict‑free, it is auto‑confirmed immediately And confirmation calendar invites are sent to all attendees within 10 seconds of auto‑confirm And holds on all other slots are released and their approval actions become non‑actionable within 10 seconds
Hybrid Push/Poll Reliability and Latency
Given connected calendars using push webhooks (e.g., Google/Microsoft) and others using polling When calendar changes occur during an active hold window Then 99% of push‑detected changes are processed end‑to‑end within 20 seconds And polling detects changes within 60 seconds with zero missed events in a 24‑hour soak test And if a webhook fails or is revoked, the system falls back to polling within 30 seconds and logs the transition And duplicate deliveries from push and poll are handled idempotently with no duplicate user notifications or state thrashing
Real‑Time Participant and Organizer Notifications
Given any state change (slot invalidated, slot re‑enabled, quorum reached, hold expired) When the change is applied Then participants and organizers receive a Slack/email update that includes local time, reason, current quorum status, and a deep link to the live hold view And duplicate notifications for the same state change are suppressed per user for 2 minutes And failed notifications retry with exponential backoff up to 3 attempts before surfacing an error to the organizer And notification delivery and engagement metrics are captured for audit
Hold Window Expiry and Safe Termination
Given an active hold window with no slot having reached quorum by expiry time T When T is reached Then all holds are released within 10 seconds and no further approvals are accepted And participants are notified that the window expired and what the next action is (e.g., new window proposal) And the organizer receives a summary of approvals, invalidation reasons, and the top next viable window And the recalculation engine stops processing events for the expired hold and ignores late approvals
Revalidation on Conflict Removal
Given a candidate slot S_k was invalidated due to a must‑have conflict When the conflicting event is removed or rescheduled so S_k is conflict‑free Then the system detects the change within push/poll SLAs and revalidates S_k within 10 seconds of detection And S_k is reinserted into the candidate set with an updated ranking and viability status And participants are notified that S_k is available again with a one‑tap approval action And previously superseded approvals are not auto‑restored to S_k without explicit user action

Asset Carry-Through

Moves the meeting without breaking anything: agenda, attachments, conferencing link, recording settings, and invite rules persist. Participants receive delta-only updates and ICS continuity, so externals keep working links and nobody has to rebuild the invite.

Requirements

Agenda & Structured Notes Persistence
"As a product manager scheduling across time zones, I want the agenda and notes to persist when I move a meeting so that I don’t have to rebuild structure and participants retain context."
Description

When a meeting is rescheduled within TimeMeld, all agenda content, sections, checklists, and timeboxed items created in TimeMeld or synced from connected docs remain attached to the event. The system updates only the start/end time while preserving the agenda data model and bi-directional links, ensuring participants see the same agenda in the new time slot. Recurring series and single-instance moves are handled via stable event UID and instance IDs, and conflicts are resolved with last-writer-wins plus change annotations.

Acceptance Criteria
Single-Instance Reschedule Preserves Agenda Assets
Given a non-recurring meeting with agenda sections, checklists with completion states, timeboxed items, and linked external docs When the organizer reschedules the meeting within TimeMeld to a new start and end time Then the event UID remains unchanged And agenda content, structure, and checklist completion states remain identical And timeboxed durations and relative ordering persist, anchored to the new start time And bi-directional links to external docs remain unchanged and functional And only the event start and end timestamps are changed in the event record
Recurring Series—Move One Occurrence
Given a recurring series with instance-specific agenda edits When the organizer moves only a single occurrence to a new time Then the series master UID remains unchanged And the moved occurrence retains its instance identifier (RECURRENCE-ID) and agenda content And no other occurrences are modified And participants see the same agenda for the moved occurrence at its new time
Recurring Series—Move Entire Series
Given a recurring series with a shared agenda template and per-instance notes When the organizer moves the entire series to a new schedule Then the series master UID remains unchanged And the agenda template persists unchanged and is visible at the new times And per-instance notes remain attached to their respective instances at the new schedule And no agenda content is duplicated or orphaned
External Doc Sync and Links Intact After Move
Given agenda items synced from a connected document with bi-directional links When the meeting is rescheduled within TimeMeld Then the external document URL and anchors remain the same And TimeMeld continues syncing with the same document without creating a new document or link And users opening the agenda from calendar or invite link land on the same document and sections
Concurrency—Last-Writer-Wins With Change Annotations
Given two participants edit agenda content concurrently while the event is rescheduled When the system merges the changes Then last-writer-wins is applied at the smallest addressable element level such as an agenda item or checkbox And conflicting elements are annotated with editor identity, timestamp, and prior value And no successful user edit is lost without an annotation And the agenda remains attached to the moved event
Participant View and Links Consistent Post-Reschedule
Given internal and external invitees access the agenda via supported calendar clients and shared links When the event is moved to a new time Then opening the event from any supported calendar shows the same agenda content And the agenda share URL remains unchanged and accessible And checklist completion states and timeboxed items are identical to pre-move
Operation Is Atomic and Audited
Given a reschedule action is initiated When any step of the operation fails Then the event remains at its original time with its agenda intact and the user is notified of failure When the operation succeeds Then the event is fully moved with the agenda intact and a Rescheduled system annotation including actor and timestamp is recorded And no duplicate agendas or orphaned links exist after the operation
Attachment & Link Integrity Validation
"As an engineer, I want attachments and links to keep working after a reschedule so that I can access the same materials without chasing new URLs."
Description

All attachments (files, decks, PRDs) and deep links associated with the meeting are preserved across moves without generating new share URLs. TimeMeld maintains attachment metadata and permissions, revalidates accessibility post-move, and warns on broken links with one-click fix flows. For external attendees, share links continue functioning via unchanged resource IDs embedded in the event description or attachment fields.

Acceptance Criteria
Same-calendar reschedule preserves attachment and link URLs
Given an existing meeting with N attachments and M deep links in the description and attachment fields When the meeting is moved to a new time/date on the same calendar without editing content Then no new share URLs are generated for any attachment or link And each resource ID for all attachments and links remains identical pre- and post-move And the attachments list (count, order, filenames, MIME types) is unchanged And the event description text and markup are unchanged And all links return HTTP 200 for attendees who previously had access And the revalidation completes within 5 seconds of move completion
Move a single instance of a recurring meeting retains assets
Given a recurring series with attachments and deep links applied at the series or instance level When a single occurrence is rescheduled (RECURRENCE-ID) without content edits Then only that occurrence's DTSTART/DTEND change and SEQUENCE increments by 1 And the attachments and deep links on that occurrence remain identical (no additions, removals, or regenerated URLs) And the series master and other instances remain unchanged And external attendees can access the same URLs from their existing calendar entries for that occurrence
External attendee continues to access unchanged share links after move
Given at least one external attendee has previously received the invitation and accepted When the organizer moves the meeting Then the external attendee's existing invite maintains the same join link and attachment URLs And the ICS UID remains unchanged and SEQUENCE increments by 1 And the update email and ICS contain only delta changes (time fields) with no ATTACH/URL replacements And previously received links in the original email continue to function without requiring a new invite And the external attendee can access each link with HTTP 200 using prior permissions
Post-move accessibility revalidation flags broken assets
Given the meeting has attachments/links where at least one resource has become inaccessible due to provider permission changes or deletion When the meeting is moved Then TimeMeld revalidates each attachment/link within 10 seconds And inaccessible items are flagged with specific reasons (e.g., 403 permission, 404 missing) and affected attendees And the organizer is shown a non-blocking warning listing the broken items and a one-click Fix Access action And no attachment/link URLs are auto-replaced during revalidation
One-click fix restores access without changing URLs
Given one or more attachments/links are flagged as inaccessible to some attendees post-move When the organizer clicks Fix Access in TimeMeld and confirms the audience scope Then TimeMeld updates provider permissions to match the meeting attendee list or selected scope And the original URLs and resource IDs remain unchanged And revalidation reruns automatically and passes within 10 seconds for fixable items And external attendees with link-based access can retrieve the resource with HTTP 200 And an audit entry records the permission changes and the acting user And if provider denies the change, a clear error is shown with next steps
ICS continuity and delta-only updates for moved meetings
Given a meeting (single or recurring instance) is moved by TimeMeld When update notifications are sent to attendees and calendars sync Then the ICS UID remains unchanged and SEQUENCE increments by exactly 1 And only DTSTART/DTEND (and RECURRENCE-ID for instances) are modified; DESCRIPTION, ATTACH, and URL fields remain byte-for-byte identical And attendees do not receive a new meeting object (no duplicates) across Google and Outlook And conferencing links and recording settings remain unchanged in the calendar payload And the attendee sees a single updated event with the same links accessible as before
Conferencing Bridge Continuity
"As an ops lead, I want the video link to stay the same when we move a meeting so that invitees’ bookmarks and room systems still work."
Description

The conferencing provider details (join URL, meeting ID, dial-ins, passcodes) remain unchanged when the event time shifts, preventing new links from being issued. TimeMeld uses provider APIs (Google Meet, Zoom, Microsoft Teams) to update time metadata only, preserving meeting identifiers. If a provider enforces time-bound windows, TimeMeld extends the session window or regenerates tokens behind the same join URL where supported; otherwise it alerts the organizer with clear fallback options.

Acceptance Criteria
Google Meet — Reschedule Within Allowed Window
Given an existing calendar event with a Google Meet conference (join URL, meeting code, dial-ins, passcode) When the organizer shifts the event start/end time by up to 12 hours using TimeMeld Then the Google Meet join URL, meeting code, dial-ins, and passcode remain unchanged And no new conference is created on the provider And only the provider time metadata is updated successfully And attendees receive a single time-change update with the same join URL visible And the ICS UID remains unchanged and SEQUENCE increments by 1
Zoom — Cross-Day Reschedule With Session Extension
Given an existing Zoom meeting with a join URL and meeting ID And the new time moves the meeting across calendar days When the organizer reschedules the meeting using TimeMeld Then TimeMeld extends the Zoom meeting’s scheduled window without issuing a new join URL And the Zoom meeting ID and join URL remain unchanged And attendees receive a delta-only calendar update with unchanged conferencing details And the ICS UID remains unchanged and SEQUENCE increments by 1
Microsoft Teams — Single Occurrence Reschedule in a Series
Given a recurring Teams meeting where a single occurrence is selected for reschedule When the organizer shifts only that occurrence using TimeMeld Then the Teams join URL and conference identifiers remain identical for that occurrence And other occurrences retain their original times and links And the rescheduled occurrence is published with a RECURRENCE-ID in ICS; UID unchanged; SEQUENCE increments And attendees of that occurrence receive a time-change update with the same link
ICS Continuity for External Attendees
Given a rescheduled meeting with preserved conferencing When TimeMeld issues updates to external attendees via .ics Then the iCalendar object retains the same UID And METHOD is REQUEST with SEQUENCE incremented by at least 1 And VEVENT contains unchanged conferencing properties/links; only DTSTART/DTEND are modified And no additional .ics attachments containing a different conferencing link are sent
Provider Requires Link Regeneration — Organizer Fallback Prompt
Given a provider indicates the join URL cannot be preserved for the requested new time When TimeMeld attempts the update and receives a constraint error Then TimeMeld presents options: keep original time; create new link and notify attendees; propose alternate windows And the prompt clearly states a new link would be required if proceeding And no attendee updates are sent until the organizer chooses an option And the audit log records the provider error code and the organizer’s decision
Delta-Only Update Content
Given a successful reschedule with preserved conferencing details When attendee notifications are sent Then the update contains only time changes and does not display a new or different join link, meeting ID, dial-ins, or passcodes And the event description and conferencing fields remain byte-identical to the prior version And update delivery latency to all attendees is under 60 seconds for the 95th percentile
Provider API Usage — Time Metadata Only
Given a reschedule request for a meeting with existing conferencing When TimeMeld updates the conferencing provider Then only time-related fields are modified via the provider API And no API calls to create or replace the conference are executed And provider resource identifiers (meeting ID/UUID) remain unchanged before and after And telemetry captures the API calls made for audit and troubleshooting
Recording & Meeting Options Preservation
"As a meeting host, I want recording and option settings to carry over when I change the time so that our compliance and facilitation settings remain intact."
Description

Recording preferences and meeting-level options (auto-record, lobby, host/presenter roles, mute-on-join, passcode settings, breakout assignments) persist through rescheduling. TimeMeld updates provider-side schedule metadata while retaining option flags and role assignments mapped to attendee identities. The system verifies that organizer permissions remain valid post-move and prompts reassignment only if provider constraints require it.

Acceptance Criteria
Reschedule Keeps Recording and Core Options Intact
Given an existing meeting created via TimeMeld with auto-record enabled, mute-on-join enabled, lobby enabled, and a specified recording destination And provider-side meeting metadata for these fields is captured as Baseline A When the meeting is rescheduled to a new time via TimeMeld without changing options Then the provider-side metadata for auto-record, mute-on-join, lobby, and recording destination equals Baseline A after the update And the conferencing join URL remains unchanged And TimeMeld records a verification entry indicating no option deltas
Role Assignments Persist Across Reschedule
Given host and presenter roles are assigned to named attendees (internal and external) by identity And provider-side role mapping is captured as Baseline R When the meeting is rescheduled via TimeMeld Then host and presenter assignments after the update equal Baseline R And the designated host retains organizer/host capabilities upon join And no participants are downgraded in role
Passcode and Lobby Settings Remain Stable
Given the meeting has lobby enabled and a passcode value P currently in effect And the current passcode P is visible via provider API and ICS When the meeting is rescheduled via TimeMeld Then the passcode remains P and lobby remains enabled post-update And both the provider API and the regenerated ICS reflect passcode P And no new passcode is generated
Breakout Room Assignments Are Preserved
Given breakout rooms are configured with assigned attendees by identity And provider-side breakout configuration is captured as Baseline B When the meeting is rescheduled via TimeMeld Then the breakout configuration after the update equals Baseline B (rooms, names, and attendee-to-room assignments) And attendees not assigned before remain unassigned after the update
Organizer Permission Revalidation and Prompted Reassignment
Given TimeMeld holds organizer credentials sufficient to update the meeting When a reschedule is initiated Then TimeMeld validates update permissions with the provider before committing changes And if validation passes, the reschedule is applied without changing the organizer And if validation fails due to missing scope or expired token, the user is prompted to reauthenticate or reassign an eligible organizer before any change occurs And the reschedule proceeds only after successful reauthentication or reassignment, with the action captured in the audit log
Provider Constraint Handling for Unsupported Options
Given certain configured options are not preservable for the requested move due to provider constraints (e.g., cross-tenant restriction on breakout assignments or recording location) When the meeting is rescheduled via TimeMeld Then all supported options are preserved unchanged And only the specific unsupported options are adjusted as required by the provider And the user is shown a pre-commit summary detailing the exact option deltas and provider reason codes And an audit record is stored listing the constraints and applied deltas
Invitee Rules & RSVP State Retention
"As an organizer, I want invitee settings and RSVPs to stay intact when I reschedule so that I don’t lose commitments or have to reconfigure attendance."
Description

Attendee lists, optional/required status, RSVP responses, reminders, and notification preferences persist during a move. TimeMeld updates the event’s start/end time while maintaining the same iCalendar UID and incrementing SEQUENCE to ensure clients treat the change as an update, not a new event. Optional attendees remain optional, delegation and forwarding rules remain applied, and reminder offsets are recomputed against the new start time without altering user-set preferences.

Acceptance Criteria
Time-Only Move Preserves Attendee Roster and Roles
Given an existing event with required and optional attendees (including externals) When the organizer updates only the start and/or end time via TimeMeld Then the updated event contains the exact same set of attendees as before And each attendee's required/optional designation is unchanged And the organizer identity remains unchanged And no duplicate or missing attendees are present
RSVP State Retention Across Time Change
Given attendees have Accepted, Tentative, Declined, and Needs Action states on the event When the event time is changed via TimeMeld Then each attendee's RSVP state remains unchanged And any response comments/notes remain associated to the attendee And no attendee's state is reset or cleared
Reminder and Notification Preferences Persist and Recompute
Given attendees have user-set reminder channels and offsets (e.g., email 30m, popup 10m) When the event start time is moved Then reminders are rescheduled relative to the new start time using the same offsets per attendee And the number and type of reminders per attendee remain unchanged And notification channels and quiet-hours preferences remain unchanged
iCalendar UID Continuity with SEQUENCE Increment
Given an existing iCalendar event with UID = U and SEQUENCE = S When TimeMeld updates only the start/end time Then the outgoing ICS retains UID = U And SEQUENCE equals S + 1 And DTSTAMP is updated to the update time And clients display a single updated event (not a duplicate)
Delta-Only Update and Link Continuity for Externals
Given the event includes external attendees and has conferencing links and attachments When the event time is changed via TimeMeld Then the ICS update includes only changed properties (start/end time, SEQUENCE, DTSTAMP) And conferencing links and attachment URLs remain identical and functional And external attendees can join using previously received links without re-accepting
Delegation and Forwarding Rules Remain Applied
Given an attendee with a delegate (DELEGATED-TO/DELEGATED-FROM) and existing forwarding rules When the event time is updated via TimeMeld Then delegation metadata persists for both principal and delegate in the updated invite And update notifications are routed to delegate/forward recipients per existing rules And no additional recipients beyond the original routing receive notifications
Delta-Only Notifications with ICS UID Continuity
"As an external attendee, I want a minimal update that keeps my calendar event intact so that I don’t end up with duplicate invites or dead links."
Description

Participants receive concise delta updates reflecting only what changed while preserving the original iCalendar UID to maintain continuity for external calendars. TimeMeld sends iTIP updates with incremented SEQUENCE and appropriate METHOD values, aggregates changes into a single update, and suppresses redundant emails. For externals, ICS attachments include the same UID and updated DTSTAMP/DTSTART/DTEND, preventing duplicate events and broken links.

Acceptance Criteria
Reschedule Time—Delta-Only Update Preserved UID
Given an existing event with UID U and SEQUENCE S When the organizer changes only the meeting time (DTSTART/DTEND) and saves Then TimeMeld sends a single iTIP update with METHOD:REQUEST, UID=U, SEQUENCE=S+1, DTSTAMP increased And the ICS reflects updated DTSTART/DTEND only; other event identifiers (UID) remain unchanged And the participant notification content lists only the time change and omits unchanged fields And each participant receives no more than one email for this action
Add and Remove Attendees—Single Aggregated Update
Given an existing event with UID U and SEQUENCE S And the organizer adds Alice and removes Bob within a 2-minute aggregation window When the organizer saves changes (or the aggregation window elapses) Then existing attendees receive one iTIP update with METHOD:REQUEST, UID=U, SEQUENCE=S+1 summarizing attendee changes only And Alice (new attendee) receives one invitation with METHOD:REQUEST, UID=U, SEQUENCE=S+1 containing full current event details And Bob (removed attendee) receives one cancellation with METHOD:CANCEL, UID=U, SEQUENCE=S+1 And no attendee receives more than one email for these combined changes And notification content lists only the added/removed attendees and omits unchanged fields
External Calendar Update—UID Continuity Prevents Duplication
Given an external attendee has accepted the event in Google Calendar or Outlook And the event has UID U and SEQUENCE S When the organizer updates the meeting time and saves Then the external attendee receives one update email with an ICS attachment where UID=U, METHOD:REQUEST, SEQUENCE=S+1, and DTSTAMP increased And after calendar sync, the attendee’s calendar shows exactly one event (no duplicate) updated in place to the new DTSTART/DTEND And the conferencing/join link in the event remains functional and unchanged And the event’s reminder settings on the external calendar are preserved by virtue of in-place update
No Material Change—No Notification or Sequence Bump
Given an existing event with UID U and SEQUENCE S When the organizer opens the event and saves without changing any notifiable fields Then TimeMeld sends no iTIP message and no email to participants And the stored SEQUENCE remains S (no increment) And the event’s UID remains U And audit logs reflect a no-op save with zero outbound notifications
Batch Multiple Edits—One Consolidated Update
Given an existing event with UID U and SEQUENCE S And within a 2-minute aggregation window the organizer changes the time and updates the location When the changes are committed (save or window elapses) Then participants receive exactly one iTIP update with METHOD:REQUEST, UID=U, SEQUENCE=S+1 that includes both changes And notification content lists only the changed fields (time, location) and omits unchanged fields And no intermediate or redundant emails are sent during the aggregation window And the ICS DTSTAMP is later than the previous DTSTAMP and DTSTART/DTEND/location reflect new values
Cancellation Uses Correct METHOD with UID Continuity
Given an existing event with UID U and SEQUENCE S When the organizer cancels the event Then TimeMeld sends one iTIP message with METHOD:CANCEL, UID=U, SEQUENCE=S+1 and updated DTSTAMP to all attendees And external calendars remove or mark the original event as canceled without creating duplicates And no further update emails are sent after the cancellation for this event
Atomic Move with Idempotent Retry and Rollback
"As a distributed team organizer, I want moves to be all-or-nothing with safe retries so that we don’t end up in a broken state where links or attendees are out of sync."
Description

Rescheduling executes as an atomic operation across calendar, conferencing, and attachment services. Either all assets update successfully, or the system rolls back to the previous state. Operations are idempotent with request IDs, featuring exponential backoff and compensating actions on partial failure. Pre-flight checks validate organizer permissions, event ownership, and provider quotas. A detailed audit log records changes with trace IDs to support troubleshooting and compliance.

Acceptance Criteria
Atomic Reschedule Success Across Services
Given an owned event with valid organizer permissions and sufficient provider quotas across calendar, conferencing, and attachment services And the event has agenda, attachments, conferencing link, recording settings, and invite rules configured When the organizer reschedules the event to a new valid time window Then the system updates the event time across all services within a single logical transaction boundary And agenda, attachments, conferencing link, recording settings, and invite rules persist unchanged And external participants receive a delta-only update with ICS continuity (same UID, incremented SEQUENCE, updated DTSTART/DTEND) And all conferencing and attachment URLs remain unchanged and functional And the attendee list remains unchanged unless explicitly modified And the operation completes within 5 seconds P95 under normal load
Rollback on Partial Failure
Given a reschedule attempt triggers a non-retriable error in any downstream service during commit When partial changes are detected Then the system rolls back all changes, restoring the original time and assets across all services And participants receive no net-change notification (or a corrective cancellation/update) such that the final calendar state matches the original And the final state across all services equals the pre-operation snapshot And an audit log entry records rollback=true with error details and trace ID And no duplicate, orphaned, or stale conferencing rooms, recordings, or attachments remain
Idempotent Move with Request ID
Given the client includes a unique request_id in the reschedule request When the same request_id and identical payload are submitted multiple times within 24 hours Then exactly one reschedule is executed and subsequent submissions return 200 with idempotent_result=duplicate and produce no side effects And when the same request_id is reused with a different payload, the system returns 409 Conflict and applies no changes And idempotency keys expire after 24 hours and are garbage collected
Exponential Backoff and Retry Policy
Given a reschedule attempt encounters retriable errors (e.g., 429, 5xx, or network timeouts) from any service When retrying the affected operation Then the system uses exponential backoff with jitter: initial delay 1s, multiplier 2, ±20% jitter, max delay 32s, max 5 attempts per service And total retry wall-clock time does not exceed 90 seconds And retries stop immediately on non-retriable errors And the final outcome is either full success or full rollback with no partial state left
Pre-flight Validation Blocks Unsafe Moves
Given the organizer initiates a reschedule When pre-flight checks run Then the system verifies organizer permissions, event ownership, attendee modification rights, conferencing/recording policy compliance, and provider quotas And if any check fails, the move is blocked with a descriptive error code and no changes are applied to any service And a pre-flight audit entry is recorded with trace ID and failure reason And pre-flight completes within 1 second P95
Comprehensive Audit Logging with Traceability
Given any reschedule attempt (success, rollback, or failure) When the operation completes Then an immutable audit log entry is stored containing: trace_id, request_id, actor, timestamps (received, started, committed/rolled_back), pre and post event metadata (time, assets, attendees), per-service outcomes, retry counts, and final state And audit entries are queryable by trace_id and request_id within 1 second P95 And sensitive fields are redacted per policy while retaining forensic value And audit logs are retained for at least 400 days and are tamper-evident

Smart Decline Swap

When a required attendee can’t make the proposed time, Slipstream offers them humane alternates within equity rules and lets the organizer swap into the earliest mutually fair window in one tap—saving manual triage while keeping fairness intact.

Requirements

Instant Decline Trigger
"As a required attendee, I want my decline to automatically offer a smarter reschedule path so that I don’t have to manually negotiate a new time."
Description

Detects when a required attendee declines or marks the proposed time as not workable via calendar response, in‑app prompt, or Slack action, and initiates the Smart Decline Swap flow. Pulls attendee context (timezone, working hours, do‑not‑disturb, focus blocks) from TimeMeld profiles and connected calendars to determine eligibility and constraints. Normalizes responses across Google/Microsoft calendars via webhooks, maps decline reasons, and records the triggering event for auditability. Ensures only meetings with required attendees and reschedulable policies are processed and gracefully falls back to standard decline behavior when the feature is disabled or constraints cannot be met.

Acceptance Criteria
Cross-Calendar Decline Webhook Triggers Swap
Given a scheduled TimeMeld meeting with reschedulable policy enabled and at least one required attendee integrated via Google or Microsoft 365 And calendar webhooks are active for the attendee When the attendee submits a Decline RSVP from Google Calendar or Outlook/Office 365 Then TimeMeld receives the provider webhook and normalizes the status to a unified "decline" with a mapped reason code And a Smart Decline Swap flow is initiated within 10 seconds of webhook receipt And duplicate provider notifications for the same attendee/event received within 60 seconds are deduplicated And the meeting reflects that a swap flow has started, with trigger_source="calendar"
In-App and Slack Decline Triggers
Given a scheduled TimeMeld meeting with reschedulable policy enabled and a required attendee viewing the meeting in-app or in Slack When the attendee selects "Can't make it" via the in-app prompt or the Slack message action Then TimeMeld records a normalized decline with trigger_source set to "in-app" or "slack" and captures any provided decline reason And the attendee receives an acknowledgment in the same surface within 1 second And a Smart Decline Swap flow is initiated within 3 seconds of the action And the event is recorded for auditability
Eligibility Gate: Required Attendee and Reschedulable Policy
Rule: Optional attendee declines must not initiate Smart Decline Swap; standard decline behavior applies Rule: Meetings with reschedulable policy disabled must not initiate Smart Decline Swap even if a required attendee declines Rule: If the Smart Decline Swap feature is disabled at the workspace or meeting level, declines must fall back to standard behavior Rule: Eligibility decisions are recorded with eligibility_result and reason for auditability
Context Enrichment on Trigger
Given a valid decline trigger for a required attendee When evaluating eligibility and constraints Then TimeMeld fetches timezone, working hours, do-not-disturb windows, and focus blocks from the attendee profile and connected calendars covering the next 14 days And the fetch completes within 1500 ms or falls back to cached values no older than 24 hours And if data is missing or sources are unavailable, documented defaults are applied without failing the trigger And the resolved constraints are attached to the swap flow payload for downstream use
Audit Logging of Decline Trigger
Given any decline trigger processed by TimeMeld When the trigger is handled Then an immutable audit record is written containing: meeting_id, attendee_id, trigger_source, provider, normalized_status, normalized_reason, received_at_utc, processed_at_utc, eligibility_result, policy_snapshot_id, idempotency_key, and swap_flow_id (if started) And the record is available for query via the audit interface/API within 5 seconds of processing And audit records are retained for at least 180 days
Graceful Fallback on Ineligibility or Constraint Failure
Given a decline trigger where the meeting or workspace is ineligible or constraints cannot be satisfied (e.g., calendars disconnected, context fetch failure, no fair alternate windows) When processing the trigger Then Smart Decline Swap is not initiated And the attendee is informed that a standard decline will be used And the organizer receives only the standard provider decline notification (no duplicate TimeMeld email or DM) And an audit record is written with failure_reason and recovery_action
Idempotency and Concurrency Control for Declines
Given multiple decline signals for the same attendee and meeting arriving within a 5-minute window from any combination of calendar, in-app, or Slack sources When the signals are processed concurrently Then exactly one Smart Decline Swap flow is created And subsequent duplicate signals are acknowledged without side effects using a stable idempotency key And only one organizer notification about swap initiation is sent And a metric "decline_trigger_duplicates_suppressed" increments for each suppressed duplicate
Fairness Rules Engine Compliance
"As an organizer, I want alternates to be validated against our fairness rules so that reschedules don’t concentrate burden on the same people."
Description

Evaluates candidate reschedule windows against TimeMeld’s equity scoreboard and fairness policies before any option is shown or accepted. Enforces rotation of meeting ownership, prevents repeated inconvenient slots for the same individuals or regions, applies timezone‑weighted ergonomics (e.g., avoids very early/late hours), and respects recent burden history and cooldowns. Computes a fairness score for each window and rejects/flags options that would regress equity. Exposes machine‑readable reasons for acceptance/rejection and writes fairness decisions to the audit log for transparency and analytics.

Acceptance Criteria
Candidate Window Fairness Scoring and Threshold Enforcement
Given a fairness policy with min_score in [0,100] And a set of candidate windows for a meeting When the engine evaluates the candidates Then each candidate is assigned a fairness_score in [0,100] and persisted And candidates with fairness_score >= policy.min_score are marked acceptable And candidates with fairness_score < policy.min_score are rejected with reason_codes including "below_min_score" And only acceptable candidates may be displayed or selected for swap
Timezone-Weighted Ergonomics Compliance
Given each required attendee has an ergonomic_band [start_local,end_local] and hard_limits [earliest_local,latest_local] from policy When a candidate places an attendee outside their ergonomic_band but within hard_limits Then a penalty proportional to hours outside is applied to fairness_score And reason_codes includes "outside_ergo_band" with impacted_participants identified When a candidate places any required attendee outside hard_limits Then the candidate is automatically rejected with reason_codes including "outside_hard_limit" for that attendee And no rejected candidate is shown or accepted
Ownership Rotation Preservation on Swap
Given a swap is initiated to an accepted candidate window And the fairness scoreboard tracks meeting ownership rotation When computing ownership for the swapped meeting Then the selected window must not assign the same owner consecutively unless all other eligible owners have owned since the last cycle reset And if rotation would be violated, the engine either reassigns owner to the next eligible or rejects the candidate with reason_codes including "rotation_violation" And upon a successful swap, the scoreboard update and calendar change occur atomically
Recent Burden History and Cooldown Enforcement
Given policy.cooldown_days = 7 And burden is defined as any slot outside an attendee's ergonomic_band or flagged by policy as high-burden When a candidate would impose a burden on an attendee who had a burden event within the past policy.cooldown_days Then the candidate is rejected with reason_codes including "cooldown_violation" and includes prior_burden_at timestamps per impacted attendee And candidates that avoid additional burden are not penalized by cooldown logic
Humane Alternates on Decline with Earliest Mutually Fair Window
Given a required attendee declines the proposed time When alternates are requested Then the engine returns up to policy.max_alternates (default 3) earliest future windows with fairness_score >= policy.min_score and no violations of rotation, cooldown, or hard_limits And alternates are sorted by start_time ascending and include fairness_score And tapping Swap on the earliest alternate schedules that window, updates calendar invites, and records a fairness decision with decision="accepted" And no alternate that would regress equity is returned
Decision Explainability via Machine-Readable Reasons
Given a fairness evaluation result exists for a meeting's candidate window When retrieved via API GET /fairness/decisions?meeting_id={id} Then each item returns JSON fields: decision ("accepted"|"rejected"), fairness_score (number), reason_codes (array<string>), impacted_participants (array<id>), policy_version (string), weights (object) And rejected decisions include at least one reason_code And accepted decisions include an empty reason_codes array And the response validates against the versioned JSON Schema for policy_version
Audit Log Write and Retrieval for Fairness Decisions
Given any fairness decision is finalized (accepted or rejected) When the decision is recorded Then an immutable audit log entry is written within 1000 ms containing: decision_id, meeting_id, window_start, window_end (ISO 8601 UTC), actor_id, decision, fairness_score, reason_codes, policy_version, previous_owner_id, new_owner_id, timestamp And audit entries are retrievable via API with filters by meeting_id and time range and are ordered by timestamp descending And attempts to modify or delete existing audit entries are denied and logged
Humane Alternate Window Generation
"As a decliner, I want ergonomic, fair suggestions I can choose from quickly so that I minimize disruption and still attend."
Description

Generates a small, high‑quality set of alternate windows for the decliner that balance mutual availability, fairness scores, and ergonomic constraints. Surfaces 3–5 options ranked by earliest mutually fair time, with clear local‑time displays for all required attendees. Allows the decliner to pick one, propose a range, or request the next fair week. Honors buffer times, travel blocks, and personal preferences, and supports quick actions from email, in‑app, or Slack without forcing context switches. Fails gracefully with guidance when no fair windows exist and can optionally expand the search according to policy.

Acceptance Criteria
Decliner Receives 3–5 Ranked Fair Alternate Windows
Given a required attendee declines the proposed meeting time and all required attendees are marked as required When the system generates alternate windows Then it returns between 3 and 5 options inclusive, or all available if fewer than 3 exist And every option is mutually available for all required attendees And every option meets ergonomic constraints defined by policy (e.g., working hours, no-early/late bands) And every option meets or exceeds the minimum fairness score threshold defined by policy And options are ranked by earliest mutually fair time; ties are ordered by higher fairness score, then earlier chronological time And each option matches the original meeting duration And generation completes within 2 seconds at the 95th percentile
Clear Local-Time Displays for All Required Attendees
Given alternate windows have been generated When options are presented in any channel (email, in‑app, Slack) Then each option displays the start time in the decliner’s local time and in the local time for every required attendee And each displayed time includes the time zone abbreviation and UTC offset with DST correctly applied And any attendee for whom the time falls outside their stated working hours is clearly indicated And formatting respects each viewer’s 12/24‑hour preference in in‑app views and uses a standard 24‑hour format in email/Slack summaries
Quick Actions from Email, In‑App, and Slack
Given alternate windows are delivered via email, in‑app notification, or Slack When the decliner selects “Pick Option”, “Propose Range”, or “Next Fair Week” in that channel Then the action is accepted in‑channel without requiring a context switch And if a valid secure token is present the action completes without additional authentication; otherwise a single SSO step is prompted And the system acknowledges the action within 3 seconds end‑to‑end and reflects the selection in the app state And the organizer receives a confirmation notification and the relevant calendar artifacts (invite/update or hold) are created
Decliner Can Pick, Propose Range, or Request Next Fair Week
Given the decliner is viewing the generated alternates When the decliner picks a single option Then TimeMeld proposes/swaps the meeting to that slot, updates all required attendees, and reconciles any temporary holds When the decliner proposes a time range Then the system returns the earliest mutually fair window within that range that meets policy and requests confirmation And if no window fits the range, a clear message is shown with an option to expand search per policy When the decliner requests the next fair week Then the system surfaces the earliest mutually fair window in the next calendar week that meets policy and requests confirmation
Honor Buffers, Travel Blocks, and Personal Preferences
Given attendee calendars include buffer rules, travel/commute blocks, and personal no‑meeting preferences When alternate windows are generated Then no proposed option violates any attendee’s buffer-before/after constraints relative to neighboring events And no proposed option overlaps travel/commute blocks or personal no‑meeting times And minimum notice lead time and maximum daily meeting load limits are respected per policy And options that would repeat inconvenient slots for the same attendee cohort in consecutive weeks are excluded per equity rules
Graceful Failure and Policy-Governed Expansion
Given the system finds no alternate windows that satisfy availability, ergonomics, and fairness under current policy When alternates are requested Then the decliner sees a clear explanation of the constraint(s) preventing options and is offered actions And available actions include: request next fair week; expand search using policy-defined relaxations And upon choosing to expand, the system applies the configured relaxations in order and regenerates options, labeling any relaxed constraints And if still no options exist, the system records the outcome, offers to notify the organizer, and provides guidance to coordinate asynchronously
One‑Tap Swap & Auto‑Reschedule
"As an organizer, I want to swap into the earliest mutually fair window in one tap so that I can reschedule without manual triage."
Description

Enables the organizer to approve a selected alternate in a single action, automatically updating the original event and invites. Modifies start/end time, preserves conferencing links and agenda, updates resources/rooms, notifies all participants, and cancels the original slot with proper ICS updates to prevent duplicates. Ensures atomicity with transactional updates across Google/Microsoft APIs, retries on transient failures, and rollback if any participant cannot be updated. Maintains the meeting thread context in email/Slack and posts a concise change summary with before/after times in each attendee’s local timezone.

Acceptance Criteria
One‑tap swap preserves event details and updates time
Given an existing meeting with conferencing link, agenda, attachments, participants, and an approved alternate time When the organizer taps "Swap into alternate" Then the event start and end times are updated to the alternate time And the conferencing link/meeting ID remains unchanged And the agenda text and attachments remain unchanged And there is exactly one meeting instance on each attendee’s calendar after synchronization And a success confirmation is shown to the organizer within 5 seconds (P95)
Atomic cross‑provider reschedule with retries, rollback, and idempotency
Given attendees span Google Workspace and Microsoft 365 tenants and network conditions may be unreliable When the swap is initiated Then updates to all participants’ calendars are executed as a single transaction and are only committed if every participant update succeeds And transient errors (HTTP 429/5xx/timeouts) are retried up to 3 times with exponential backoff up to 90 seconds total And if any participant cannot be updated after retries, all interim changes are rolled back to the original meeting time for everyone And no update notifications are sent until the transaction commits And the operation is idempotent: duplicate taps within 60 seconds do not create duplicate updates or notifications (same idempotency key)
Proper ICS/iTIP sequencing prevents duplicates
Given the original event has a stable UID and an alternate time is approved When the system updates external calendars via ICS/iTIP Then the UID remains the same and SEQUENCE is incremented by +1 on the updated invite (METHOD: REQUEST) And any separate hold/placeholder for the original slot is canceled with METHOD: CANCEL and matching UID And attendees in Google Calendar and Outlook receive exactly one updated event on their calendars and zero duplicates after the next sync cycle And removed placeholders no longer appear on any attendee or room calendar
Thread continuity and localized change summary in Email and Slack
Given the meeting has an existing email thread and a Slack thread for coordination When the swap completes Then an email is sent as a reply in the existing thread (In-Reply-To/References preserved) with subject prefixed "[Rescheduled]" And the email and Slack thread messages include a concise summary: old time → new time for each attendee in their local timezone with city and UTC offset And the Slack message is posted in the existing thread (same thread_ts) without creating a new channel thread And at least three attendees in different timezones see correct localized times matching their profile timezones
Room/resource rebooking on swap
Given the original meeting has a room/resource booked and an alternate time is selected When the swap is executed Then the system attempts to rebook the same room at the new time and releases the prior hold And if the room is unavailable, the best available room is auto-selected per configured preference rules And if no rooms are available, the swap is aborted, all changes are rolled back, and the organizer sees a clear error with alternatives And no orphaned room holds remain on any resource calendar after completion
Organizer can approve from mobile and web in one tap/click
Given the organizer is viewing the proposed alternate in the mobile app or web app When the organizer approves the alternate Then the action requires at most one primary tap/click from the alternate view And the CTA is labeled "Swap into this time" and shows a loading/disabled state during processing And the end-to-end operation completes within 5 seconds at P95 and 10 seconds at P99 And the CTA is disabled if the meeting starts within 5 minutes or if the alternate violates equity policies
Fairness guardrails validated before swap
Given equity policies are configured (timezone-weighted fairness and ownership rotation) When the organizer attempts to swap into an alternate time Then the policy engine evaluates the alternate and returns pass/fail with an audit record of scores And swaps proceed only if the policy evaluation passes and do not increase any attendee’s inconvenience beyond configured thresholds And if the evaluation fails, the swap is blocked with a clear reason and at least one compliant next-best suggestion
Smart Holds & Conflict Resolution
"As a scheduler, I want tentative holds on candidate times so that good slots aren’t lost while we finalize the swap."
Description

Places short‑lived, reversible soft holds on candidate windows across required attendees to reduce race conditions while a swap is being confirmed. Continuously rechecks availability and fairness scores up to confirmation, resolves conflicts if overlapping holds arise, and releases holds immediately on rejection, timeout, or completion. Handles edge cases like newly added attendees, changed working hours, or organizer overrides, and escalates with alternatives or retry strategies when conflicts invalidate the leading option.

Acceptance Criteria
Soft Hold Placement on Leading Candidate Window
Given a Smart Decline Swap is initiated for a meeting with a defined set of required attendees and a leading candidate window is selected When soft holds are placed Then a reversible soft hold is created for each required attendee on the leading window within 3 seconds, without sending calendar invites or emails And each hold is labeled as "TimeMeld Soft Hold" and is visible in TimeMeld UI indicators for the affected attendees And hold placement is idempotent: repeated requests with the same correlation ID do not create duplicate holds And holds do not overwrite or delete existing hard events And an audit record is stored with correlation ID, attendees, window, timestamp, and initiator
Continuous Recheck of Availability and Fairness During Pending Hold
Given a leading window has active soft holds and the swap is awaiting confirmation When any attendee availability changes, a new conflicting event arrives, working hours are updated, or fairness inputs change Then the system recalculates availability and fairness within 2 seconds of the change And the current leading window and its score are updated in the UI And if the held window no longer satisfies availability or minimum fairness thresholds, it is marked invalid and escalation is triggered And all recalculations are logged with timestamps and inputs used
Conflict Detection and Deterministic Resolution Across Overlapping Holds
Given overlapping soft holds exist that involve at least one common attendee across different meetings or swap flows When a conflict is detected Then the system applies a deterministic tiebreaker: (1) higher meeting priority, (2) earlier hold timestamp, (3) greater organizer equity deficit, (4) lexicographical meeting ID as final fallback And the losing hold set is released within 1 second and the impacted flow is notified with the reason code And at most one soft hold per attendee per time window remains active across the system
Immediate Release on Confirmation, Rejection, or Timeout
Given a window is under soft hold When the organizer confirms the swap, any required attendee rejects, or the response SLA timeout elapses (default 5 minutes, configurable) Then all holds associated with the window are released within 1 second And no soft hold indicators remain visible in UI for any attendee And exactly one confirmation event is persisted atomically to prevent duplicate bookings And an outcome audit record (confirmed/rejected/expired) is stored with timestamps and actor IDs
Dynamic Updates for Added/Removed Attendees and Working Hours Changes
Given a window has active soft holds during an in‑progress swap When a required attendee is added or removed, or any required attendee changes working hours affecting the held window Then the system reevaluates validity and fairness within 3 seconds and updates the hold set accordingly And holds are added for newly added required attendees only if the window remains valid; otherwise escalation is triggered And holds for removed attendees are released immediately And the fairness score and rationale are updated and logged
Organizer Override with Guardrails and Equity Accounting
Given the leading window is invalid due to availability or fairness constraints When the organizer performs an override to force confirmation Then the system requires an explicit confirmation with a mandatory override reason and displays the policy impact And the confirmation is recorded with an override flag and rationale in the audit log And the equity scoreboard is adjusted according to policy to debit/credit fairness balances for affected participants And all previously held windows not selected are released within 1 second and attendees are notified of the override outcome
Escalation with Alternatives and Retry Strategy
Given the leading window under hold becomes invalid or is lost during resolution When escalation is triggered Then the system proposes the next‑best alternative that satisfies availability and minimum fairness thresholds and places soft holds within 3 seconds And previous holds are fully released before placing new holds And if the alternative fails, the system retries up to N configured alternatives before surfacing a failure with a ranked list of viable windows And each escalation step records reason codes, scores, and timing in the audit trail
Notifications & Swap Analytics
"As a team lead, I want clear notifications and an audit trail of swaps so that I can monitor outcomes and fairness over time."
Description

Delivers timely, channel‑appropriate notifications (email, in‑app, Slack) for decline receipt, alternate options, organizer approval, and final confirmation, with timezones localized per recipient. Provides an audit trail of each decision step, including fairness rationale, and aggregates metrics such as time‑to‑swap, fairness score deltas, burden distribution, and prevented after‑hours occurrences. Exposes dashboards and CSV export while adhering to privacy settings and data retention policies.

Acceptance Criteria
Localized Multi-Channel Decline Notification Delivery
Given a required attendee declines a proposed meeting time, When their notification preferences include email, in-app, and Slack, Then the system sends a decline-received notification on all selected channels within 60 seconds of the decline action. Given the recipient's timezone differs from the organizer's, When notifications are sent, Then all date-times in each message are localized to the recipient's timezone and include the timezone abbreviation (e.g., 09:30, IST). Given a channel delivery error occurs (e.g., Slack API failure), When delivery is attempted, Then the system retries up to 3 times over 5 minutes, falls back to other enabled channels, and records the failure and fallback in the audit trail. Given duplicate triggers for the same decline occur within a 2-minute window, When notifications are processed, Then recipients receive at most one notification per channel (idempotency key enforced). Given a recipient has Do Not Disturb hours configured, When a notification would be sent during DND, Then in-app is queued immediately, email is delayed until DND ends unless marked critical, and Slack uses silent delivery; all delays are reflected in timestamps.
Organizer Approval and Final Confirmation Notifications
Given alternates are generated after a decline, When the organizer taps One-Tap Swap on the earliest mutually fair window, Then all required attendees receive a final confirmation notification with the new time, conferencing link, and updated calendar invite within 60 seconds. Given approval-required swaps are enabled, When a swap is proposed, Then required attendees receive approval requests with Accept/Decline actions; if quorum is met within the configured window (e.g., 15 minutes), the swap executes and confirmations are sent; otherwise the proposal is canceled and the organizer is notified. Given a calendar conflict is detected for any required attendee at confirmation time, When the system attempts to execute the swap, Then the swap is blocked, the next mutually fair window is proposed, and both the organizer and conflicted attendee are notified with conflict details. Given notification content policies, When messages are sent, Then they include a deep link to view details and rationale in-app; message length fits channel constraints (Slack/Push < 160 chars body; Email subject < 80 chars).
Immutable Audit Trail with Fairness Rationale
Given any decline, alternate generation, organizer action, attendee approval, or final confirmation event, When the event occurs, Then an audit entry is written within 5 seconds including actor, action type, UTC timestamp, localized display time(s), decision inputs, fairness rationale text, previous and new fairness score, burden distribution deltas, and after-hours flags. Given audit entries are stored, When users with permission view the audit trail, Then entries are read-only, strictly time-ordered, and tamper-evident via a cryptographic hash chain linking successive entries. Given filtering needs, When filters by meeting, user, team, or date range are applied, Then the audit list updates within 2 seconds and returns only matching entries. Given privacy permissions restrict access, When a non-authorized user views the audit trail, Then PII is redacted and pseudonymous IDs are shown; users without any access see an access denied message. Given a retention policy of N days is configured, When entries exceed N days, Then they are excluded from views and exports and purged by a daily job that itself records a purge summary entry.
Analytics Dashboard: Time-to-Swap and Fairness Metrics
Given a team with completed swaps in the selected date range, When the analytics dashboard loads, Then it displays metrics: count of swaps, median and 90th percentile time-to-swap, average fairness score delta per swap, burden distribution by timezone and role, and count of prevented after-hours occurrences; values match audit data within 0.5%. Given interactive filters (team, date range, role, timezone, meeting type), When filters are applied, Then charts and tables recalculate within 2 seconds and reflect the active filters. Given drill-down is available, When a dashboard tile is clicked, Then the user sees the contributing swap list with links to each swap's audit trail. Given privacy settings exclude specified users and enforce k-anonymity, When analytics are computed, Then excluded users are removed from calculations and any cohort with fewer than k=5 members is aggregated or hidden.
CSV Export of Swap Analytics
Given a user with export permission requests an export for the current analytics view, When the export is initiated, Then a CSV is generated within 30 seconds containing rows for individual swaps and aggregated metrics, with ISO-8601 UTC timestamps and clearly labeled columns. Given privacy exclusions and retention policies, When the export file is generated, Then redacted fields remain redacted, excluded users are omitted, and records older than the retention period are not present. Given a large export exceeding 100,000 rows, When the export is requested, Then it is processed asynchronously, progress is shown in-app, and a secure download link (24-hour expiry) is sent via the user's preferred channel upon completion. Given reproducibility requirements, When the same export parameters are used within the same day, Then the exported dataset is identical except for newly added records; a parameter hash and generation timestamp are embedded in the file header.
Notification Templates and Channel Appropriateness
Given channel-specific templates, When notifications are rendered, Then email includes subject and body with full details and an audit link; Slack messages are concise with action buttons/links; in-app notifications include actionable buttons and badges; all meet WCAG AA contrast and include accessible labels. Given localization requirements, When content is rendered, Then date, time, and number formats respect the recipient's locale and timezone; untranslated placeholders never appear to end users. Given notification rate limiting, When a user would receive more than 5 non-critical notifications within 1 minute, Then the system queues and condenses them into a digest within 5 minutes while allowing critical notifications to bypass limits. Given user notification preferences, When a recipient opts out of email, Then non-critical emails are suppressed within 1 minute of the preference change; critical policy-defined notifications may still be sent with an explanatory footer.

Travel-Aware Shift

Detects upcoming timezone changes and PTO for key attendees and proactively suggests a fair, minimal-disruption slip. You stay ahead of travel-induced conflicts and keep show-rates high with considerate, preemptive reschedules.

Requirements

Multi-source Travel & PTO Detection
"As a meeting organizer, I want the system to detect when key attendees will change timezones or be on PTO so that I can address conflicts before they disrupt attendance."
Description

Continuously detect upcoming timezone shifts and time-off for key attendees by ingesting signals from connected calendars (Google/Outlook working location, event timezones, OOO), HRIS PTO integrations, user-declared travel plans, Slack status, and device/session timezone changes. Normalize signals into a unified attendee availability model with effective date ranges, confidence scores, and sensitivity levels. Respect least-privilege OAuth scopes, user consent, and data retention limits. Expose a detection service that publishes events for downstream scheduling logic and flags affected recurring series and one-off meetings within the detection window.

Acceptance Criteria
Calendar Signals Ingestion and Normalization
Given a user has connected Google and/or Outlook with read-only scopes and has upcoming working-location changes, event timezones differing from home TZ, and OOO events within the configured detectionWindow When the detection job runs or a provider webhook is received Then the system creates/updates normalized availability entries per signal with fields: userId, effectiveStart, effectiveEnd, timezone, availabilityType (TRAVEL_SHIFT|OOO), source, sourceTimestamp, confidence ∈ [0.0,1.0], sensitivity ∈ {public, internal, private} And entries are persisted within 5 minutes of the source change And duplicate source replays do not create duplicate entries (idempotent by sourceEventId) And removing or editing the source signal updates or deletes the corresponding normalized entry within 10 minutes
HRIS PTO Sync to Availability Model
Given an HRIS PTO integration is active and the attendee has an approved PTO spanning specific dates When the HRIS webhook fires or the scheduled sync runs Then a normalized availability entry of type OOO is created covering the PTO period in the attendee's home timezone with confidence ≥ 0.9 And PTO updates/cancellations in HRIS propagate to the model within 15 minutes And no write operations are attempted against HRIS (read-only access enforced) And if a calendar OOO overlaps HRIS PTO, the model reflects a single merged OOO period with confidence equal to the max of contributing signals
Slack Status and Device Timezone Change Detection
Given the attendee's Slack status indicates OOO/Travel or Slack presence is Vacation, and/or the attendee's device/session timezone changes and remains stable for the configured persistenceThreshold When these signals are detected Then the system emits normalized entries: TRAVEL_SHIFT for timezone change; OOO_HINT for Slack indicators with default confidence 0.6 And if the device timezone persists past the threshold, the TRAVEL_SHIFT confidence is ≥ 0.8 And if multiple signals conflict, the model selects the highest-confidence signal per time slice and records all contributing sources in provenance[] And clearing Slack status or reverting the device timezone removes or downgrades the hints within 10 minutes
User-Declared Travel Plans with Consent and Sensitivity
Given a user submits a travel plan with start/end, destination timezone, sensitivity level, and sharing consent When the plan is saved Then the model creates a TRAVEL_SHIFT entry overriding other signals for that period with confidence = 1.0 And if sensitivity = private, downstream events and flags omit destination details for viewers without permission And the user can revoke the plan, after which the model entries and any published events derived from it are deleted or compensated within 60 seconds
Detection Service Event Publishing with Idempotency
Given any normalized availability entry is created, updated, or deleted within the detectionWindow When the change is committed Then a DetectionEvent is published to the event bus within 60 seconds with schema fields: eventId, eventType (CREATE|UPDATE|DELETE), userId, effectiveStart, effectiveEnd, timezone, availabilityType, confidence, sensitivity, sources[], sourceEventIds[], correlationId, idempotencyKey And duplicate source deliveries do not result in duplicate downstream events within a 24-hour deduplication window And the service supports event replay according to the configured retention policy and orders events per user by eventTime
Flagging Affected One-Off and Recurring Meetings
Given a normalized availability change intersects scheduled meetings (one-off and recurring instances) within the detectionWindow When the detection service processes the change Then each impacted meeting instance is flagged with: flagId, reason (TRAVEL_SHIFT|OOO), affectedInstanceTime, confidence, suggestedAction (SHIFT|SKIP|KEEP) And for recurring series, only instances within the effective range are flagged and the parent series is annotated with an impactedCount And flags appear in the scheduling UI within 2 minutes and a notification is emitted for downstream scheduling logic And system evaluation on a seeded test set achieves ≥ 95% precision for correctly flagged impacted meetings
Privacy, OAuth Scopes, and Data Retention Enforcement
Given providers are connected and authorization is requested When OAuth consent screens are presented and data is processed Then only least-privilege read scopes are requested per provider (e.g., calendar.read-only, workingLocation.read-only, Slack profile read, HRIS PTO read) and any attempt to use disallowed scopes fails And the user can view and revoke any data source; upon revocation, polling/webhooks cease within 10 minutes and no new data from that source is processed And data retention is enforced: rawSignals older than rawRetentionDays and derivedModel entries older than derivedRetentionDays are purged by a daily job with audit logs And sensitive fields (e.g., destination city, PTO notes) are excluded from events/UI for unauthorized viewers and access attempts are denied and logged
Travel-Aware Reschedule Engine
"As a product manager, I want reschedule options that account for attendees’ local times and fairness so that we keep meetings effective without burdening the same people repeatedly."
Description

Evaluate affected meetings against detected travel/PTO windows and compute minimal-disruption schedule adjustments that preserve cadence and fairness. Generate candidate slots by weighting attendee local hours, ergonomic windows, and equity scoreboard penalties, while honoring required/optional roles, buffers, and resource constraints. Support recurring series logic (single occurrence vs series shift), meeting length constraints, maximum slip thresholds, and hard blackout rules. Provide deterministic, explainable scoring for each candidate with a clear rationale payload for UI and notifications.

Acceptance Criteria
Detect Travel/PTO and Flag Affected Meetings
Given connected calendars and travel/PTO sources are synced and the detection horizon is 14 days When the engine runs on schedule every 6 hours or upon a travel/PTO webhook Then it flags any meeting where a required attendee has PTO overlapping the meeting time or a timezone shift ≥ 2 hours effective by the meeting start And it records for each flagged meeting the source references (event IDs, timezone deltas, attendee IDs) and the effective window And it excludes meetings already flagged and unchanged since the last evaluation to avoid duplicate work
Generate Candidate Slots With Constraints
Given a travel-affected meeting with length L, required attendees (RA), optional attendees (OA), configured ergonomic windows, hard blackouts, buffers, and resource constraints When generating candidate slots Then each candidate preserves length L and includes all RA marked available And each candidate falls within each RA's configured ergonomic window and outside hard blackouts And per-attendee minimum buffer before and after is enforced (default ≥ 15 minutes or user-configured value) And required resources (e.g., VC bridge, room) are available/auto-bookable for the candidate time And the candidate occurs within maximum slip thresholds (one-off: ≤ 48 hours; series: ≤ 20% of recurrence period) And at least 3 candidates are produced if feasible; otherwise a "No viable slot" outcome is returned with enumerated blockers
Deterministic Scoring With Explainable Rationale
Given inputs (attendees, calendars, ergonomic windows, buffers, equity scores, constraints) are unchanged When scoring candidates Then the same candidate set receives identical numeric component scores and ordering across repeated runs And each candidate exposes a score object with components: ergonomic_fit, equity_penalty, cadence_deviation, slip_cost, resource_fit, blackout_risk, and a total normalized score in [0,1] And a rationale payload is produced containing: per-attendee local times and UTC, timezone offsets, PTO/travel references, constraints satisfied, trade-offs, and the equity/ownership impact And deterministic tie-breaking is applied in order: higher ergonomic_fit, lower equity_penalty, earlier UTC start
Fairness and Equity Penalties Applied
Given an equity scoreboard tracking cumulative out-of-window burden and meeting ownership rotation When evaluating and scoring candidates Then penalties increase proportionally for assigning time outside an attendee's ergonomic window based on their cumulative burden And ownership rotates away from the current owner if they owned the most recent occurrence(s) and a viable alternative exists And the selected candidate does not assign out-of-window burden to the same attendee more than 2 consecutive meetings unless no viable alternative exists; if forced, the rationale explicitly lists the forced burden and justification
Recurring Series: Single Occurrence vs Series Shift
Given a recurring series with cadence C and a travel/PTO window W When W affects exactly one upcoming occurrence Then the engine proposes a single-occurrence shift that preserves the original series cadence for future occurrences When W affects ≥ 2 consecutive occurrences or W duration exceeds 25% of C Then the engine proposes a series-level shift that preserves cadence pattern (weekday/time) and stays within maximum slip thresholds And the proposal payload includes: affected occurrence IDs, old/new times, slip deltas, and reversion plan (return to original schedule after W ends)
Required vs Optional Roles and Quorum Handling
Given a meeting defines required roles (R) and optional roles (O) with quorum policy requiring all R When generating and filtering candidates Then only candidates where all R can attend are considered valid If no valid candidates exist within thresholds Then the engine returns either (a) a best-effort option relaxing optional attendance with explicit list of omitted O and reasons, or (b) a "No viable slot" decision with enumerated violated constraints and blockers And the payload clearly separates required vs optional attendance outcomes for UI/notifications
Timezone Correctness, DST, and Performance
Given candidate generation occurs around DST transitions and cross–date-line travel When computing local representations for candidate UTC times Then per-attendee local times and offsets are correct for the meeting date (including DST in effect), and no candidate violates hard blackouts due to offset miscalculation And for a batch of up to 200 travel-affected meetings, the engine returns results within 120 seconds, with per-meeting candidate generation averaging ≤ 1 second And repeated runs on the same inputs yield identical UTC times and local conversions
Preemptive Suggestion & Approval Workflow
"As an engineering lead, I want timely, low-friction reschedule prompts so that I can approve changes quickly and avoid last-minute conflicts."
Description

Proactively surface reschedule suggestions N days before an impacted occurrence via in-app, email, and Slack with one-click actions (Accept, Propose Alternative, Snooze). Allow auto-apply based on policy thresholds (e.g., slip ≤ 30 minutes and no required attendee leaves ergonomic hours). Hold tentative slots when supported, and gracefully handle external attendees by sending ICS proposals. Include deadlines, escalation rules, and fallback behavior when no decision is made. Ensure accessibility and mobile responsiveness for approvals on the go.

Acceptance Criteria
Preemptive Suggestion Delivery Across Channels
Given a meeting occurrence within the next N days is impacted by a detected timezone change or PTO for a required attendee When the trigger time equals N days before the scheduled start (workspace-configurable, default N=5) Then the system generates exactly one reschedule suggestion and delivers it within 2 minutes via in-app, email, and Slack DM to the meeting owner and delegates with Accept, Propose Alternative, and Snooze actions And each notification includes reason, proposed time(s), slip delta in minutes, ergonomic compliance indicator, decision deadline timestamp, and affected attendees And duplicate suggestions are deduplicated across all channels And an immutable audit log entry is recorded with timestamp, detector source, and recipients
Policy-Based Auto-Apply of Minimal Slip
Given workspace policy "Auto-apply if slip <= 30 minutes and no required attendee leaves ergonomic hours" is enabled And a suggestion meets all policy thresholds and no conflicts are detected for required attendees When the suggestion is generated Then the new time is applied automatically within 1 minute without human approval And internal attendees receive updated calendar invites; external attendees receive an ICS proposal email without altering their calendars until accepted And tentative holds (if any) are converted to confirmed for internal attendees and preserved as proposals for externals And a confirmation notification is sent across in-app, email, and Slack with an undo option for 10 minutes And the audit log records the auto-apply decision and policy version used
One-Click Accept Flow
Given a reschedule suggestion is pending and within deadline When the user clicks Accept from any channel (in-app, email action, Slack button) Then the event is updated to the suggested time within 1 minute and all proposed holds are cleaned up And internal attendees receive updated invites; external attendees receive ICS proposals And the original and new times are shown with slip delta and ergonomic status And the action is idempotent; repeated Accepts do not create duplicate updates And the suggestion card/state is closed and marked Accepted across all channels
Propose Alternative Windows with Ergonomic Ranking
Given the user selects Propose Alternative on a pending suggestion When the alternatives modal or page opens Then 3-7 ranked windows are displayed that keep all required attendees within ergonomic hours and avoid repeating inconvenient slots from the last 4 occurrences And each window shows local times for all required attendees, slip delta, fairness score, and conflict count And selecting a window sends proposals and places tentative holds where supported And the decision deadline is preserved or extended per policy, and recipients are notified And if no qualifying windows exist, the user is informed with a reason and offered to widen constraints
Snooze, Deadline, Escalation, and Fallback
Given a suggestion has a decision deadline D When a user clicks Snooze Then the decision deadline extends by the selected interval (e.g., 1h, 4h, 24h) up to a maximum of 48h total deferral And all recipients see the updated deadline consistently across channels And if D passes with no decision, escalation messages are sent to the meeting owner and designated escalation channel, and tentative holds are released And if the suggestion qualifies for auto-apply, it is applied; otherwise the original time is retained and the suggestion is closed as Expired with a summary And all actions are logged with timestamps
Tentative Holds Lifecycle
Given the calendar provider supports tentative holds When suggestions or alternatives are generated Then holds are placed on proposed slots for required internal attendees with a maximum duration of 24h or until decision, whichever comes first And holds never double-book a required attendee over an existing confirmed event And holds are converted to confirmed on Accept or Auto-apply and are removed on Decline or Expiry And for providers without hold support, no placeholder events are created; proposals use ICS without holds
Accessibility and Mobile Approvals
Given any approval surface (web app, mobile web, email action page, Slack dialog) When a user with assistive technologies or on a small screen interacts with the suggestion Then all actionable controls are reachable via keyboard, have ARIA labels, and meet WCAG 2.1 AA contrast And layouts responsively render at 320px width without horizontal scrolling; primary actions are visible without zoom And email buttons include accessible markup and fallbacks; Slack messages include alt text for interactive elements And errors and success states are announced to screen readers and include clear, actionable text
Policy & Preferences Management
"As a workspace admin, I want configurable policies for travel-aware shifting so that reschedules align with our teams’ working norms and compliance requirements."
Description

Provide admin and user-level controls that govern detection sensitivity, ergonomic hours, maximum permissible slip, meeting anchoring preferences, required vs optional attendee rules, blackout dates, and auto-apply thresholds. Support team-specific policies and per-series overrides with clear precedence. Offer user consent controls and visibility into what signals are used. Store policies centrally and expose them to the detection and reschedule engines to produce compliant outcomes.

Acceptance Criteria
Policy Precedence: Series Overrides > Team Policy > User Preference
Given a team policy sets ergonomic_hours=09:00–17:00 local and max_slip=30m, a user preference sets ergonomic_hours=08:00–18:00, and a per-series override sets max_slip=15m When a reschedule is triggered for that series Then the applied policy uses ergonomic_hours=09:00–17:00 and max_slip=15m Given no per-series override exists and team policy conflicts with user preference When a reschedule is triggered Then the applied policy uses team policy values over user preferences Given a per-series override is removed at time T When the next reschedule is triggered after T Then the applied policy reverts to team policy values without requiring service restart and the decision log includes policy_source=team
Ergonomic Hours and Maximum Slip Compliance
Given a meeting originally at 10:00 local for the anchor attendee and max_slip=20m with ergonomic_hours set per required attendees When travel or PTO triggers a shift Then all proposed slots for auto-apply fall within each required attendee’s ergonomic_hours in their local time Given max_slip=20m When no slot within max_slip satisfies all required attendees’ ergonomic_hours Then no auto-apply occurs and a single suggestion is generated with reason=no_compliant_slot Given anchoring preference keep_weekday=true When generating compliant slots Then proposals retain the original weekday unless doing so violates ergonomic_hours for any required attendee, in which case the reason includes violated_constraint=ergonomic_hours
Required vs Optional Attendee Rules Enforcement
Given attendees are tagged required or optional by policy for a series When generating an auto-apply reschedule Then 100% of required attendees must be within ergonomic_hours and free of blackout/holiday conflicts Given at least one required attendee cannot be accommodated within policy constraints When evaluating auto-apply Then auto-apply is blocked and a suggestion is produced with reason=required_attendee_blocked and the blocked attendee list is included Given optional attendees conflict with policy constraints When optional_auto_drop=true in policy Then the proposal may proceed to auto-apply and conflicting optional attendees are marked dropped in the invite update
Blackout Dates and Regional Holidays Adherence
Given team or user-level blackout dates and locale-specific holidays are configured When generating reschedule options Then no proposed time falls within any blackout or holiday for required attendees Given all compliant times within max_slip land on a blackout or holiday for at least one required attendee When evaluating auto-apply Then auto-apply is not performed and a suggestion is produced with reason=blackout_conflict Given only optional attendees have blackout/holiday conflicts When optional_auto_drop=true Then those conflicts do not block auto-apply and affected optional attendees are notified as optional-conflict
Detection Sensitivity and Auto-Apply Thresholds
Given detection confidence=0.85 and auto_apply_threshold=0.80 from effective policy When a travel-induced change is detected Then the reschedule is auto-applied and the decision log includes confidence=0.85, threshold=0.80, decision=auto_applied Given detection confidence=0.79 and auto_apply_threshold=0.80 When a travel-induced change is detected Then only a suggestion is created and no calendar changes are sent Given detection_sensitivity=high (timezone_delta_threshold=1h) in policy When an attendee’s planned timezone delta is 1.5h Then a reschedule is considered; and when detection_sensitivity=low (timezone_delta_threshold=2h) Then the same event does not trigger a reschedule
User Consent Controls and Signal Transparency
Given a user has not granted consent for itinerary_email and device_timezone signals When detection runs Then those signals are not accessed or used, and the decision log lists excluded_signals=[itinerary_email, device_timezone] with reason=consent_missing Given a user grants consent for itinerary_email at time T When detection runs at or after T+5m Then itinerary_email appears in the signals_used list for decisions that reference it and consent_timestamp is recorded Given a user revokes consent for a signal When detection runs within 15m of revocation Then the revoked signal is not used and any cached data from that signal is ignored for new decisions; decisions include reason=consent_revoked Given a user opens the Signals Used view for a decision When the panel loads Then it displays the list of signals with timestamps and sources used in that decision
Central Policy Store and Engine Integration
Given a policy update changes max_slip from 30m to 20m and is saved as version v123 at 12:00:00 UTC When the detection or reschedule engine processes events at or after 12:00:45 UTC Then the effective policy uses max_slip=20m and the decision log includes policy_version=v123 Given the engine requests the effective policy via API When calling GET /policies/effective?series_id={id} Then the response is 200 with precedence-resolved values and includes version and source fields Given the central policy store logs changes When an admin updates any policy field Then an immutable audit entry records who, what, when, and previous_value→new_value Given the policy store is temporarily unavailable When generating a reschedule Then auto-apply is blocked and a suggestion is produced with reason=policy_unavailable; the decision log includes last_policy_fetch_age and no non-compliant changes are applied
Equity Scoreboard Synchronization
"As a recurring meeting owner, I want fairness to be tracked and balanced during reschedules so that no one is consistently disadvantaged by timing changes."
Description

Update the fairness metrics and ownership rotation whenever a shift is proposed or executed, attributing inconvenience scores based on local-time deviation from ergonomic bands and historical burden. Surface fairness impact in suggestions and prevent repeated inconvenience for the same attendees. Persist metrics per series and across series where relevant, and integrate with the existing equity scoreboard UI and reporting.

Acceptance Criteria
Proposed Shift Fairness Preview and Ranking
- Given a meeting series S with attendees A, B, C and existing cumulative burden points [A:5, B:3, C:7], when Travel-Aware Shift generates 3 candidate windows (W1, W2, W3), then for each candidate the UI displays per-attendee predicted inconvenience points, per-attendee delta vs current plan, and the net fairness variance delta for S. - Given multiple candidates, when the preview is rendered, then candidates are ranked by: (1) lowest post-selection standard deviation of cumulative burden across attendees; tie-breakers: (2) lowest total added inconvenience points, (3) smallest absolute time shift in minutes from original slot. - Given a preview, when the organizer has not accepted a candidate, then no metrics are persisted and no rotation pointer changes; a what-if record exists only in memory/cache and expires after 24 hours or upon dismissal. - Given network latency, when the preview loads, then fairness impact numbers render within 1500 ms for up to 8 candidates and 15 attendees.
Executed Shift Commits Metrics and Rotation
- Given a proposed shift candidate Wk is accepted by an organizer, when the reschedule is executed, then per-attendee inconvenience points for the new occurrence are added to their cumulative burden for series S and to their cross-series totals within 2 seconds. - Given ownership rotation is enabled for series S, when the reschedule is executed, then the rotation pointer advances to the next eligible attendee with the lowest cumulative burden among those attending the occurrence; ties are broken alphabetically by attendee id. - Given idempotency, when the same acceptance event is retried within 24 hours with the same series_id, occurrence_id, and candidate_id, then metrics are updated at most once and the operation returns an idempotency indicator. - Given eventing, when metrics are committed, then an equity_update event is emitted containing series_id, occurrence_id, before/after burden per attendee, rotation_before/after, actor_id, and timestamp.
Repeated Inconvenience Guardrails
- Rule: For any attendee i, do not propose a candidate that would place i in an off-hours band (>1.5x penalty) more than 1 time in the last 2 consecutive occurrences of series S unless organizer explicitly overrides. - Rule: For any attendee i across all series, block candidates that would result in i accumulating more than 3 off-hours occurrences in a rolling 30-day window unless organizer explicitly overrides. - Given an override, when an organizer chooses "Allow once" with a required reason, then the candidate may be proposed/executed, the override is logged with reason and actor, and the occurrence still counts toward guardrail tallies. - Given guardrail violations, when suggestions are displayed, then violating candidates are either hidden or visibly demoted with a "Guardrail" badge and cannot be the top-ranked option unless overridden.
Ergonomic Bands and Inconvenience Scoring
- Rule: Ergonomic bands per attendee local time: Ergonomic = 09:00–17:00 (penalty 0/min); Shoulder = 07:00–09:00 and 17:00–20:00 (penalty 0.5/min); Off-hours = 20:00–07:00 (penalty 1.5/min). Weekend multiplier = 2x. Company holiday/PTO multiplier = 3x for the affected attendee if scheduled to attend. - Given a 30-minute meeting at 06:30–07:00 local on a weekday, then inconvenience points = 30 min * 1.5 = 45. - Given a 30-minute meeting at 08:30–09:00 local on a weekday, then inconvenience points = 30 min * 0.5 = 15. - Given a 60-minute meeting at 16:30–17:30 local on a weekday, then inconvenience points = 30 min * 0 + 30 min * 0.5 = 15. - Given a 30-minute meeting at 06:30–07:00 local on a Saturday, then inconvenience points = 30 min * 1.5 * 2 = 90. - Given PTO for attendee A on the meeting day, when A is included as required, then points applied to A for that occurrence use the 3x multiplier unless PTO exclusion is enabled (see Timezone/PTO Adjustment).
Persistence, UI Integration, and Reporting
- Given metrics are updated, when the scoreboard UI is opened for series S, then cumulative burden, last-10-occurrence trend, and current rotation owner render with the new values within 2 seconds of commit. - Given cross-series aggregation, when an occurrence is committed, then attendee-level totals and off-hours counts are persisted under keys (attendee_id, month, org_id) and reflected in the Organization Equity Report API within 5 seconds. - Given a service restart, when the system comes back up, then the last committed metrics for series S and cross-series are intact and match the last equity_update event. - Given CSV export, when an equity report is downloaded, then each row includes series_id, occurrence_id, attendee_id, points_added, cumulative_points_after, band_classification, rotation_owner_after, and timestamp. - Given eventual consistency, when the UI initially shows stale metrics post-commit, then it auto-refreshes to the committed values within 5 seconds without user action.
Timezone and PTO Adjustment in Fairness Attribution
- Given an attendee has a scheduled timezone change effective before the rescheduled occurrence, when scoring candidates, then local-time bands are computed using the post-change timezone for that occurrence. - Given an attendee has PTO overlapping the occurrence, when scoring and rotation are computed, then that attendee is excluded from ownership rotation for that occurrence and receives 0 burden points if PTO exclusion is enabled for the series; the UI displays a "PTO-adjusted" badge. - Given travel-induced slip suggestions, when a candidate reduces the number of attendees in off-hours compared to the original slot, then the fairness preview displays the count reduced and the net variance delta reflecting the improvement. - Given conflicting data (timezone not resolvable), when scoring is attempted, then the system falls back to the attendee’s current timezone, marks the candidate with a "Timezone unverified" badge, and logs a warning without blocking suggestion generation.
Automated Invite Update & Communications
"As an ops coordinator, I want invites and notifications to update automatically with clear context so that everyone stays aligned with minimal manual effort."
Description

Upon approval or auto-apply, update calendar events across providers while preserving conferencing links, agendas, and attachments. Notify participants with a concise rationale (e.g., attendee travel window) and clearly state the new time in each participant’s local timezone. Handle series updates vs single occurrence changes, external guests, room resources, and ICS attachments. Deduplicate notifications with provider emails and ensure a single source of truth in TimeMeld.

Acceptance Criteria
Cross-Provider Calendar Event Update on Approval or Auto-Apply
Given a Travel-Aware Shift reschedule is approved or auto-applied for an existing meeting with attendees on at least two calendar providers When TimeMeld executes the update Then the event start and end times are updated on all connected provider calendars within 60 seconds for 95% of updates and within 5 minutes for 100% And the organizer and attendee event UIDs remain unchanged and SEQUENCE is incremented where applicable And conferencing links, agenda/description content, and file attachments remain unchanged And attendees’ RSVP statuses are preserved across providers And provider API failures trigger retries with exponential backoff up to 3 attempts and a single consolidated alert in TimeMeld if final failure occurs
Preserve Conferencing Links, Agenda, and Attachments
Given a meeting has an existing conferencing link, agenda text, and attachments When a Travel-Aware Shift reschedule is applied Then the conferencing link value remains unchanged And the agenda/description (plain text and HTML) remains unchanged And all previously attached files remain attached on each provider And any attempted modification to these fields by the reschedule process is blocked and logged as an error
Participant Notifications Include Localized New Time and Rationale
Given the event time changes due to a Travel-Aware Shift When TimeMeld sends participant notifications Then each participant receives exactly one notification that includes the new date and time in their detected local timezone with abbreviation and UTC offset (e.g., Tue Sep 16, 10:00–10:30 AM PDT, UTC-7) And the notification includes a concise rationale (e.g., attendee travel or PTO window) And for participants with unknown timezone, the event timezone is shown explicitly and a link to update timezone preferences is provided And links to view the event in TimeMeld and open in native calendar are included And notification delivery succeeds for ≥99% of recipients, with bounces and failures logged and visible in TimeMeld
Series vs Single Occurrence Update Handling
Given the meeting is part of a recurring series When a slip for a single occurrence is approved Then only that occurrence is updated using RECURRENCE-ID and other instances remain unchanged And attendees receive updates only for the affected occurrence And room resources are rebooked only for the affected occurrence When a full-series time change is approved Then all future instances from the effective date are updated, preserving existing exceptions And the series master retains the same UID with SEQUENCE incremented
External Guests and Room Resources
Given the attendee list includes external guests and room resources When the event time is changed by TimeMeld Then external guests receive a standards-compliant update email with a .ics attachment that preserves the same UID and updates SEQUENCE And their prior RSVP status is preserved unless they respond differently And room resources are automatically rebooked at the new time; if unavailable, a configured fallback (e.g., best-fit available room) is selected or the update is blocked with a single actionable alert to the organizer And the final attendee and resource state is consistent between TimeMeld and connected providers
ICS Update Generation and Client Compatibility
Given an attendee requires email-based calendar updates When TimeMeld generates and sends an .ics update Then the .ics conforms to RFC 5545 with METHOD:REQUEST (or CANCEL when applicable), consistent UID, incremented SEQUENCE, correct DTSTART/DTEND (with TZID), and RECURRENCE-ID for single-occurrence changes And major clients (Google Calendar, Microsoft Outlook, Apple Calendar) correctly apply the update in manual validation And the email uses Content-Type text/calendar; charset=UTF-8; method=REQUEST with CRLF line endings and a .ics attachment filename And opening the .ics results in one updated event rather than a duplicate
Notification Deduplication and Single Source of Truth
Given some providers auto-send update emails when events change via API When TimeMeld updates an event and prepares notifications Then each participant receives no more than one human-visible notification per change And TimeMeld suppresses duplicates by disabling provider emails where supported or suppressing its own message when a provider email is detected And TimeMeld’s event record matches provider state (title, time, conferencing link, attendees, attachments) within 1 minute of update completion And a single activity log entry is recorded with initiator (auto or approver), timestamp, affected occurrence(s), and notification count
Audit Trail & Impact Analytics
"As a team lead, I want visibility into what changed and why so that I can trust the system and demonstrate its impact on attendance and fairness."
Description

Record detection signals, suggestion sets, decisions, overrides, and outcomes with timestamps and actors. Provide an auditable history per meeting and series, plus workspace-level analytics on avoided conflicts, average slip size, fairness improvements, and show-rate deltas. Offer export and retention controls aligned with org policy. Expose insights back into the suggestion rationale to build user trust.

Acceptance Criteria
Audit Event Capture for Travel-Aware Shifts
Given a meeting series with key attendees and a travel/PTO signal is detected When TimeMeld generates suggestion sets and a user accepts or overrides a suggestion Then the system records events for detection, suggestion_set_created, decision_accepted|rejected, override_applied, and outcome_finalized including: meeting_id, series_id, workspace_id, actor (system|user id), actor_role, source, ISO8601 timestamp with offset, signal type/window/confidence, suggestion payload hash, selected option And events are immutable, append-only, and ordered by timestamp then sequence_id And 100% of generated suggestions in test data produce a corresponding event within 200ms And querying by meeting_id returns a complete, gapless sequence matching the user-visible flow
Per-Meeting/Series Audit Timeline UI
Given an authorized user opens the Audit Trail for a meeting or series with existing events When the timeline is requested Then a reverse-chronological list renders within 2 seconds for up to 200 events And each row displays timestamp (local and UTC), event_type, actor, summary, and link to details And filtering by event_type and date range returns only matching events and preserves order And pagination loads the next 200 events within 1 second And an unauthorized user receives 403 and no data exposure And field values exactly match stored event payloads (byte-for-byte for IDs, ±0 seconds for timestamps)
Workspace Analytics: Avoided Conflicts, Slip, Fairness, Show-Rate
Given at least 90 days of audit data is available When an admin opens the Analytics dashboard Then the metrics display: avoided_conflicts, average_slip_minutes, fairness_index_improvement, and show_rate_delta with current values And filters for time range, team, organizer, and series update charts and KPIs within 2 seconds And avoided_conflicts equals the count of meetings where a detected conflict was resolved by reschedule removing overlap for all key attendees And average_slip_minutes equals mean |final_start - original_start| in minutes for rescheduled meetings And fairness_index_improvement is computed from the defined equity score method and is reproducible from raw events within 0.5% tolerance And show_rate_delta equals (attendance% post-feature − baseline%) for matched cohorts within 0.5% tolerance
Export and Retention Policy Compliance
Given a workspace retention policy of N days is configured by an admin When current_time exceeds event_time + N days Then purge jobs remove events from primary stores and exclude them from analytics recomputation, with a purge audit event recorded And an admin can export audit logs and analytics in CSV and JSON, scoped by time range, team, series, and organizer And exports exclude purged data and redact personal emails, device identifiers, and precise locations for non-admin roles And export requests up to 1,000,000 rows complete within 5 minutes and are encrypted at rest and in transit And each export generates an audit record including requester, scope, row_count, checksum, and expiry And a DSAR delete request removes subject-linked events within 7 days and logs completion
Suggestion Rationale Transparency in UI
Given a user views a reschedule suggestion for a meeting When they open the "Why this?" panel Then the panel lists top contributing factors with weights (e.g., time zone delta, PTO window, fairness rotation, historical show-rate impact) And provides links to the corresponding audit events for verification And no sensitive PII (e.g., exact travel location) is shown to non-admin users And displayed values (e.g., delta hours, fairness score) match analytics within 0.5 units And the panel loads within 500ms on p50 and 1s on p95 for typical network conditions
Override Attribution and Outcome Tracking
Given an organizer rejects a suggested time and proposes a manual time When the meeting concludes Then the override decision is logged with reason code and optional free text (≤500 chars) linked to the meeting_id and series_id And attendance outcome and tardiness (minutes late by attendee) are recorded And analytics attribute the meeting to the override cohort and recompute show_rate_delta accordingly And the audit timeline displays detection → suggestions → override → final outcome with consistent correlation IDs And events become queryable in APIs and UI within 15 minutes of occurrence

Title Tuner

Auto-rewrites vague, generic subjects into concise, action‑oriented titles with smart tags (e.g., Decision, Review, Retro). Enforces length and clarity guidelines, flags filler words, and highlights the meeting’s purpose at a glance—so recipients instantly know why it matters and whether to attend.

Requirements

Context-Aware Title Generation
"As a product manager scheduling a meeting, I want the system to auto-generate clear, action-oriented title options from my context so that invitees instantly understand the purpose and whether they should attend."
Description

Implement an AI-driven rewrite engine that transforms vague or generic subjects into concise, action-oriented titles informed by meeting context (agenda snippets, attendee roles, project names, recent activity) and TimeMeld metadata. Generate 2–3 ranked options using active verbs and remove filler/hedging language while preserving key entities. Ensure outputs adhere to brand tone and privacy constraints (redact secrets, never store raw inputs beyond session). Provide deterministic regeneration with the same inputs and allow quick accept/edit. Fail gracefully by requesting minimal intent input if context is insufficient.

Acceptance Criteria
Ranked, Action-Oriented Title Options from Rich Context
Given meeting context includes agenda snippets, attendee roles, project names, recent activity, and TimeMeld metadata When the user triggers Title Tuner on a vague subject Then the system returns 2–3 title options ranked by relevance And each option begins with an active verb within the first 3 words And each option includes exactly one smart tag from the configured whitelist (e.g., Decision, Review, Retro) And each option contains zero banned filler/hedging words from the configured list And detected key entities (e.g., product, project, feature, team names) appear verbatim in the options
Deterministic Regeneration with Identical Inputs
Given identical inputs (subject, context, metadata, model version, configuration) within the same session When the user clicks Regenerate Then the system returns the exact same options in the same order with identical ranking scores Given any input changes (subject, context, metadata, model version, configuration) When the user clicks Regenerate Then the system may return different options and includes response metadata indicating the changed inputs
Privacy Redaction and Non-Persistence
Given the input contains secrets or sensitive strings (API keys, tokens, passwords, 16+ digit numbers, SSH keys, env vars) When generating titles Then all such substrings are redacted or masked in any generated output and UI surface And no raw inputs are written to disk, logs, analytics, or long-term storage beyond the active session And telemetry contains only aggregated counts/lengths without raw text And an audit event records that redaction was applied
Graceful Failure with Minimal Intent Prompt
Given context sufficiency score is below the configured threshold When the user triggers Title Tuner Then the system does not generate titles and instead prompts for a one-line intent (3–10 words) with examples When the user submits minimal intent Then the system generates 2–3 options using that intent while preserving any detected entities When the user dismisses the prompt Then the original subject remains unchanged and a non-blocking notice is shown
Quick Accept and Inline Edit Flow
Given 2–3 options are displayed When the user presses 1, 2, or 3 or clicks Accept on an option Then the event title is updated immediately and confirmation appears within 300 ms And an Undo option is available for 5 seconds to revert the change When the user invokes inline edit (Ctrl/Cmd+E or Edit icon) Then the selected option becomes editable and Save applies changes via the calendar API within 500 ms P95
Tagging, Length, and Clarity Enforcement
Rule: Each option starts with a single bracketed smart tag [Tag] drawn from the configured whitelist (must include Decision, Review, Retro) Rule: Title length is between 35 and 70 characters inclusive Rule: No emojis, no exclamation marks, no trailing period, no double spaces, maximum one colon Rule: Contains at least one action verb; contains zero members of the banned filler/hedging lexicon Rule: If no suitable tag can be inferred, default to [Sync]
Smart Purpose Tagging
"As an engineering lead, I want the meeting title to include a clear purpose tag so that everyone can quickly grasp why we’re meeting and prioritize attendance."
Description

Auto-classify the meeting’s purpose and attach standardized tags (e.g., [Decision], [Review], [Retro], [Planning], [Standup], [Interview]) based on text cues, historical patterns, and attendee composition. Support workspace-custom tag taxonomies and synonym mapping, with confidence thresholds and inline confirmation when uncertain. Persist tags to calendar metadata and prepend to titles where supported, ensuring consistency across email subjects, invites, and notifications.

Acceptance Criteria
Baseline Auto-Classification from Content and Attendees
Given a meeting draft contains a title and/or agenda text with purpose cues and an attendee list When the user pauses input for >= 500 ms or saves the draft Then the system assigns a single primary purpose tag from the workspace’s active taxonomy And Then the assigned tag’s confidence score must be >= 0.75 by default; otherwise do not auto-apply (defer to confirmation flow) And Then the tag appears as a visible pill in the composer within 200 ms of assignment And Then reclassification occurs on subsequent edits with a 500 ms debounce and will not overwrite a user-confirmed tag unless the user explicitly changes it
Workspace Custom Tag Taxonomy and Synonym Mapping
Given a workspace has custom tags and synonym mappings configured When classification detects any configured synonym in the title/agenda Then the corresponding custom tag is eligible and may be assigned as primary if it scores highest And Then synonym matching is case-insensitive and matches whole words or phrase boundaries And Then custom tag precedence overrides built-in tags when scores are equal And Then a workspace can define at least 50 custom tags, each with up to 50 synonyms, without increasing classification latency by more than 100 ms per evaluation
Confidence Thresholds and Inline Confirmation Flow
Given the top candidate tag confidence is between 0.50 and 0.74 inclusive When classification completes Then show an inline confirmation with up to 3 candidate tags ordered by confidence and a Confirm and Cancel option And Then no tag is persisted or prepended until the user confirms And Then if the user selects a different candidate and confirms, that tag is persisted and used going forward And Then if the top candidate confidence is < 0.50, show a Select purpose prompt without a pre-selected option
Title Prepending and Surface Consistency
Given a calendar provider that supports editable titles (e.g., Google Calendar, Outlook) When a tag is assigned or confirmed Then prefix the meeting title with [Tag] exactly once And Then idempotency: if the title already starts with [Tag], do not duplicate or reorder tags And Then the prefixed title is reflected identically in the calendar event title, email invite subject, and in-app/notification titles within one sync cycle (<= 60 seconds) And Then for providers that do not allow title edits via API, do not alter the title; still expose the tag in metadata and UI surfaces under the title
Calendar Metadata Persistence and Round-Trip Integrity
Given a tag is assigned or confirmed When the event is saved to the calendar provider Then the tag is persisted as provider-supported metadata and is retrievable via API within 5 seconds And Then subsequent external edits to time, location, or description do not remove or alter the persisted tag And Then the tag survives at least 10 full sync cycles and remains present after organizer or attendee updates (subject to provider metadata capabilities) And Then deleting the event removes the associated tag metadata
Attendee-Composition Signal for Interview Tagging
Given at least one attendee matches configured recruiting signals (e.g., role=Candidate or candidate email domain) and the text contains interview synonyms (e.g., screen, interview, onsite) When classification runs Then [Interview] is assigned as the primary tag with confidence >= 0.75 And Then if interview text cues are absent but attendees match strong recruiting signals (Candidate + Recruiter) and no other tag exceeds confidence 0.60, set [Interview] with confidence >= 0.65 and route to confirmation if < 0.75 And Then if recruiting attendees are removed, re-run classification within 500 ms and remove [Interview] if its confidence drops below threshold
Clarity Linter and Filler Detection
"As an operations manager, I want vague or filler words in my meeting title to be highlighted with better alternatives so that our invites are consistently clear and actionable."
Description

Provide a real-time linter that flags vague phrases (e.g., "sync", "touch base", "misc"), passive constructions, and redundant words, offering concise replacements and examples. Surface a clarity score with pass/fail thresholds and inline suggestions; allow one-click apply for fixes. Respect admin-enforced rules, support user overrides with justification, and maintain accessibility (keyboard-first, screen-reader friendly).

Acceptance Criteria
Real-time Detection and Flagging of Vague, Passive, and Redundant Phrases
Given the title input contains any vague phrase, passive construction, or redundant word, When the user stops typing for ≥200 ms or the field loses focus, Then each offending span is flagged inline with a category indicator. Given the title contains no issues, When detection runs, Then no flags are shown. Given a title of up to 120 characters, When detection runs, Then initial flags render within 150 ms on a median device. Given multiple issues are present, When detection runs, Then all issues are flagged with non-overlapping highlights.
Inline Suggestions and One-Click Apply with Undo
Given a flagged item is focused or clicked, When the suggestion popover opens, Then it displays at least one concise replacement and one short example. Given the suggestion popover is open, When the user activates Apply on a suggestion, Then the replacement is inserted, the caret position is preserved (±1 character), and flags and score recompute within 300 ms. Given two or more flagged items exist, When the user activates Apply All, Then all visible suggestions are applied in one operation and can be reverted in a single undo. Given a replacement was applied, When the user presses Ctrl/Cmd+Z or clicks Undo within 5 seconds, Then the title reverts to its prior state and prior flags are restored.
Clarity Score and Pass/Fail Threshold
Given a title is present, When detection runs, Then a clarity score from 0 to 100 is displayed and updates within 300 ms of input changes. Given the default pass threshold is 80 unless overridden by admin, When score ≥ threshold, Then status shows Pass; When score < threshold, Then status shows Fail. Given Fail status is shown, When the user focuses the status indicator, Then the top reasons (up to 3) are listed with links to flagged locations. Given the title contains no issues, When detection runs, Then the score is 100 and status shows Pass.
Admin-Enforced Rules Compliance
Given an admin has configured banned phrases, When a banned phrase is present in the title, Then the corresponding flag cannot be dismissed and saving/sending is blocked with an admin policy message. Given an admin has configured a minimum clarity score, When the current score is below that minimum, Then saving/sending is blocked and the UI explains the minimum required score. Given admin rules are updated, When the user loads the composer or refocuses the title field, Then the latest rules are applied without requiring a page reload.
User Override with Justification and Audit
Given org policy permits overrides, When a save/send is blocked by admin rules, Then an Override with justification control is visible and enabled only after ≥10 characters of justification are entered. Given the user submits an override, When the action completes, Then the title is saved/sent and an audit record is created capturing user ID, timestamp, title text, violated rules, and justification. Given org policy disables overrides, When a save/send is blocked, Then no override option is displayed.
Accessibility: Keyboard-First and Screen-Reader Friendly
Given only a keyboard is used, When navigating the title field and lint suggestions, Then all flags and actions are reachable via Tab/Shift+Tab and actionable via Enter/Space; Escape closes popovers and returns focus to the trigger. Given a screen reader is active, When flags are created, Then the number of issues is announced; When a suggestion popover opens, Then its role, name, and item count are announced; each action has an ARIA label describing the replacement. Given an issue highlight is rendered, When assessed for contrast and redundancy, Then it meets WCAG 2.1 AA contrast (≥4.5:1) and does not rely on color alone to convey meaning (icon/text present). Given a suggestion is applied, When focus behavior is evaluated, Then focus remains in the title field adjacent to the replaced text.
Length and Client Compatibility Guardrails
"As a remote teammate, I want the title to display cleanly across calendar and email clients so that I can read the full purpose at a glance without truncation or garbled characters."
Description

Enforce title length and readability guidelines with a live character counter and green zone tuned for common clients (Google/Outlook/Apple Calendar, mobile notifications, email subjects). Simulate truncation across clients and locales, prevent emoji/special-character rendering issues, and automatically shorten with smart abbreviations when limits are exceeded. Provide previews for each channel before commit.

Acceptance Criteria
Live Counter and Green Zone Across Selected Clients
Given a user is drafting a meeting title in Title Tuner and has at least one client/channel selected When the user types, deletes, pastes, or uses IME composition Then the live counter updates within 100 ms per input event using Unicode grapheme cluster counting And the counter color reflects the most conservative selected client’s recommended range (green), warning range (yellow), or over-limit (red) And a tooltip displays each selected client’s recommended and hard limits from the client profile configuration And if the title exceeds any selected client’s hard limit, an inline error names the client(s) and the overage count And undo/redo maintains an accurate counter with no desynchronization
Per-Client, Per-Locale Preview and Truncation Simulation
Given a draft title, selected clients/channels, and a chosen locale When the user opens Previews Then a preview card is shown for each selected client/channel with its rendering width and truncation rules applied And the simulated visible length matches the client profile configuration for the chosen locale And truncation uses the configured ellipsis character and position (end or middle) per client And RTL and CJK text are rendered with correct direction and line-breaking in the preview And changing locale updates all previews consistently And automated tests with fixture titles (EN, DE, JA, AR) match approved snapshots
Emoji and Special-Character Compatibility Warnings and Fallbacks
Given the draft title contains emoji or special characters And at least one selected client marks any of those characters as unsupported or risky When validation runs (on change or on preview) Then a warning lists the exact characters and the affected clients And the preview shows the fallback rendering (replacement, removal, or text alias) per client profile And the system normalizes the title to Unicode NFC and strips zero-width/invisible control characters And bidirectional override characters are preserved only when required and are escaped in ICS output And saving is blocked until the user accepts replacements or explicitly overrides with confirmation
Smart Auto-Shortening to Meet Most-Conservative Limit
Given the title exceeds the most conservative hard limit among selected clients And Auto-Shorten is enabled or the user clicks Shorten When auto-shortening runs Then the system applies only allowed transformations from the abbreviation ruleset (e.g., remove filler words, compress dates, standard abbreviations, collapse whitespace) And the leading smart tag (e.g., [Decision], [Review]) and bracketed content are preserved unmodified And proper nouns detected from the organization dictionary are not abbreviated And the resulting title length is less than or equal to the most conservative hard limit And a before/after diff is displayed with Undo available And analytics record the action with old/new lengths and transformations applied
Readability Guardrails and Filler-Word Flagging
Given a draft title When readability checks run Then the title is flagged if it violates configured rules (max words, punctuation density, passive-voice/filler stoplist, duplicate spaces) And flagged filler words are underlined with one-click replacements And the green zone is only achieved when both length and readability rules pass for all selected clients And accessibility is met: counter and flags are announced via ARIA live regions and color is not the sole indicator
Pre-Commit Multi-Channel Preview and Explicit Override
Given the user clicks Apply Title When any selected client is over its hard limit or has unresolved compatibility warnings Then a pre-commit modal displays previews for each selected channel with pass/warn/fail status And the user can proceed only after resolving issues or providing an explicit override reason And on proceed, the final title applied is exactly the one shown in previews And the decision (resolved vs override), timestamp, and affected clients are logged for audit
Workflow Integration and Auto-Propagation
"As a scheduler, I want the improved title to automatically update everywhere the meeting appears so that I don’t have to edit multiple places and risk inconsistencies."
Description

Seamlessly inject the tuned title and purpose tag into TimeMeld’s scheduling flow: proposed windows, final invites, ICS attachments, email subjects, and Slack/Teams notifications. Keep titles synchronized if changes occur post-send, de-duplicate notifications, and respect user permissions. Provide a preview panel and confirm before propagating edits to existing events.

Acceptance Criteria
Tuned Title in Scheduling Proposals
Given a meeting draft with a vague subject and selected participants And the Title Tuner generates a tuned title and purpose tag When the user opens the Proposed Windows screen and sends proposal emails Then the proposals UI displays the tuned title and purpose tag on each proposal card And the proposal email subject equals the tuned title prefixed with the purpose tag And the proposal email body header shows the tuned title And the tuned title in the subject is 60 characters or fewer And the tuned title is used consistently across all proposal variants And the proposed time windows remain unchanged by title tuning
Final Invites and ICS Propagation
Given a meeting is finalized from proposals and a tuned title with purpose tag exists When TimeMeld creates calendar invites and generates ICS attachments Then the calendar invite title equals the tuned title And the outbound email subject equals the tuned title And the ICS file contains SUMMARY set to the tuned title And the ICS file contains a purpose indicator (CATEGORIES or X-PURPOSE) set to the purpose tag And exactly one invite email is sent per attendee for the final event creation
Slack/Teams Notifications Include Title Without Duplicates
Given Slack and/or Microsoft Teams integrations are configured When proposals are sent or a final invite is created or updated Then one notification per connected channel is posted containing the tuned title and purpose tag in the first line And no duplicate notification is posted for the same event update within a 60-second coalescing window per channel And if both Slack and Teams are connected, each receives exactly one notification And subsequent updates within the coalescing window are added as a thread/update to the original message rather than a new post
Post-Send Title Edit Auto-Propagation
Given an event with invites has already been sent and a tuned title exists And the user has permission to edit the event When the tuned title is updated in TimeMeld after send Then updated calendar invites are issued with incremented iCalendar SEQUENCE and the new title within 2 minutes And proposal pages, invite titles, email update subjects, ICS attachments, and Slack/Teams messages all reflect the new title within 2 minutes And recipients receive a single update per channel for this title change And no stale titles remain in TimeMeld UI or outbound artifacts after propagation completes
Permission-Gated Title Propagation
Given meeting roles include Owner, Editor, and Viewer and ownership can rotate via the equity scoreboard When a Viewer attempts to save and propagate a tuned title Then the action is blocked with an Insufficient permission message and no propagation occurs When the current Owner or an Editor attempts the same action Then propagation succeeds And when ownership rotates, the new Owner gains propagation rights and the former Owner loses them immediately And all permission checks and outcomes are recorded in the audit log
Preview and Confirm Before Updating Existing Events
Given there are existing proposals or invites referencing the current title When a user clicks Save on a changed tuned title Then a preview panel appears listing channels to be updated (Proposals UI, Final Invites, ICS, Email Subject, Slack, Teams) with counts of affected items And the panel shows a diff of old vs new title and purpose tag And the primary action is Confirm and Propagate and the secondary action is Cancel And no propagation occurs until the user confirms And if no existing items will be affected, the preview panel is skipped and the change is saved locally only
Failure Handling and Partial Propagation Recovery
Given propagation to multiple channels is initiated When any channel returns an error or times out Then the system retries up to 3 times with exponential backoff (30s, 60s, 120s) And no duplicate outward notifications are sent during retries And after final retry failure, the user is notified with per-channel failure details and a Retry option And successfully updated channels remain updated, and the event is marked Out of sync until all channels succeed And all failures and retries are recorded in the audit log
Admin Policy Controls and Custom Guidelines
"As a workspace admin, I want to configure and enforce title guidelines so that meeting titles across the company remain consistent and purposeful."
Description

Enable workspace admins to define title policies: required/allowed tags, banned words, minimum clarity score, preferred verb list, and length thresholds. Support team-level overrides, enforcement modes (warn/block), and import/export of rules. Provide audit reports on adherence and exceptions to drive org-wide clarity standards.

Acceptance Criteria
Workspace Admin Configures Global Title Policy
Given a workspace admin with access to Policy Settings When they define required_tags=[Decision, Review], allowed_tags=[Decision, Review, Retro], banned_words=[sync, TBD], min_clarity=75, preferred_verbs=[Decide, Review, Plan], length_min=30, length_max=80 Then the policy saves successfully, is assigned a new version_id, records actor and timestamp, and is retrievable via UI and API Given a policy where required_tags contains a tag not present in allowed_tags When the admin attempts to save Then validation fails with error code POLICY_CONFIG_INVALID and a message identifying the offending field(s) Given any policy change When saved Then the new policy is enforced across the workspace within 30 seconds and an audit log entry is created with before/after diff
Tag Rules Enforcement (Required/Allowed Smart Tags)
Given a draft meeting title without all required tags When the organizer tries to apply or save the title Then Title Tuner surfaces a policy message listing missing tags and, in Warn mode, allows proceed with warning; in Block mode, prevents save with error code POLICY_TAG_REQUIRED Given a draft meeting title containing a tag not in the allowed list When validation runs Then a policy message identifies disallowed tags and, in Warn mode, suggests allowed alternatives; in Block mode, prevents save with error code POLICY_TAG_NOT_ALLOWED Given tag tokens in the title with varying case or leading/trailing whitespace When validation runs Then detection is case-insensitive and trims whitespace Given the title is submitted via API When it violates tag rules Then the API responds with HTTP 422 and the corresponding policy error code and details
Lexical Rules Enforcement (Banned Words & Preferred Verbs)
Given a policy with banned_words=[sync, catch-up] When a title contains any banned word as a whole word (case-insensitive) Then Title Tuner flags the offending tokens and, in Warn mode, highlights and suggests replacements; in Block mode, prevents save with error code POLICY_BANNED_WORD Given a policy with preferred_verbs=[Decide, Review, Plan] When the title’s leading verb does not match any preferred verb (case-insensitive, accounting for common inflections) Then the system suggests the top 3 preferred verb rewrites; in Block mode, a preferred verb must be applied before save Given a title generated by Title Tuner auto-rewrite When lexical rules are violated Then the generator proposes a compliant alternative via a single-click “Apply suggested rewrite” action
Clarity and Length Thresholds Enforcement
Given a policy with min_clarity=75 and length thresholds 30–80 characters (inclusive) When a title scores below 75 or is outside the length range (measured on the rendered title including smart tags) Then Title Tuner shows the current score/length, the target thresholds, and specific improvement tips; in Warn mode, proceed is allowed with a visible warning; in Block mode, save is prevented with error code POLICY_THRESHOLD_NOT_MET Given the user edits the title When changes are made Then clarity score and length indicators update within 200 ms of a keystroke and validation re-evaluates on each change and on submit Given API submission of a title violating thresholds When validated server-side Then the API returns HTTP 422 with error code POLICY_THRESHOLD_NOT_MET and numeric details {score,length,min_clarity,length_min,length_max}
Team-Level Overrides and Policy Resolution
Given a workspace default policy and a team override for Engineering When an organizer belonging to Engineering edits a title Then the Engineering team policy is applied; if a setting is not specified in the team override, the workspace default for that setting is used Given an organizer who changes the meeting’s team context from Engineering to Product When the team is switched Then the active policy re-resolves immediately and validation results update to reflect the Product team policy Given an organizer is a member of multiple teams When creating a meeting Then the policy of the explicitly selected team for the meeting is applied; if none is selected, the user’s primary team is used; if no team exists, the workspace default applies
Policy Import/Export with Validation and Versioning
Given an admin with Policy Settings access When they export the current policy Then a downloadable JSON and YAML file is produced containing schema_version, version_id, updated_at, updated_by, and the full policy payload Given an import file that violates the schema (e.g., min_clarity > 100, unknown tag) When the admin attempts import with Dry Run enabled Then validation fails with a line/field-specific error and no changes are applied Given a valid import file When the admin imports with Apply enabled Then the policy is updated atomically to a new version, an audit entry records the diff, and rollback to the previous version is available Given export followed by immediate import with no edits When applied Then round-trip integrity holds and the resulting policy equals the original
Audit Reporting of Policy Adherence and Exceptions
Given policy enforcement is active When viewing the Audit Reports for a selectable date range Then the report displays counts and percentages of compliant vs non-compliant titles by team and organization-wide, and lists exceptions with timestamp, actor, policy version, violation type, and enforcement mode Given a report view When filters are applied (team, violation type, enforcement mode, date range) or results are exported Then results update within 2 seconds and CSV export downloads with the applied filters Given access control rules When a non-admin attempts to view audit reports Then access is denied with HTTP 403 in API and a "You don’t have access" UI state Given a large dataset (≥10,000 validations in range) When generating the report Then the first page loads within 5 seconds and pagination is available
Versioning, Audit, and Revert
"As a team lead, I want to see what changed in a meeting title and revert if needed so that I can maintain accuracy and accountability."
Description

Maintain a version history capturing original and tuned titles, applied rules, author, timestamp, and rationale. Show diffs, allow one-click revert, and record change logs for compliance. Expose lightweight analytics on adoption and manual overrides to inform ongoing improvements.

Acceptance Criteria
Auto-Version Capture on Title Tune Apply
Given a user accepts a Title Tuner suggestion for a meeting When the user clicks Apply or saves the tuned title Then the system creates a new version record with fields: version_id (incremented), meeting_id, original_title, tuned_title, rules_applied [array], actor_id, actor_type (user|system), timestamp (UTC ISO 8601), rationale, action_type (tune|manual_edit|revert) And each required field is non-empty and persisted And the new version is immediately retrievable via the meeting’s Version History within 1 second
Diff Visualization Between Any Two Title Versions
Given a meeting has at least two title versions When a user opens Version History and selects any two versions Then the UI displays a word-level diff highlighting additions (green) and deletions (red) and ignores whitespace-only changes And the diff renders within 500 ms for histories up to 50 versions And the user can switch baseline and comparison versions without page reload
One-Click Revert Creates New Version and Preserves Audit Trail
Given a user with edit permission views Version History When the user clicks Revert on a prior version and confirms Then the current title updates to exactly match the selected version And a new version is created with action_type=revert, actor_id captured, timestamp (UTC), and rationale (auto “Reverted to vX” plus optional user note) And Version History shows the revert as the latest version number And no prior version records are modified or deleted
Lightweight Analytics: Adoption and Manual Overrides
Given an authorized user opens Title Tuner Analytics with a date range filter When data is loaded Then the dashboard shows Adoption Rate (%) = (count of accepted tuner suggestions without subsequent manual edits within 24h) / (count of suggestions shown) for the period And shows Manual Override Rate (%) = (count of manual edits or reverts within 24h of a tuner apply) / (count of tuner applies) And metrics are available per workspace and per team with filterable dimensions And data latency does not exceed 60 minutes
Compliance Change Log Export (CSV)
Given a workspace admin requests a change log export for a date range When Export CSV is clicked Then the system generates a CSV with columns: version_id, meeting_id, previous_title, new_title, rules_applied, actor_id, actor_type, timestamp_utc, rationale, action_type And the export covers all version events in the range and preserves order by timestamp And the download starts within 30 seconds for up to 100k records
Access Control for Version History and Analytics
Given a user attempts to view a meeting’s Version History or Title Tuner Analytics When the user lacks the required permission Then the system returns 403 Forbidden and shows no event metadata or counts And authorized users (meeting organizer, editors, workspace admins) can access full details And all access attempts are logged with user_id, resource_id, outcome, and timestamp
Rationale Capture and Validation for All Version Events
Given any version event is created (tune, manual_edit, revert) When the event is saved Then rationale is auto-generated for tune events summarizing applied rules in <= 240 characters And rationale is optional free text for manual_edit and revert events and limited to 240 characters; inputs are sanitized to remove HTML/script And events with rationale exceeding the limit are rejected with a validation error

Agenda Cards

Builds a crisp, time‑boxed agenda from micro‑cards (topic, owner, expected outcome, minutes). Suggests realistic durations, limits bloat to the essentials, and formats clean bullets in the invite—creating shared expectations and tighter, on‑time meetings.

Requirements

Micro-Card Agenda Builder
"As a meeting organizer, I want to quickly create and arrange micro-cards with topic, owner, expected outcome, and minutes so that everyone shares clear expectations and we stay on time."
Description

Provide an editor to create, edit, and reorder agenda micro-cards with required fields: Topic (text), Owner (person), Expected Outcome (short text), and Minutes (integer). Enforce field validation, character limits, and positive time values. Support drag-and-drop ordering, keyboard shortcuts, quick-add, and templates per meeting type. Auto-sum total minutes and display remaining/overage against the scheduled meeting length from TimeMeld. Persist drafts with autosave, handle offline edits with local caching and conflict resolution on reconnect, and associate agendas to a specific calendar event. Ensure accessibility (WCAG AA), responsive layout, and minimal clicks to build a crisp, time-boxed agenda.

Acceptance Criteria
Create and Validate Agenda Micro-Cards
Given I am in the agenda editor When I create a micro‑card without a Topic, Owner, Expected Outcome, or Minutes Then the missing field(s) show inline errors, are announced to screen readers, and the card cannot be added Given I enter a Topic longer than 120 characters or an Expected Outcome longer than 180 characters When I attempt to add or save the card Then I see a character‑limit error and the field is truncated only after I confirm the change Given I enter Minutes that are non‑integer, zero, or negative, or greater than 240 When I move focus away from the Minutes field Then the field shows an error stating “Enter 1–240 whole minutes” and prevents save until corrected Given I correct all invalid fields When I submit/add the card Then the card is added successfully with values persisted and visible on reload
Reorder Cards via Drag-and-Drop and Keyboard
Given an agenda with at least 5 micro‑cards When I drag one card to a new position and release Then the list reflects the new order, the position is announced to assistive tech, and the order persists after reload Given focus is on a card handle When I press Shift+Alt+Up or Shift+Alt+Down Then the card moves up or down one position respectively and the new index is announced Given I reorder multiple cards When I go offline and reload the editor Then the most recent local order is restored and later syncs to the server on reconnect
Auto-Sum Minutes and Display Remaining/Overage
Given the linked meeting length is 45 minutes from TimeMeld When my card Minutes total 40 Then a Remaining indicator shows 5 minutes (green, aria‑labelled) and updates within 200 ms of the last edit Given my card Minutes total exactly 45 When I stop editing Then Remaining shows 0 minutes (neutral state) and no warning is displayed Given my card Minutes total 52 When the total is computed Then an Overage indicator shows +7 minutes (red, aria‑labelled with explanation) and is included in the screen reader live region Given I enter a Minutes value of 0 or a negative number When the total is recalculated Then the field is rejected with an error and excluded from the total until corrected
Autosave Drafts and Offline Edit Sync
Given I edit any field on a card When I stop typing for 2 seconds Then an autosave occurs and the UI shows “Saved” within 500 ms after the save completes Given I lose network connectivity while editing When I continue to add or edit cards Then an offline banner appears, all changes are cached locally, and no data is lost on refresh or app restart Given the app reconnects and the remote agenda has not changed since my last sync When autosync runs Then all local changes are uploaded within 5 seconds and the “All changes synced” status is shown Given the app reconnects and the remote agenda has changed since my last sync When autosync runs Then I am shown a conflict dialog listing conflicting cards/fields with options to Keep Local, Keep Remote, or Merge per card, and no data is discarded until I confirm a choice
Associate Agenda to Calendar Event
Given I open the event picker When I select a TimeMeld calendar event Then the agenda stores the event ID, shows the event title/timezone on the agenda header, and persists the association on reload Given the associated event duration changes in TimeMeld When I reopen the agenda Then the remaining/overage calculation updates to reflect the new duration Given the associated event is deleted or becomes inaccessible When I open the agenda Then I see a warning that the event is missing and I can re‑associate the agenda to a different event without losing cards
Templates and Quick-Add for Meeting Types
Given I choose the meeting type “Sprint Planning” When I apply its template Then default micro‑cards (with Topics, Expected Outcomes, and suggested Minutes) are inserted in the documented order and total Minutes do not exceed the event duration Given the quick‑add input is focused When I enter “Topic | Owner | Outcome | Minutes” and press Enter Then a new card is created with parsed values; if Minutes is omitted, 5 minutes is suggested; if Owner is not found, an inline resolver prompts me to select a person Given I press N anywhere in the editor (not in a text field) When the shortcut is handled Then a new empty card is added and focused for immediate typing
Accessibility, Responsiveness, and Efficiency
Given I navigate using keyboard only When I add, edit, reorder, delete cards, apply a template, and resolve errors Then all controls are reachable and operable without a mouse, focus order is logical, and changes are announced via ARIA live regions (WCAG 2.1 AA) Given I view the editor at 320, 375, 768, 1024, and 1440 px widths When the layout loads Then all core functions are available without horizontal scroll at ≤375 px, hit targets are ≥44×44 px, and text has contrast ≥4.5:1 Given I start from an empty agenda for a 45‑minute meeting When I use a template and quick‑add to create 4 fully populated cards Then I can complete this in ≤60 seconds and ≤12 clicks (excluding typing), and the minutes total is within ±5 minutes of the event duration
Smart Duration Suggestions
"As a meeting organizer, I want realistic duration suggestions per agenda item so that the agenda fits the booked time without overruns."
Description

Suggest realistic minutes per agenda card using heuristics that consider meeting length, number of items, historical actuals from prior meetings, participants’ time zones (fatigue windows), and meeting type. Provide inline suggestion chips and one-click "Apply" for each card and "Fit to Slot" to rebalance all items to fit the booked window. Recompute suggestions when items are added, removed, or reordered. Allow full manual override with an explanation tooltip for transparency. Respect privacy by using aggregated, anonymized historical metrics. Log actuals post-meeting to continuously improve suggestions.

Acceptance Criteria
Inline Suggestion Chips and One-Click Apply
Given an agenda with at least one card and a booked meeting window When the agenda loads Then each card displays a suggestion chip with a minute value if a suggestion is available, or a neutral "No suggestion" state if not And clicking Apply on a chip sets the card's duration to the suggested value and updates the chip state to "Applied" And an undo action is available for at least 10 seconds after Apply And the applied value persists across page reloads And Apply is disabled when no suggestion exists or the suggestion is out of allowed bounds (below 1 or above meeting length)
Fit to Slot Rebalance Across All Agenda Cards
Given an agenda with N cards and a booked meeting window of T minutes And zero or more cards have manually entered durations (locked) When the user clicks Fit to Slot Then the sum of all card durations equals exactly T And manually entered durations remain unchanged And each non-locked card's duration is adjusted to an integer minute >= 1 And if T is less than the sum of locked durations, a blocking error explains the conflict and no changes are applied And the rebalancing completes within 1 second for agendas up to 50 cards
Auto-Recompute on Add/Remove/Reorder
Given an agenda with computed suggestions When the user adds, removes, or reorders cards Then suggestions for all non-overridden cards recompute automatically And the recompute completes within 1 second for up to 20 cards (and within 2 seconds for up to 100 cards) And manual overrides are not changed by recompute And the UI indicates which suggestions were updated during the recompute
Manual Override with Transparent Explanation and Persistence
Given a card with a suggested duration When the user manually enters a duration value Then the value is validated as a positive integer between 1 and the meeting length and saved And the manual value persists across page reloads, recomputes, and is treated as locked by Fit to Slot And the user can revert to the latest suggestion with a single click And when the user opens the explanation tooltip, it lists the key factors considered (e.g., meeting length, number of items, meeting type, historical actuals, participant fatigue windows) and how they influenced the suggestion And the tooltip contains no personally identifiable information and is accessible via keyboard and screen readers
Heuristic Sensitivity to Meeting Context (Length, Items, Type, Fatigue)
Given two otherwise identical agendas where meeting length doubles When suggestions are computed Then the total suggested minutes across cards increases by 80%–120% relative to baseline Given two agendas with the same meeting length but double the number of items When suggestions are computed Then the average suggested minutes per card decreases by 40%–60% relative to baseline Given participants' local times are shifted so that at least 50% fall into defined fatigue windows for the meeting time When suggestions are computed Then cards owned by fatigued participants receive suggested durations at least 10% lower than their baseline suggestions Given the meeting type is changed (e.g., from Status Update to Design Review) When suggestions are computed Then at least one card's suggested duration changes and the total suggested minutes changes by at least 10% relative to baseline
Privacy-Safe Use of Historical Data
Given the system computes suggestions using historical meeting data When the eligible cohort for a context has fewer than 5 qualifying meetings Then historical metrics are withheld and non-historical heuristics are used And no API or UI exposes raw per-user actual durations And stored metrics used for suggestions contain no direct identifiers and meet k-anonymity threshold k >= 5 And each suggestion computation records a log entry with cohort size and whether the privacy threshold was applied
Post-Meeting Actuals Logging for Continuous Improvement
Given a scheduled meeting with agenda cards ends When up to 5 minutes have elapsed after the scheduled end time Then the system records actual durations per card from captured timestamps or final user edits And if the meeting is canceled or has no activity, no actuals are logged And aggregated actuals are incorporated into the suggestion model in the next nightly update And the write success rate for actuals logging is at least 99.9% over a rolling 7-day window with retries for transient errors
Bloat Guardrails & Fit Check
"As a meeting organizer, I want guardrails that prevent bloated agendas so that we focus on the essentials and finish on time."
Description

Prevent overstuffed agendas by providing a live time budget bar, overage warnings, and limits configurable per meeting type (e.g., max items, minimum minutes per item). Enable tagging items as Essential or Optional and offer an Auto-Trim action that deprioritizes or compresses optional items to fit the timebox. When overage occurs, present actionable options (compress evenly, drop optional items, extend meeting by X minutes via TimeMeld reschedule). Ensure changes maintain readability and preserve expected outcomes.

Acceptance Criteria
Live Time Budget Bar Accuracy and Sync
Given a meeting timebox of 30 minutes and three agenda items of 10, 10, and 5 minutes, When the agenda is displayed, Then the time budget bar shows 25 min planned, 5 min remaining, and approximately 83% fill. Given I change an item’s duration by +3 minutes, When I blur the input or stop typing for 300 ms, Then the time budget bar recalculates within 300 ms and reflects the new total. Given I add or remove an agenda item, When the change is saved, Then the bar updates totals and percentage within 300 ms. Given the sum of durations equals the timebox, When the bar renders, Then it shows 0 min remaining and 100% fill without an overage warning. Given the sum exceeds the timebox by X minutes, When the bar renders, Then it displays "Over by X min" and switches to the overage state.
Overage Threshold Warnings and Visual States
Given planned minutes are between 90% and 99% of the timebox, When viewing the agenda, Then a non-blocking warning state labeled "Approaching timebox" with yellow styling and a tooltip is shown. Given planned minutes are >= 100% of the timebox, When viewing the agenda, Then an "Over by X min" state with red styling and an alert icon is shown. Given a screen reader user, When the state changes to approaching or overage, Then an aria-live region announces the exact message within 1 second. Given a warning is shown, When planned minutes drop below 90%, Then the warning clears immediately and the component returns to the neutral state.
Meeting-Type Guardrail Configurations Persist and Enforce
Given meeting type "Sprint Planning" has max items = 8 and min minutes per item = 3 configured, When a user selects this meeting type, Then the agenda composer enforces these limits. Given 8 items already exist for "Sprint Planning", When the user attempts to add a 9th item, Then the add action is prevented and an inline message indicates the max items limit for this meeting type. Given an item duration is set below the configured minimum, When the field loses focus, Then the value auto-corrects to the minimum and a hint explains the constraint. Given a different meeting type without custom limits is selected, Then system defaults are applied and enforced. Given the user returns to compose another meeting of the same type, Then the configured limits persist across sessions.
Essential vs Optional Tagging Behavior
Given an agenda item exists, When the user toggles its tag to Optional, Then the item displays an "Optional" badge and becomes eligible for Auto-Trim dropping. Given an agenda item is tagged Essential, When Auto-Trim runs, Then the item is never dropped and its minutes are not reduced below the configured minimum. Given the agenda list contains a mix of tags, When viewed, Then a summary shows counts of Essential and Optional items. Given the invite preview is generated, When tags are present, Then Optional items are labeled "(Optional)" without changing their Topic or Expected Outcome text.
Auto-Trim Options: Compress Evenly and Drop Optional
Given total planned minutes exceed the timebox by X, When the user clicks Auto-Trim, Then a dialog presents options: Compress evenly, Drop optional items, and Cancel. Given the user selects Compress evenly, When applied, Then each item's minutes are reduced proportionally to fit the timebox, rounded to whole minutes, without setting any item below the configured minimum; Essential items are reduced only after all Optional items reach their minimums. Given the user selects Drop optional items, When applied, Then Optional items are removed from the agenda starting from the bottom of the list until the plan fits; removed items appear in a Dropped list with Restore controls. Given Auto-Trim is applied, When reviewing the changes, Then a preview shows before/after minutes per item and the user can Undo to restore the exact prior state. Given all Optional items are dropped and all items are at their minimum minutes and overage still exists, Then the dialog displays the irreducible overage amount and offers Extend meeting as the primary action.
Overage Action: Extend Meeting via TimeMeld Reschedule
Given an overage exists, When the user selects Extend meeting by X minutes, Then TimeMeld opens a reschedule flow pre-filled with the new duration (original + X). Given attendee calendars and timezone constraints, When TimeMeld proposes new windows, Then at least three timezone-weighted slots within the next five business days are shown that avoid hard conflicts for required attendees. Given the user confirms a suggested slot, Then the calendar event updates to the new end time, all invitees receive an updated invite with the formatted agenda, and the time budget bar recalculates with no overage. Given the user cancels the reschedule flow, Then no calendar changes are made and the agenda remains in the overage state.
Readability and Outcomes Preservation After Trimming
Given any automatic change (compress or drop) is applied, When viewing the agenda and invite preview, Then Essential items retain their Topic and Expected Outcome text exactly as entered. Given Optional items are compressed (not dropped), When applied, Then only the Minutes field changes; Topic and Expected Outcome text remain unchanged. Given the invite description is generated, Then each agenda item is formatted as a single bullet: "• [min] [topic] — [owner] (Expected outcome: [outcome])" with no truncation or ellipses for Essential items. Given Auto-Trim drops Optional items, When the invite is generated, Then the invite includes a final bullet indicating the count of optional items not scheduled and references where to view them in TimeMeld. Given the agenda renders on narrow screens, When line wrapping occurs, Then words are not split mid-word and owner and minutes remain visible on the first line or immediately wrapped line.
Invite Sync & Clean Bullets
"As a meeting organizer, I want the agenda to sync as clean bullets into the calendar invite across Google and Outlook so that attendees have a single source of truth before the meeting."
Description

Generate a clean, structured bullet list of agenda cards (Topic, Owner, Expected Outcome, Minutes) and sync it to the calendar invite description for Google Calendar and Outlook/Office 365. Use idempotent updates to avoid churn and duplicates, preserve any non-agenda content added by organizers, and minimize notification spam. Maintain a canonical agenda in TimeMeld with a stable marker block in the invite; update on edits until the meeting starts, then lock and append outcomes. Support ICS formatting, plain-text fallback, locale-aware time formatting, and error handling with retry and audit logs. Respect OAuth scopes and tenant policies.

Acceptance Criteria
GCal Agenda Sync: Idempotent Marker Update Preserves Organizer Content
Given a Google Calendar event description contains organizer-authored text and a prior TimeMeld agenda block delimited by BEGIN:TIMEMELD_AGENDA and END:TIMEMELD_AGENDA When a sync runs and the TimeMeld agenda has no changes Then no PATCH request is made to Google Calendar and the event ETag remains unchanged Given a Google Calendar event contains organizer-authored text outside the markers and the TimeMeld agenda has changed When a sync runs Then only the text between BEGIN:TIMEMELD_AGENDA and END:TIMEMELD_AGENDA is replaced with a clean bullet list with each card formatted as "- Topic — Owner — Expected Outcome — N min", and text outside the markers is preserved verbatim Given multiple consecutive syncs with identical agenda input When they run within a 5-minute window Then the invite description contains exactly one marker-delimited block and no duplicate agenda blocks are created Given agenda card fields include UTF-8 characters and newlines When synced to Google Calendar Then characters render correctly in web and mobile clients without HTML artifacts or broken encoding
Outlook/Office 365 Agenda Sync: Marker-Based Idempotent Update
Given a Microsoft 365 event body contains organizer-authored text and a prior TimeMeld agenda block delimited by BEGIN:TIMEMELD_AGENDA and END:TIMEMELD_AGENDA When the TimeMeld agenda is unchanged and a sync runs via Microsoft Graph PATCH /events/{id} with sendUpdates=None Then no body change is sent and the iCalUId and lastModifiedDateTime remain unchanged Given the TimeMeld agenda has changed When a sync runs Then only the content between the markers is replaced with the clean bullet list formatted as "- Topic — Owner — Expected Outcome — N min", preserving organizer text before/after, and no duplicate marker blocks exist after the update Given the event body contentType is HTML When the agenda is synced Then the content is stored as HTML but renders visually as plain bullets without inline CSS, and a plain-text alternative is preserved for non-HTML clients
Notification Minimization for Agenda-Only Updates
Given attendees are already invited and only the agenda content changes (no time/attendee changes) When syncing to Google Calendar Then the update uses sendUpdates=none and attendees receive no email notifications Given the same preconditions on Microsoft 365 When syncing via Graph Then the update uses sendUpdates=None and attendees receive no email notifications Given multiple agenda edits occur within a 10-minute window When sync runs for each edit Then updates are coalesced to at most one provider PATCH per provider within that window without losing the latest agenda state
Pre-Start Updates and Post-Start Lock with Outcomes Append
Given the current time is before the scheduled event start When the agenda is edited in TimeMeld and synced Then the marker-delimited agenda block in the invite updates to match and remains editable in TimeMeld Given the current time is at or after the event's actual start (or scheduled start if actual is unknown) When further edits to agenda cards are attempted Then the agenda section is locked (no changes applied to the marker-delimited block) and a new marker-delimited "BEGIN:TIMEMELD_OUTCOMES ... END:TIMEMELD_OUTCOMES" section is appended containing outcomes Given the meeting is rescheduled to a future time before it has actually started When syncing Then the agenda lock is removed and agenda edits are again applied until the new start time
ICS Export, Plain-Text Fallback, and Locale-Aware Time Formatting
Given a meeting with agenda cards exists When exporting/downloading the event as ICS or sending an ICS attachment Then the VEVENT DESCRIPTION includes a plain-text bullet list of agenda cards formatted as "- Topic — Owner — Expected Outcome — N min", uses CRLF line endings with RFC 5545 line folding, and contains UTF-8 characters correctly Given clients that do not support HTML bodies When the invite is viewed Then the agenda renders as the plain-text bullet list without HTML tags Given the organizer locale is en-US and another organizer locale is de-DE When generating any human-readable date/time strings included by TimeMeld in the description header Then en-US renders times in 12-hour format with AM/PM (e.g., Thu Sep 11, 2025, 2:30 PM PT) and de-DE renders in 24-hour format with locale-appropriate punctuation (e.g., Do., 11.09.2025, 14:30 Uhr)
Robust Error Handling, Retry, and Audit Logging
Given Google Calendar or Microsoft Graph returns transient errors (HTTP 429/5xx) When syncing the invite description Then the system retries with exponential backoff and jitter for up to 3 attempts (e.g., ~1s, ~2s, ~4s +/- jitter) and surfaces success/failure in internal telemetry Given a permanent error occurs (HTTP 401/403 or tenant policy violation) When syncing Then retries stop, the sync is marked as failed for that event, the UI shows a non-blocking warning with re-auth/policy guidance, and no further write attempts are made until user action Given any sync attempt (success or failure) When it completes Then an audit log entry is recorded with timestamp, provider, event id, change summary (diff hash and count of cards), result (success/failure), attempt count, and correlation id
OAuth Scope and Tenant Policy Compliance
Given Google OAuth tokens are granted only calendar.events scope and Microsoft tokens are granted only Calendars.ReadWrite When syncing agenda content Then only the minimum required API endpoints are invoked and no scopes outside the granted set are requested Given tenant policies restrict body updates or external app writes When a write is attempted Then the operation is blocked by the provider, TimeMeld surfaces a clear policy message, does not escalate permissions, and stops retrying for that event until configuration changes Given an account is deauthorized or tokens expire When the next scheduled sync occurs Then no provider calls are made with invalid tokens, the agenda remains unchanged, and the user is prompted to reauthorize
Ownership Rotation Integration
"As a team lead, I want suggested rotating owners for agenda items based on equity so that meeting ownership is fairly distributed over time."
Description

Integrate Agenda Cards with TimeMeld’s equity scoreboard to propose a fair, rotating Owner for each item. Display suggested owners with reasoning (e.g., last three ownerships, contribution balance) and allow override with a justification note. Update equity metrics after the meeting based on items actually owned and completed. Handle external attendees (non-account users) via guest placeholders without affecting internal equity. Enforce permissions so only organizers can change owners while all invitees can view. Provide safeguards to prevent repeatedly assigning inconvenient time or ownership to the same individuals across time zones.

Acceptance Criteria
Owner Suggestion per Agenda Card via Equity Scoreboard
Given an agenda with at least two eligible internal attendees and zero or more external guests And historical ownership data exists for the last three meetings When Agenda Cards are created or edited Then the system suggests exactly one owner per card within 2 seconds for up to 20 cards And the suggested owner is an internal attendee who did not own more than 50% of items across the last three meetings, unless all other internal attendees are ineligible (declined, out-of-office, or removed) And external guests and out-of-office attendees at the meeting time are excluded from suggestion eligibility And given the same inputs, the suggestion is deterministic
Ownership Reasoning Display on Agenda Cards
Given a suggested owner has been computed for an agenda card When viewing the agenda in the invite or Agenda Cards UI Then the card shows a Why suggested section including: ownership count over the last three meetings, contribution balance (positive/negative delta), and a rotation note And a View equity scoreboard link opens the scoreboard filtered to the meeting participants And all invitees (internal and external) can view the reasoning And the reasoning text is accessible (screen-reader readable and meets WCAG AA contrast)
Organizer Override with Justification and Audit Trail
Given a user is the meeting organizer When they change the suggested owner on a card Then the system requires a justification note of at least 10 characters before saving And records an audit entry with previous owner, new owner, organizer id, timestamp, and justification And the override and justification are visible to all invitees And external guests cannot be selected as owner during override
Post‑Meeting Equity Update from Actual Owned and Completed Items
Given a meeting has ended When an agenda item is marked Completed with an assigned owner Then update the equity scoreboard within 10 minutes to credit that owner with 1 ownership unit And items not marked Completed do not update equity And canceled meetings or deleted items do not update equity And an audit log entry records item id, owner id, completion timestamp, and meeting id
External Attendee Handling via Guest Placeholders
Given an invitee without a TimeMeld account is added by email When Agenda Cards render participants Then the system creates a Guest Placeholder with the external's display name and email And guest placeholders are excluded from owner suggestion eligibility and equity updates And attempts to assign a guest as owner are blocked with a message explaining that external attendees do not affect internal equity And guests can view agenda items and reasoning if the invite is shared with attendees
Owner Edit Permissions by Role
Given a meeting with an organizer and invitees When the organizer views Agenda Cards Then they can set or change owners and must provide justifications for overrides And when any non-organizer attempts to edit ownership, the control is disabled and the API returns 403 Forbidden And all invitees (internal and external) can view owners and reasoning without edit access
Timezone Safeguards Against Repeated Inconvenient Ownership
Given user working hours are configured or default to 09:00–18:00 local time And historical ownership records exist for the past 14 days When proposing or overriding an owner for a meeting scheduled outside the user's working hours Then the system warns if the user has two or more off-hours ownerships in the trailing 14 days And the suggestion engine deprioritizes that user so an alternative eligible owner is selected when available And if no alternatives exist, the organizer can proceed only after entering a justification note and the warning is logged
Agenda Timer & Live Progress
"As a facilitator, I want a live agenda timer that tracks progress per card so that we can adjust in real time and end on time."
Description

Provide a lightweight in-meeting view that displays the agenda list with per-item countdown timers, controls to start/skip/extend, and visual progress against the timebox. Notify the current Owner when their item is up and when 1 minute remains. Capture actual durations and deviations to feed Smart Duration Suggestions. Allow quick capture of outcomes per card and mark items as carried over, automatically creating a follow-up card for the next session. Ensure minimal footprint (floating pane or companion web view), keyboard shortcuts, and resilience to network hiccups with graceful reconnection.

Acceptance Criteria
Live Agenda View with Per-Item Countdown
Given an active TimeMeld meeting with N agenda cards and planned durations When the user opens the floating pane or companion web view Then the agenda list displays each card with title, owner, expected outcome, planned minutes, and a countdown timer for the current card initialized to its planned duration, and upcoming cards show a queued state without a running timer Given the current card timer is running When 5 seconds elapse Then the displayed remaining time decreases accordingly at 1 Hz and stays within ±1 second of real time in both the floating pane and the web view Given minimal footprint mode is enabled When toggled Then the pane collapses to a header bar ≤ 96px tall on a 1080p display, remains draggable, and shows the current card title and remaining time on a single line Given a card title exceeds available width When rendered Then the title is truncated with an ellipsis and the full text is available via tooltip and screen-reader label
Item Controls: Start, Skip, Extend with Shortcuts
Given a current card is selected When the facilitator presses Space or clicks Start Then the timer starts within 100 ms Given the current card is running When the facilitator presses Space or clicks Pause Then the timer pauses within 100 ms Given the current card is running or paused When the facilitator presses N or clicks Skip Then the current card is marked Skipped with actual duration = 0s, and the next card becomes current within 200 ms Given the current card is running or paused When the facilitator presses + or clicks Extend (default increment = 2 minutes) Then the remaining time increases by the increment and the total agenda remaining updates immediately Given the current card is running or paused When the facilitator presses - or clicks Shorten Then the remaining time decreases by the increment but not below 0 Given the facilitator presses ? When the shortcuts overlay is requested Then it lists Space (start/pause), N (skip/next), + (extend), - (shorten), O (add outcome), C (carry over), and can be dismissed with Esc
Visual Progress Against Timebox
Given planned total agenda time T is available When any item timer runs Then a meeting progress bar shows elapsed/T and updates at least once per second Given cumulative elapsed ≤ 90% of T When displayed Then the bar is green; when > 90% and ≤ 100%, it is yellow; when > 100%, it is red and shows +overrun time in mm:ss Given a card exceeds its planned duration When that threshold is crossed Then the card row displays an overrun badge with +mm:ss and an overrun style without obscuring controls
Owner Notifications for Turn and 1-Minute Remaining
Given a card becomes current and its timer starts When this transition occurs Then the card Owner receives an in-app toast titled "You're up: <card title>" within 1 second and, if permissions are granted, a desktop notification Given the current card reaches 1:00 remaining When that threshold is crossed Then the Owner receives a "1 minute remaining" notification exactly once for that item Given the meeting tab is unfocused When notifications fire Then a web push is sent (if permission granted) or the notification is queued and shown within 2 seconds upon refocus; duplicate notifications are not delivered Given audio cues are enabled When a notification fires Then a short chime plays respecting system volume and can be disabled in preferences
Actual Duration Capture and Deviation Logging
Given a card has been started and later marked Done When Done is pressed Then actual duration equals the sum of all started intervals and deviation = actual − planned are recorded Given a card is skipped When Skip is pressed Then actual duration is recorded as 0s and deviation = −planned Given the app is online When Done or Skip is pressed Then the record syncs to the backend within 5 seconds; if offline, it is stored locally and queued for sync Given the client reconnects after being offline When syncing occurs Then server-side actuals match local within ±2 seconds and only one consolidated record exists per card Given a record is created When events are emitted Then an event is sent to Smart Duration Suggestions with cardId, meetingId, plannedSeconds, actualSeconds, deviationSeconds, and timestamp
Outcome Entry and Carry-Over Follow-Up Creation
Given a current card is active or paused When the facilitator presses O or clicks Add Outcome and enters up to 500 characters Then the outcome is saved on Done and appears in the meeting summary and calendar invite notes (if connected) within 10 seconds Given a card is not completed When Carry Over is toggled and the facilitator advances Then a follow-up card is created for the next scheduled session with the same title, Owner (defaulting to original), suggested duration = max(planned, actual) rounded to the nearest minute, and a backlink to the source card Given there is no next session scheduled When Carry Over is confirmed Then the follow-up card is placed in the team's agenda backlog and will surface in the next agenda-building flow Given a follow-up card is created When the meeting ends Then all participants can see it with a "carried over from <date>" tag
Network Resilience and Graceful Reconnection
Given a network disconnect occurs during a meeting When the timer is running Then the local timer continues to run, controls remain usable, and an Offline badge is shown Given connectivity is restored When reconnection occurs Then unsynced events (start, pause, extend, shorten, skip, done, outcome) are synced within 3 seconds using exponential backoff (1s, 2s, 4s... up to 30s) while offline Given reconciliation with the server happens When conflicting state is detected Then last-write-wins using server time (client-server delta accounted for) with max drift ≤ 2 seconds, and no duplicate notifications or double-advances occur Given the pane is closed while offline When it is reopened Then the meeting state (current card index, run/paused state, remaining time) restores from local cache in under 300 ms

Link Auditor

Validates the conferencing link before send: checks provider, expiry, passcode embedding, and host/guest permissions. Detects multiple links, stale rooms, or missing dial‑in and auto-fixes with a safe default—preventing “which link?” confusion at join time.

Requirements

Provider Fingerprinting & Link Parsing
"As a scheduler, I want TimeMeld to accurately recognize and interpret any conferencing link I paste so that it can validate and repair issues automatically without manual effort."
Description

Detect and parse conferencing links from major providers (Zoom, Google Meet, Microsoft Teams, Webex) anywhere in the event (location, description, notes). Extract structured attributes (provider, meeting ID, passcode presence/embedding, attendee vs host URL, region, deep-link parameters) and normalize them into a standard schema. Handle multiple URL formats, vanity domains, and pasted text with surrounding noise. Expose a deterministic confidence score and parse errors for downstream logic. Integrate with TimeMeld’s scheduling composer and API so the parsed result drives subsequent validations and fixes.

Acceptance Criteria
Unified Parsing Across Event Fields
Given an event with conferencing URLs in location, description, and notes When the parser runs Then it extracts all conferencing URLs from all fields and returns a deduplicated list Given a URL from Zoom, Google Meet, Microsoft Teams, or Webex When parsed Then provider is correctly identified and confidence >= 0.95 Given a non-conferencing URL When parsed Then it is excluded from results and errors include code "NON_CONFERENCE_URL" and confidence <= 0.2 Given no URLs present When parsed Then result set is empty and errors include code "NO_LINK_FOUND"
Attribute Extraction and Normalization
Given a valid provider URL When parsed Then output includes provider, meetingId, isPasscodeEmbedded, urlType (ATTENDEE|HOST), region, deepLinkParams, originalUrl; non-applicable fields are null Given an attendee link with embedded passcode When parsed Then isPasscodeEmbedded = true and passcodePresent = true Given a host link When parsed Then urlType = HOST and warnings include "HOST_LINK_DETECTED" Given URL includes region indicators When parsed Then region is normalized to an ISO 3166-1 alpha-2 or provider-specific region code per schema rules Given deep link parameters are present When parsed Then deepLinkParams contains URL-decoded key-value pairs Given a required attribute (provider or meetingId) cannot be derived When parsed Then the attribute is null and errors include code "MISSING_ATTRIBUTE" with a field reference
Vanity Domains and URL Format Variants
Given a Zoom vanity domain URL like https://acme.zoom.us/j/123456789 When parsed Then provider = ZOOM and meetingId = 123456789 Given a Google Meet code like meet.google.com/abc-defg-hij When parsed Then https scheme is inferred and meetingId = abc-defg-hij Given a Microsoft Teams URL in format https://teams.microsoft.com/l/meetup-join/... When parsed Then provider = MICROSOFT_TEAMS and meetingId is extracted per documented pattern Given a Webex personal room URL like https://acme.webex.com/meet/jane.doe When parsed Then provider = WEBEX and meetingId = jane.doe and urlType is correctly determined Given a deep link scheme (zoommtg:, msteams:) When parsed Then provider is recognized and deepLinkParams are extracted
Noise Tolerance and Multiple Link Handling
Given free text where a valid conferencing URL is followed by punctuation or wrapped in markdown When parsed Then the URL is recognized without trailing punctuation and link text markers are ignored Given an event containing two different provider links When parsed Then two distinct records are returned, each with correct provider and meetingId Given an event containing duplicate URLs of the same meeting When parsed Then duplicates are collapsed and a single record is returned with a warning "DUPLICATE_LINKS_COLLAPSED" Given an event containing both a host and attendee link for the same meeting When parsed Then the attendee link is preferred in primary selection and a warning "CONFLICTING_LINKS" is emitted Given overly long or malformed URLs When parsed Then they are skipped and errors include code "MALFORMED_URL"
Deterministic Confidence Scoring and Error Reporting
Given the same input content parsed multiple times When parsed Then the confidence score is identical to 4 decimal places Given all primary attributes are successfully extracted When parsed Then confidence >= 0.95 and the errors array is empty Given provider is detected but meetingId is ambiguous or missing When parsed Then confidence is between 0.4 and 0.7 inclusive and errors include code "MISSING_MEETING_ID" Given input does not match any supported provider pattern When parsed Then confidence <= 0.3 and errors include code "UNSUPPORTED_FORMAT" with a non-empty message Given multiple parsing issues are detected When parsed Then the errors array includes all applicable codes without duplicates
API and Composer Integration Contract
Given a scheduling composer draft with event fields containing links When the composer invokes the link parser Then the normalized parse results populate the composer with provider, urlType, region, passcodeEmbedding, and confidence Given a POST /v1/parse-links request with payload <= 50KB When processed Then the API responds with HTTP 200 and P95 latency <= 150ms and returns JSON matching the documented schema version with results, errors, and confidence Given parsing yields one or more errors When processed Then the Link Auditor downstream receives the error list and applies safe default behavior when policy flag useSafeDefaultOnError = true Given feature flag linkParsing.providers includes a new provider When enabled Then responses include the provider in the enum, schema version increments by 0.1, and existing consumers continue to parse without change
Expiry & Time-Window Validity Check
"As an organizer, I want to know if the meeting link will still be valid at the time of the meeting so that attendees can join without being blocked or redirected."
Description

Verify that the conferencing link will be valid for the scheduled meeting window by querying provider metadata when available and applying heuristics when not (e.g., personal room vs time-bound meetings). Flag expired links, meetings scheduled in the past, or links requiring regeneration after a set lifetime. Detect deleted or canceled provider meetings and mismatched times between calendar and provider. Surface clear diagnostics and recommended actions to the user and downstream auto-fix routines.

Acceptance Criteria
Valid Link Covers Meeting Window (Provider Metadata)
Given a calendar event with start S and end E (S < E) and a conferencing link for provider P And the provider API returns meeting start_time <= S and (end_time is null or end_time >= E) and status in ["scheduled","ready","started"] When the Link Auditor validates expiry and time-window Then result.status = "valid_for_window" And diagnostics include {code:"OK_VALID_FOR_WINDOW", provider:"P", meeting_id, validity_start, validity_end, check_method:"provider_api"} And no warnings or errors are surfaced
Expired Before Meeting Start
Given a calendar event with start S > now and end E and a conferencing link for provider P And the provider API returns status in ["ended","expired"] or end_time < S When the Link Auditor validates expiry and time-window Then result.status = "invalid" And diagnostics include {code:"LINK_EXPIRED_FOR_WINDOW", provider:"P", meeting_id, expired_at} And recommended_action = "regenerate_link" is returned to UI and auto-fix And auto_fix_payload includes {provider:"P", desired_start:S, desired_end:E}
Provider Meeting Canceled or Deleted
Given a calendar event with a conferencing link for provider P And the provider API returns HTTP 404 or status "canceled" When the Link Auditor validates expiry and time-window Then result.status = "invalid" And diagnostics include {code:"LINK_DELETED_OR_CANCELED", provider:"P", meeting_id} And recommended_action = "create_new_meeting"
Calendar–Provider Time Window Mismatch
Given a calendar event with start S and end E and a conferencing link for provider P And the provider API returns meeting start_time = Ps and end_time = Pe When |Ps − S| > 5 minutes or |Pe − E| > 5 minutes Then if Ps > S or Pe < E, result.status = "invalid" with diagnostics {code:"TIME_WINDOW_MISMATCH", provider:"P", provider_start:Ps, provider_end:Pe, calendar_start:S, calendar_end:E} and recommended_action = "update_provider_meeting_times_to_calendar" And if Ps <= S and Pe >= E, result.status = "warning" with diagnostics {code:"TIME_WINDOW_OFFSET", provider:"P", provider_start:Ps, provider_end:Pe, calendar_start:S, calendar_end:E} and recommended_action = "align_provider_times"
Heuristic Validation: Personal Room Without Metadata
Given a calendar event with start S > now and end E and a conferencing link whose provider metadata is unavailable And the link matches a known personal room pattern for the provider And (E − S) <= 8 hours When the Link Auditor validates expiry and time-window Then result.status = "valid_for_window_heuristic" And diagnostics include {code:"HEURISTIC_VALID_FOR_WINDOW", provider, pattern:"personal_room", check_method:"heuristic"} And no blocking error is surfaced
Meeting Scheduled in the Past
Given a calendar event with end E < now and a conferencing link When the Link Auditor validates expiry and time-window Then result.status = "invalid" And diagnostics include {code:"MEETING_IN_PAST", event_end:E} And recommended_action = "reschedule_meeting"
Link Lifetime Exceeds Provider TTL
Given a calendar event with start S and end E and a conferencing link for provider P And the provider returns link creation_time C and max_lifetime_days L or token_expiry T When (T exists and T < E) or (C + L days < E) Then result.status = "invalid" And diagnostics include {code:"LINK_LIFETIME_EXCEEDED", provider:"P", created_at:C, lifetime_days:L, token_expiry:T} And recommended_action = "regenerate_link" And auto_fix_payload includes {provider:"P", desired_start:S, desired_end:E}
Role & Access Policy Verification
"As an organizer, I want confirmation that the link enforces the right security and access settings so that only intended participants can join and the host role is protected."
Description

Assess whether the link enforces correct roles and access controls per workspace policy: passcode required, waiting room/lobby on, guest lobby bypass disabled, and no inadvertent host-privilege URLs shared publicly. Detect domain-restricted links that attendees cannot access (e.g., SSO or org-only) and warn when passcodes are not embedded but policy allows embedding. Produce actionable guidance and a machine-readable policy compliance report consumed by the auto-fix engine.

Acceptance Criteria
Policy Enforcement: Passcode Required
Given a conferencing link and a workspace policy that requires a passcode When the link does not require a passcode or the passcode is missing or invalid Then the audit marks the link Noncompliant with code PASSCODE_REQUIRED And the audit proposes a remediation to enable a passcode or embed the passcode if embedding is permitted by policy and provider And the compliance report includes provider, meeting_id, detection_evidence, and proposed_fix entries for PASSCODE_REQUIRED
Policy Enforcement: Waiting Room/Lobby Enabled
Given a conferencing link and a workspace policy that requires a waiting room or lobby When the link has the lobby disabled or the provider’s lobby capability is turned off Then the audit marks the link Noncompliant with code LOBBY_DISABLED And if the provider supports lobby, the audit proposes a remediation to enable the lobby before distribution And if the provider does not support lobby, the audit emits severity WARN with guidance to switch provider or add pre-join screening, and records rationale in the report
Policy Enforcement: Guest Lobby Bypass Disabled
Given a conferencing link and a workspace policy that requires guest lobby bypass to be disabled When the link allows guests or same-domain attendees to bypass the lobby Then the audit marks the link Noncompliant with code GUEST_BYPASS_ENABLED And the audit proposes a remediation to disable all bypass options except for hosts/co-hosts as allowed by policy And the compliance report includes the detected bypass settings and the proposed_fix
Access Mismatch: Domain-Restricted Link with External Attendees
Given a scheduled meeting with an attendee list and a conferencing link that is domain- or SSO-restricted When at least one attendee’s domain or identity does not satisfy the link’s access restriction Then the audit marks the link Noncompliant with code ACCESS_RESTRICTION_MISMATCH And the report enumerates blocked attendees with domain and reason And the audit proposes a remediation such as generating a guest-access link or relaxing restriction per policy with approval requirements
Safety: Host-Privilege URL Detection and Sanitization
Given a conferencing link that confers host or moderator privileges (e.g., start_url, organizer token) When the link is prepared for distribution to non-host recipients or placed in public event fields Then the auditor blocks distribution and replaces it with an attendee-safe join URL And the audit marks the original link Noncompliant with code HOST_PRIVILEGE_URL_EXPOSED And the report includes evidence of host-privilege detection and a proposed_fix with sanitized_link
Policy Guidance: Passcode Embedding Permitted but Missing
Given a workspace policy that permits passcode embedding and a provider that supports embedded passcodes When the meeting is passcode-protected but the distributed link does not include the embedded passcode Then the audit emits a Warning with code PASSCODE_NOT_EMBEDDED And the audit proposes a remediation to embed the passcode into the link and updates the invite body accordingly And the report records evidence and the proposed_fix without exposing the raw passcode in cleartext
Output: Machine-Readable Policy Compliance Report
Given a completed audit against a known policy version When the report is generated Then the output is valid JSON conforming to schema id timemeld.link_audit.policy.v1 And it includes overall_status and evaluated_rules[] with rule_id, code, status (PASS|FAIL|WARN), severity, evidence, and proposed_fix {fix_id, action, parameters} And the auto-fix engine successfully parses the report and identifies at least one actionable proposed_fix when any rule fails or warns
Multi-Link Collision Resolver
"As a meeting owner, I want TimeMeld to detect and resolve conflicting links in my invite so that participants have a single, unambiguous way to join."
Description

Scan the event’s location and body to detect multiple conferencing links or conflicting dial-in details. Apply ordered heuristics to select a canonical link (location field precedence, most recent edit, provider preference), and present a one-click confirmation. Automatically remove or demote non-canonical links, rewrite the description with standardized join instructions, and log changes for auditability. Provide a non-blocking warning when confidence is low.

Acceptance Criteria
Canonicalization with Location Field Precedence
Given a calendar event where the Location field contains a valid conferencing link and the Description contains one or more different conferencing links When the Multi-Link Collision Resolver scans the event Then it selects the Location field link as the canonical link And it marks all other links as non-canonical And it removes non-canonical links from the primary join section and moves them to an Other links section or removes them based on workspace policy And it records location_precedence as the deciding heuristic And it preserves all non-link content unchanged And repeated scans are idempotent and make no further changes
Body-Only Links Resolved by Most Recent Edit Timestamp
Given an event without a conferencing link in the Location field and with two or more different conferencing links in the Description And each link has an associated last-edited timestamp available from the calendar change history When the resolver scans the event Then it selects as canonical the link with the most recent edit timestamp And if two candidate links have identical timestamps, it defers to provider preference ordering And it demotes all non-canonical links as per policy And it records most_recent_edit as the deciding heuristic
Provider Preference Ordering Applied to Ties
Given an event with multiple conferencing links from different providers and no decisive signal from location precedence or edit timestamps And the workspace has a configured provider preference order When the resolver scans the event Then it selects as canonical the first provider in the configured preference order present in the event And it records provider_preference and the evaluated order in the audit log And it demotes all non-canonical links And if no provider in the preference list is present, it selects the first detected valid conferencing link and records first_valid_fallback
One-Click Confirmation Flow and Safe Rollback
Given the resolver has identified a canonical link and at least one non-canonical link When the user with edit permission views the event in TimeMeld Then a one-click Confirm Canonical Link action is displayed with the selected canonical provider and URL And clicking Confirm immediately applies the rewrite and removals within 2 seconds And an Undo option is displayed for 30 seconds to revert all resolver changes And dismissing the prompt leaves the event unmodified And the action is non-blocking; the user can proceed with scheduling regardless of confirmation
Standardized Join Instructions Rewrite with Non-Canonical Demotion
Given a canonical link has been confirmed automatically or by user When the resolver rewrites the event Description Then it inserts a standardized Join Instructions block that includes provider name, canonical URL, meeting ID if detectable, passcode if present (not URL-encoded in the text), and primary dial-in numbers if available And it removes duplicate or conflicting join sections and ensures exactly one primary join link remains And if multiple meeting IDs or dial-in sets are present, only those corresponding to the canonical meeting are included; others are demoted or removed And it moves non-canonical links to an Other links section with provider labels, or removes them per policy And it preserves all other non-link descriptive content and formatting And the Location field is updated to the canonical link if allowed by provider and calendar permissions
Audit Logging of Canonicalization Decisions
Given any resolver decision that changes or recommends changes to the event When the operation completes Then an audit log entry is created containing event ID, organizer ID, before and after lists of conferencing links, deciding heuristic, confidence score, timestamp, actor (auto vs user ID), and whether changes were applied or dismissed And logs are persisted within 1 second and retained for at least 180 days And passcodes are stored masked and URLs are redacted to remove query secrets And logs are viewable by workspace admins in the TimeMeld Audit console and exportable as CSV
Low-Confidence Non-Blocking Warning and Actions
Given multiple conferencing links are detected and the resolver's confidence score is below the workspace threshold (default 0.70) When the user views the event in TimeMeld Then a non-blocking warning banner is shown summarizing the conflict and the recommended canonical link And no automatic removal or rewrite occurs until the user confirms And the banner presents two actions: Confirm and Skip for now And choosing Skip for now snoozes the warning for 24 hours or until the event is next edited, whichever comes first And the decision is recorded in the audit log
Dial-in & Access Details Completion
"As a participant who may join by phone or with limited bandwidth, I want dial-in and alternative access details included so that I can join reliably from any environment."
Description

Ensure every invite includes complete, localized join options when policy or participant context requires it. Fetch and insert PSTN dial-in numbers from the provider, prioritizing locales based on attendee time zones and countries, and include conference ID and passcode. Add alternative access paths (SIP/H.323 or VTC coordinates) when supported. Normalize formatting and place details in a consistent section of the invite to reduce confusion.

Acceptance Criteria
Localized PSTN Dial-ins for Multinational Attendees
Given a scheduled meeting with attendees across multiple countries or time zones and at least one PSTN-required policy or attendee context When TimeMeld composes the calendar invite Then it inserts PSTN dial-in numbers prioritized by attendee distribution, including up to 5 locales ranked by attendee count and proximity to the meeting time And includes at least one local number per represented country when available And each number is labeled with country and city and includes the conference ID and passcode
Fallback Dial-ins When Local Numbers Unavailable
Given the conferencing provider does not supply a local dial-in for a required locale When TimeMeld composes the invite Then it inserts the nearest regional or global dial-in number provided by the service And marks the entry with the region label And no "missing" or placeholder text remains in the invite And the dial-in connects to the same meeting ID as the primary link
Alternative SIP/H.323 Access Included When Supported
Given the selected conferencing provider supports SIP and/or H.323/VTC access When TimeMeld composes the invite Then it includes SIP URI and H.323/VTC coordinates under an "Alternative access" subsection And these URIs resolve to the same meeting ID/passcode as the primary link And if the provider lacks support, the subsection is omitted entirely
Normalized Join Section Placement and Formatting
Given any invite generated or updated by TimeMeld When join details are inserted Then the body contains exactly one "Join options" section placed after the agenda and before the footer And subsections appear in order: "Video link", "Dial‑in", "Alternative access" (if present) And previous join details are replaced, preventing duplicates
Passcode and Conference ID Presence and Consistency
Given the meeting requires a passcode and conference ID When TimeMeld composes the invite Then the passcode and conference ID are present next to dial-in instructions And the same values are used across the video link, dial-in, and alternative access And if provider policy forbids passcode-in-link, the URL contains no embedded passcode and the passcode is shown separately; otherwise, it is safely embedded
Single Canonical Conferencing Link After Audit
Given multiple conferencing links are detected in the event location or description When Link Auditor runs prior to sending the invite Then exactly one canonical link for the selected provider remains in both the location field and the "Video link" subsection And all other links are removed or clearly demoted with labels (e.g., "Reference only") and cannot be mistaken as join links And the canonical link's meeting ID matches the IDs used in dial-in and alternative access
Host/Guest Permission Integrity for Shared Details
Given host-only credentials (e.g., host PIN, moderator code) exist for the meeting When TimeMeld composes the invite for attendees Then only guest join details (link, conference ID, passcode) are included for non-organizers And host-only credentials are sent only to the organizer via a separate channel or organizer-visible section And no host-only credentials appear in the body or attachments received by guests
Safe Auto-Fix & Invite Update
"As a busy organizer, I want TimeMeld to automatically replace broken or risky links with a safe default and update the invite so that I don’t have to manually troubleshoot before the meeting."
Description

When validation fails or confidence is low, automatically create a fresh meeting using the workspace’s default provider and safe defaults (unique meeting ID, passcode required and embedded, waiting room/lobby enabled, guest lobby bypass disabled). Replace the event’s location and description with the new canonical link and standardized join block, notify attendees of the update, and preserve an audit trail of the original link and fixes applied. Respect provider OAuth scopes, rate limits, and organizer ownership rules.

Acceptance Criteria
Auto-Fix Creates Safe Default Meeting On Validation Failure
Given an event contains a conferencing link that fails validation or has low confidence When the Link Auditor runs before the invite is sent Then TimeMeld creates a new meeting using the workspace’s default provider And Then the new meeting has a unique meeting ID And Then a passcode is required and embedded in the join URL And Then the waiting room/lobby is enabled And Then guest lobby bypass is disabled for all non-host attendees And Then the meeting host/owner is the event organizer per provider rules And Then the provider API responds with success and returns a join URL
Canonical Link Replaces Event Location And Description
Given an event has one or more existing conferencing links in the location or description When an auto-fix meeting is created Then the event location is replaced with the new canonical join URL And Then the event description is replaced with the standardized join block containing the canonical link and dial-in details when available And Then all prior conferencing links are removed from the description And Then no other conferencing provider URLs remain in the location or description And Then the event time, attendees, and title remain unchanged And Then the calendar event UID remains the same and the SEQUENCE is incremented
Attendees Notified With Updated Invite And Minimal Disruption
Given an event has attendees with email addresses When the event is updated with the canonical link via auto-fix Then all attendees receive an update notification from the calendar provider And Then existing attendee RSVP statuses are preserved And Then only one update notification is sent per auto-fix action And Then the update message clearly indicates that the conferencing link was updated And Then external attendees can join using the canonical link without needing the passcode separately And Then the organizer receives a confirmation that the link was auto-fixed
Audit Trail Captures Original Link And Fix Details
Given an auto-fix replaces the conferencing details When the updated event is saved Then an immutable audit record is created with the original link(s), detected issues, confidence score, timestamp, event ID, organizer ID, provider used, and actions applied And Then any secrets (tokens, passcodes) are redacted in stored audit data except where required to embed in the canonical link And Then the audit record is associated with the event and retrievable via the TimeMeld UI/API by the organizer and workspace admins And Then the audit record includes provider API request identifiers for traceability And Then the audit record is immutable and retained per the workspace retention policy
Provider OAuth, Ownership, And Permission Compliance
Given the organizer has granted provider OAuth scopes required to create meetings When the auto-fix process runs Then only granted scopes are used to create or update conferencing details And Then the meeting is created under the organizer’s account or delegated host per provider ownership rules And Then if required scopes are missing, the auto-fix aborts with no event changes and the organizer is notified with remediation steps And Then if the organizer lacks host privileges for the default provider, a non-destructive failure is recorded in the audit trail and no attendee notification is sent
Rate Limits, Retries, And Failure Handling
Given the conferencing provider returns a rate-limit (429) or transient error during meeting creation When the auto-fix attempts to create the meeting Then TimeMeld retries with exponential backoff up to 3 attempts And Then if all retries fail, no changes are made to the event content And Then the organizer is notified that the auto-fix could not be completed due to provider errors or rate limits And Then the audit trail records the error category, retry count, and provider request identifiers And Then subsequent auto-fix attempts for the same event are suppressed for 15 minutes to respect rate limits
Pre-Send & Pre-Join Revalidation
"As an organizer, I want TimeMeld to verify links both before sending invites and again just before the meeting so that last-minute issues are caught and resolved proactively."
Description

Integrate validations as a blocking step before invites are sent and schedule a lightweight re-check shortly before the meeting starts to catch last-minute deletions, access changes, or provider outages. If issues are detected, trigger the auto-fix flow or alert the organizer with a one-click fix option and minimal churn to attendees. Ensure idempotent updates and avoid duplicate notifications across calendar and Slack/email channels.

Acceptance Criteria
Pre-Send Blocking Validation
Given an event draft contains a conferencing link and invitees When the organizer clicks Send Then TimeMeld validates provider support, link expiry, passcode embedding policy, host/guest permissions, presence of a single primary link, and required dial-in per workspace policy And If all checks pass Then the invite is sent without modification And If any check fails and auto-fix is disabled Then sending is blocked, specific failed checks are shown inline, and no invites are sent And Validation completes within 3 seconds at p95
Auto-Fix on Pre-Send Failure
Given pre-send validation failures and auto-fix is enabled by workspace policy When the organizer clicks Send Then TimeMeld applies safe defaults: creates/replaces with a compliant meeting link from the default provider, embeds passcode per policy, corrects host/guest permissions, removes extra links, and adds dial-in if required And Then the event is updated before send, preserving the event UID and attendee list; only conferencing/location fields and a concise description note are modified And Then the invite is sent once and attendees receive a single update
Pre-Join Revalidation
Given a scheduled meeting with a conferencing link When the meeting is within the configured re-check window (default 10 minutes before start) Then TimeMeld re-runs link validations and provider health checks And If no issues are found Then no notifications are sent And If issues are detected (deleted meeting, revoked access, expired link, provider outage) Then TimeMeld auto-fixes using safe defaults (if enabled) and sends one update, or alerts the organizer with a one-click Fix Now action that sends one update upon confirmation And The re-check executes once per meeting per window and completes within 3 seconds at p95
Idempotent Update Behavior
Given multiple validation passes on the same event within a 30-minute window When the same fix would be applied more than once Then TimeMeld performs the update at most once, preserving the calendar event UID, incrementing the iCalendar sequence only once, and avoiding duplicate calendar updates And Then the conferencing link is replaced atomically and any prior TimeMeld annotations are updated in-place without duplication And Then attendees receive at most one updated invite for the same issue
Cross-Channel Notification Deduplication
Given an issue is detected and organizer channels are configured (calendar update, Slack DM, email) When notifications are dispatched Then TimeMeld sends exactly one organizer-facing alert per issue occurrence, preferring Slack if available, otherwise email And Then attendees receive only the calendar update and no duplicate Slack/email notifications And If the issue is resolved (auto-fixed or organizer one-click fix) Then any pending alerts are suppressed And A 30-minute deduplication window is enforced per event and issue type
Minimal Attendee Churn
Given a fix is applied pre-send or pre-join When the calendar event is updated Then only conferencing-related fields (location/conference block and relevant description lines) are changed; start/end time, title, agenda, and attendees remain unchanged And Then attendees receive at most one update email and the iCalendar sequence is incremented by 1 And Then the updated invite contains a clear note indicating the new meeting link and removes superseded links

Prep Pack

Scans the invite for referenced docs and auto-attaches or links pre‑reads with correct access for externals. Adds a brief “Prep by” note and estimates prep time—so attendees arrive ready and no one scrambles for permissions at the last minute.

Requirements

Intelligent Doc Reference Parsing
"As a meeting organizer, I want TimeMeld to automatically detect and collate all documents referenced in my invite so that I don’t miss critical pre‑reads and attendees have everything in one place."
Description

Automatically scans meeting titles, descriptions, and agenda fields for referenced documents, links, and file mentions (e.g., Drive, Dropbox, OneDrive, Notion, GitHub, Confluence). Supports pattern matching, URL expansion, and basic NLP to resolve ambiguous references (e.g., “Spec v3”, “Q4 Roadmap”) against connected repositories. Consolidates a canonical list of pre‑read assets with deduplication and version preference (latest unless otherwise specified). Exposes a preview to the organizer for confirmation before attachment/linking and logs unresolved references for follow‑up.

Acceptance Criteria
Multi-field Reference Detection (Title, Description, Agenda)
Given a meeting contains references in title, description, and agenda, When the Prep Pack scan runs, Then the parser identifies all explicit URLs and plain‑text file mentions across all three fields and returns them with source field provenance. Given links from supported providers {Google Drive, Dropbox, OneDrive, Notion, GitHub, Confluence} appear in any field, When scanning, Then each is detected and labeled with the correct provider type. Given 20 explicit URL references in a test meeting, When scanning completes, Then recall for explicit URLs is >= 0.98 and precision is >= 0.98.
Shortlink Expansion and Validation
Given shortened links (e.g., bit.ly, t.co, tinyurl.com) are present, When the scan runs, Then each link is expanded to its final URL following redirects and the destination provider is identified. Given the final destination is reachable, When expansion completes, Then final URL HTTP status is 2xx and the expanded URL replaces the shortlink in the canonical list. Given an expansion times out after 2 seconds or returns 4xx/5xx, When logging occurs, Then the reference is marked unresolved with reason "ExpansionFailed" or "InvalidURL" and includes the last reachable hop. Performance: p95 expansion time per link <= 2s; overall scan p95 <= 3s for meetings with <= 10 references.
Disambiguate Named References via Repository Search
Given connected repositories are authorized and indexed, When meeting text contains ambiguous named references (e.g., "Spec v3", "Q4 Roadmap"), Then the system searches connected repositories and proposes the most relevant document based on name similarity, semantic version, and last‑modified time. Given multiple candidates exceed the relevance threshold, When tie‑breaking is needed, Then the latest last‑modified within the same document family is selected. Given no candidate meets the confidence threshold (score < 0.75), When the scan completes, Then the reference is logged as unresolved with reason "LowConfidence". On a labeled evaluation set of 100 ambiguous references, Then top‑1 resolution accuracy >= 0.85.
Deduplication and Version Preference
Given the same document appears via multiple links or references (e.g., provider share URL and its shortlink), When consolidation runs, Then duplicates are merged using provider document IDs or canonicalized URLs. Given both versioned and unversioned references exist, When building the canonical list, Then the explicitly referenced version is preserved; otherwise, the latest version by semantic version or last‑modified date is selected. Given consolidation completes, When the canonical list is produced, Then it contains no duplicates and includes a "versionSelected" attribute for each item with the applied rule (explicit|latest).
Organizer Preview and Confirmation Workflow
Given the scan has produced a candidate list, When the organizer opens the Prep Pack preview, Then each item displays title/name, provider, originating field(s), confidence score (if applicable), and version. Given the organizer edits the list (remove item, change version from available versions, rename display label), When they confirm, Then only the confirmed items are attached/linked to the invite. Given the organizer cancels or closes the preview without confirming, When the meeting is saved, Then no attachments/links are added and the last candidate state is saved to draft for later review. Given the organizer confirms, When attachments are applied, Then an audit entry is stored with timestamp, user, and applied items.
Unresolved Reference Logging and Follow-up
Given unresolved references are detected, When the preview loads, Then each unresolved item appears in a "Needs Attention" section with the raw text, failure reason, and a "Resolve" action. Given the organizer clicks "Resolve", When they search and select a document, Then the item moves to the resolved list and the log is updated with resolver, selected doc, and timestamp. Given unresolved items remain at T-24h before the meeting, When notification rules run, Then the organizer receives a single consolidated notification with deep links to resolve or dismiss. Given logs are persisted, When queried by meeting ID, Then entries include timestamp, failure reason, and user actions and are retrievable via the logs API.
Resilience and Performance SLA
Given repository API outages or rate limits for any provider, When scanning executes, Then the system continues processing other providers, marks affected references as unresolved with reason "ProviderUnavailable", and does not block meeting creation. Given a meeting with up to 10 references and total text length <= 20,000 characters, When scanning runs under normal load, Then p95 end‑to‑end scan time <= 3 seconds and p99 <= 5 seconds. Given an unexpected parsing exception occurs, When error handling triggers, Then the system captures structured error telemetry and presents a non‑blocking message with a retry option, without attaching any items by default.
Cross‑Platform Access Provisioning
"As an organizer inviting external partners, I want TimeMeld to grant the right read access automatically so that no one is blocked by permission requests right before the meeting."
Description

Ensures all referenced pre‑reads are accessible to internal and external attendees with least‑privilege sharing. Integrates with Google Drive, Microsoft OneDrive/SharePoint, Dropbox, Notion, and Confluence APIs to set viewer/commenter access based on attendee domains and organizer policy. Offers organizer‑approved exceptions for restricted content, supports link‑based access with expiration, and records exact permission changes. Handles failures with actionable alerts and a retry queue, preventing over‑sharing via domain allow/deny lists and DLP labels.

Acceptance Criteria
Least-Privilege Access for Mixed Attendees
Given a meeting invite contains links to pre-read documents across supported providers and attendees include internal and external emails And an organizer policy defines role mapping: internal=commenter, external=viewer When TimeMeld provisions access Then only listed attendees are granted access at the document level (not folder/workspace) And internal attendees receive commenter permission And external attendees receive viewer permission And no attendee receives editor/owner permission And no domain-wide, public, or "anyone with link" access is created
Provider Parity Across Google Drive, OneDrive/SharePoint, Dropbox, Notion, Confluence
Given a pre-read link from each supported provider is present in the invite When TimeMeld provisions access for all attendees Then permissions are applied using the provider’s least-privilege equivalent (viewer/commenter) And sharing is applied at the item/page level only And inherited or group-level permissions are not broadened beyond required attendees And the operation is idempotent: re-running provisioning does not add duplicates or elevate roles And no provider results in a public or organization-wide share without explicit organizer approval
Organizer-Approved Exception for Restricted Content
Given a pre-read is labeled Restricted by DLP or blocked by domain policy When TimeMeld evaluates access Then the organizer is prompted to approve an exception with options: grant limited access to named attendees, skip sharing, or replace with summary And no access changes occur until the organizer explicitly approves And upon approval, only the selected attendees receive viewer access And the exception reason is captured and attached to the audit log entry And if the organizer declines, the document is not shared and attendees are notified that access is not provided
Expiring Link-Based Access for Externals
Given external attendees cannot be directly granted account-based access in the provider When the organizer approves link-based access Then TimeMeld creates a link restricted to viewer access with download/export disabled where supported And the link expiration is set to 24 hours after the meeting end time by default (configurable 1–72 hours) And the link is revoked automatically at expiration And access after expiration returns 403/Not Authorized And the link URL and expiry are recorded in the audit log
Audit Log of Permission Changes
Given access provisioning modifies permissions When the operation completes Then an audit record is created containing: meeting_id, document_id, provider, timestamp, actor, attendees impacted, previous permissions, new permissions, exception flag/reason, and link expiry (if applicable) And the record is immutable and retrievable via the admin/audit endpoint within 5 seconds of completion And all API responses and error codes are correlated to the audit entry
Failure Handling with Actionable Alerts and Retry Queue
Given a provider API returns a transient error (e.g., 429, 5xx) during provisioning When TimeMeld processes the failure Then the change is queued for retry with exponential backoff up to 5 attempts And no broader-scoped permissions are applied as a fallback And the organizer receives an alert summarizing impacted documents, attendees, error codes, and recommended actions And upon successful retry, the alert is updated or resolved automatically And after max attempts, status is marked Failed with a link to manually retry or adjust sharing
Domain Allow/Deny and DLP Enforcement
Given organizer or org policy defines allowed and denied attendee domains and DLP rules for external sharing When TimeMeld provisions access Then attendees from denied domains are excluded from sharing and flagged in the organizer alert And DLP rules that forbid external access prevent sharing to externals unless an exception is approved And internal attendees continue to receive appropriate access And no domain-wide access is granted to bypass policy
Auto Attach & Link Pre‑reads to Invite
"As a busy organizer, I want TimeMeld to auto‑attach or link all pre‑reads in the invite so that attendees can quickly find the right materials without digging through threads."
Description

Attaches supported files directly to the calendar event (Google Calendar, Outlook) where possible and inserts clean, labeled links for all pre‑reads in a structured “Prep Pack” section of the invite. Orders items by importance and estimated read time, and adds per‑item badges (e.g., “Must‑read”, “Optional”). Preserves existing invite content, supports updates on reschedule or doc changes, and avoids duplicate notifications by batching edits. Provides a manual override for organizers to exclude items before publishing.

Acceptance Criteria
Detect referenced docs in invite description
Given a new or updated calendar event description contains one or more URLs When TimeMeld scans the description Then it identifies supported pre-read document URLs (Google Docs/Sheets/Slides, PDFs, Notion, Confluence, Dropbox, OneDrive) and excludes non-document links Given multiple occurrences of the same document URL, including variants with tracking parameters or anchors When processing the list Then TimeMeld deduplicates them to a single pre-read item Given a URL that is unreachable or returns 404/403 When scanning Then the item is flagged as Unavailable and excluded by default, and the organizer is notified in the Prep Pack editor Given detected pre-read URLs When building the Prep Pack Then each item’s display label is the document title or file name, not the raw URL
Attach and link pre-reads (Google Calendar & Outlook)
Given a Google Calendar or Outlook event with detected pre-reads When composing the Prep Pack Then supported files are attached if provider supports attachments and the file size is within limits (Google ≤ 25MB, Outlook ≤ 20MB); otherwise labeled links are inserted Given existing event content (title/subject, time, attendees, description/body) When inserting the Prep Pack Then all existing content is preserved and the Prep Pack appears as a distinct section appended to the description/body Given the Prep Pack section When viewed in Google Calendar (web/mobile) or Outlook (web/desktop) Then links render with clean labels in the format “Title — Source” without exposing raw URLs Given the event is saved with the Prep Pack When re-opening the event Then there are no duplicate attachments or duplicate link entries
Prep Pack structure, ordering, badges, and prep time
Given detected items include importance and estimated read time When composing the Prep Pack section Then items are ordered with Must-read before Optional, and within each group by ascending estimated read time Given each item in the Prep Pack When displayed Then it shows a badge (Must-read or Optional) and its estimated read time in minutes Given the event start time When composing the invite Then a Prep by note is included and set by default to 24 hours before the event, and is editable by the organizer Given items without explicit importance When composing Then organizer-referenced docs default to Must-read and auto-suggested context defaults to Optional
External access validation for pre-reads
Given the attendee list includes external domains When validating pre-read items Then TimeMeld checks access for each attendee and flags any items where one or more attendees lack access Given one or more attendees lack access to a Google or Microsoft document When the organizer reviews the Prep Pack Then TimeMeld prompts to grant Viewer access to all attendees or to skip fixing access, and blocks sending until a choice is made Given the organizer chooses to grant access When saving Then permissions are updated successfully and the Prep Pack shows no remaining access issues; failures display actionable error messages Given org policy prevents permission changes When saving Then TimeMeld leaves links intact and adds a note “(Access may be required)” to affected items
Auto-update on reschedule and document changes
Given an event with a Prep Pack is rescheduled When the organizer changes the start time Then the Prep by note updates relative to the new start time and the Prep Pack section remains intact Given a linked document is renamed or its URL changes When TimeMeld detects the change Then the item’s label and link update within 2 minutes without creating duplicates Given pre-read items are added or removed in the Prep Pack editor When the organizer saves Then the calendar event reflects the updated list in a single update
Batch edits to prevent duplicate notifications
Given multiple Prep Pack changes occur within a 5-minute window (e.g., attachments, reordering, access fixes) When saving Then TimeMeld batches them into a single calendar update so attendees receive only one notification Given successive auto-detections occur within 5 minutes of event creation When the event is first saved Then only one update is sent to attendees Given no content changes are detected between saves When saving Then no calendar updates or attendee notifications are sent
Organizer manual override to exclude items before publishing
Given detected pre-reads are listed in the Prep Pack editor When the organizer deselects one or more items before publishing Then excluded items are not attached or linked in the event Given the organizer excluded specific items When the event is later auto-updated due to reschedule or doc changes Then excluded items remain excluded unless the organizer explicitly re-enables them Given the organizer reviews exclusions When viewing the Prep Pack editor Then a summary of excluded items is shown with an option to restore each item
Prep Time Estimation & “Prep by” Scheduling
"As an attendee, I want a clear prep‑by time with a realistic estimate so that I can plan my reading and arrive prepared without last‑minute scrambling."
Description

Estimates total prep effort using document metadata (word count, page count, media length) and heuristics (reading speed ranges, complexity signals). Calculates a recommended “Prep by” timestamp relative to the meeting start and attendees’ time zones, then inserts a concise note at the top of the invite (e.g., “Prep by Tue 3:00 PM (15–20 min)”). Optionally schedules a gentle reminder for attendees who haven’t accessed the materials by the threshold, respecting notification preferences and working hours.

Acceptance Criteria
Accurate Prep Time Estimation from Mixed Materials
Given an invite containing one or more prep materials with detectable metadata (word count, page count, media duration) When the estimation runs Then the system computes a total prep time as a range in minutes by summing per-item estimates Given a text document with word count W When estimating Then the minimum minutes = ceil(W/275) and the maximum minutes = ceil(W/200) Given a media item with duration D minutes When estimating Then both minimum and maximum minutes include D rounded up to the next whole minute Given a PDF or slide deck with only page count P When estimating Then include 2–3 minutes per page in both minimum and maximum ranges Given multiple items When estimating Then the total minimum and maximum equal the sums of per-item mins and maxes, rounded to the nearest 5 minutes Given the computed range where minimum equals maximum When presenting Then display a single value format "(X min)" instead of a range
Timezone‑Aware 'Prep by' Timestamp per Attendee
Given a scheduled meeting with start time T and an attendee with timezone Z and working-hours window H When calculating the 'Prep by' time Then the displayed 'Prep by' time for that attendee is localized to Z and occurs before T Given the estimated prep effort E minutes When calculating the 'Prep by' time Then select a 'Prep by' that allows at least E minutes of working time before T within H; if not possible on the same day, select the nearest prior working-hours boundary within H Given attendees across different time zones When they view the invite Then each sees the same UTC instant localized to their timezone with weekday and time (e.g., Tue 3:00 PM) according to their locale preferences Given the computed 'Prep by' would fall outside an attendee's working hours When calculating Then set it to the last minute of the previous working window before T
Invite Note Insertion and Formatting
Given a calculated 'Prep by' timestamp and prep time estimate When updating the calendar event Then insert a single first-line note in the description with the format "Prep by {EEE h:mm a} ({min}–{max} min)" or "Prep by {EEE h:mm a} ({x} min)" for a single value Given the invite already contains a prior 'Prep by' note When re-running the calculation Then replace the prior note in-place without duplication and preserve the rest of the description unchanged Given organizer locale preferences use 24-hour time When formatting the note Then display 24-hour time (e.g., 15:00) and localized weekday abbreviations Given the meeting time or estimated prep time changes When saved Then the note updates to reflect the new time and duration within 2 minutes Given Google Calendar or Outlook as the provider When inserting the note Then it renders at the top of the description in web and mobile clients
Gentle Reminder for Non‑Accessing Attendees
Given a 'Prep by' timestamp and tracked access signals for prep materials When an attendee has not accessed any material by the reminder threshold (default at 'Prep by') Then schedule and send exactly one reminder to that attendee Given attendee notification preferences indicate opt-out of reminders When reaching the threshold Then no reminder is sent to that attendee Given attendee working hours and quiet hours When scheduling a reminder Then deliver within their working hours before the meeting; if the threshold occurs outside working hours, send at the next start of their working window that still precedes the meeting Given a reminder is scheduled When the attendee accesses any prep material before send time Then cancel the pending reminder Given the meeting has started When evaluating reminders Then do not send any pending reminders
Fallback When Metadata Is Missing or Unreadable
Given a prep material without usable metadata When estimating Then apply fallback heuristics to produce a non-empty time range using default reading speed (200–275 wpm) if text length can be approximated, or 2–3 minutes per page otherwise Given all materials fail metadata extraction When estimating Then still produce a default range of 10–15 minutes and compute a 'Prep by' accordingly Given one or more materials cannot be parsed When presenting the note Then the invite still shows a properly formatted 'Prep by' and duration range
Auto‑Update on Meeting or Materials Change
Given the meeting start time changes When the new time is saved Then recalculate the 'Prep by' and update the invite note within 2 minutes, and reschedule or cancel any pending reminders accordingly Given prep materials are added, removed, or replaced When the event is saved Then recompute the prep time estimate and reflect the new range in the invite note within 2 minutes Given the attendee list changes When a new attendee is added Then their displayed 'Prep by' localizes to their timezone and reminder eligibility respects their preferences and working hours; when an attendee is removed, cancel any pending reminders for them
Permission Health Check & One‑Click Fix
"As an organizer, I want proactive checks and quick fixes for access issues so that I can ensure a smooth meeting without firefighting right before it starts."
Description

Runs automated permission validation 24 hours and 2 hours before the meeting to confirm all externals still have access. Detects revoked or changed permissions, link expirations, or document moves/renames and alerts the organizer with a one‑click repair action. Provides a readiness indicator in the event (e.g., “Prep Pack: All accessible”) and logs fixes. Avoids attendee spam by consolidating updates and only notifying when access is restored or action is required.

Acceptance Criteria
Scheduled Permission Health Checks and Event Readiness Indicator
Given a meeting with external attendees and attached pre-read links When the time reaches 24 hours before the scheduled start Then the system runs a permission health check within 60 seconds and updates the event readiness indicator And when the time reaches 2 hours before the scheduled start Then the system runs the health check again and updates the indicator And if no issues are found Then the indicator text equals "Prep Pack: All accessible" and displays a green status And if issues are found Then the indicator displays "Prep Pack: Issues detected (n)" with an amber/red status and the organizer can view the list of affected items
Detect and Classify Access Issues
Given attached documents referenced in the invite When permissions are revoked or restricted, links expire, or documents are moved/renamed Then the health check flags each impacted item with a specific issue type: Access revoked, Access restricted, Link expired, or Moved/renamed And the system identifies impacted external attendees by email/domain for each item And the system verifies link validity by resolving redirects and current file paths to the new location when applicable And if a document remains accessible to all required externals Then no issue is raised for that item
One-Click Repair Restores Access
Given one or more access issues are detected and the organizer has granted required repair scopes When the organizer clicks "Repair all" or a per-item "Repair" action Then the system attempts automated fixes for supported providers using least-privilege access to restore only the required externals And on success for all items within 30 seconds Then the readiness indicator updates to "Prep Pack: All accessible" and the organizer receives a single confirmation And on partial or full failure Then remaining items are listed with explicit next steps and error reasons, and no duplicate permissions are created on repeated clicks And the repair action is idempotent across retries
Consolidated Organizer Alerts and Attendee Notification Policy
Given multiple access issues may exist across documents When notifying about detected issues or repair outcomes Then the organizer receives a single consolidated alert per health check window summarizing all items and available one-click repairs And attendees are not notified during detection or failed repair attempts And attendees are notified only after access is restored (via provider share notices) or when explicit manual action by the organizer is required And no more than one organizer alert per window is sent unless new issues arise after the initial alert
Audit Log of Fixes
Given any automated repair operation is executed When the operation completes Then an immutable log entry is recorded with timestamp, meeting ID, document identifier, issue type, action taken, actor (system or organizer), outcome (success or failed), and before/after access state hashes And the log is visible to the organizer in the event’s Prep Pack panel within 5 seconds of completion And log entries are exportable as JSON and retained for at least 90 days
Reschedules and Attendee Changes Trigger Re-Validation
Given a meeting is rescheduled or its attendee list changes When the change is saved and at least 5 minutes have elapsed since the prior change Then a new health check is queued within 30 seconds And the next scheduled T-24h and T-2h checks are recalculated to align with the new start time And newly added externals are included in validation and repair And removed attendees are excluded from subsequent repair invites
Performance, Reliability, and Graceful Degradation
Given a health check or repair is initiated When external providers rate-limit or are unavailable Then the system retries with exponential backoff up to 3 times per item and surfaces a clear, non-technical message if unresolved And each health check completes within 120 seconds for up to 50 documents and 50 external attendees, otherwise progress is streamed and partial results are shown And automated repairs never broaden access beyond least privilege (e.g., no public or org-wide links) And all operations respect the organizer’s consented scopes; missing scopes prompt for authorization before proceeding
Activity Log & Rollback Controls
"As a security‑conscious organizer, I want a clear audit log and the ability to undo Prep Pack changes so that I can maintain control and meet compliance needs."
Description

Captures an audit trail of all Prep Pack actions, including detected references, attachments added, links inserted, and permission changes, with timestamps and actor context. Allows organizers to undo specific actions (e.g., revert a sharing change or remove an attached file) and to export the log for compliance review. Respects organization retention policies and surfaces summaries in the event sidebar for transparency.

Acceptance Criteria
Audit Trail Captures Prep Pack Actions
Given a Prep Pack detects references, adds attachments or links, or changes sharing permissions on an event When each action is executed Then an immutable log entry is appended per action with fields: event_id, action_type ∈ {detected_reference, attachment_added, link_inserted, permission_change}, target_resource_id, before_state (nullable), after_state, actor {id, type: user|automation, on_behalf_of (nullable)}, timestamp (ISO 8601 UTC), correlation_id And entries are append-only (update/delete attempts return 403 and no change) And entries preserve execution order (timestamp and correlation_id are monotonic for the request) And viewing the event’s activity log shows exactly one entry per action performed
Rollback Sharing Permission Change by Organizer
Given an event activity log entry of type permission_change within retention And the requester is the event organizer or workspace admin When the requester selects Undo on that entry Then the system restores the target resource’s access to its prior state captured in before_state And a new log entry of type rollback is created linking to the original entry (via correlation_id / reference_id) And only the minimal change required to revert is applied (no-op if already matching before_state) And partial reversions (e.g., some principals no longer exist) are reported with per-principal outcomes And the UI surfaces a success/failure summary to the requester And unauthorized requesters are blocked with 403 and no changes occur
Rollback Attachment Addition
Given an event activity log entry of type attachment_added And the requester is the event organizer or workspace admin When Undo is triggered for that entry Then the attachment/link is removed from the calendar event description/invite And a rollback log entry is appended linking to the original And source files in external repositories are not deleted or altered And the operation is idempotent (repeating Undo yields no further changes and returns Already Reverted) And attendee-visible changes are reflected within 30 seconds
Export Activity Log with Integrity Controls
Given an organizer or workspace admin requests an export of the event’s activity log When the request includes format (CSV or JSON) and optional filters (date range, action types) Then the export contains the selected entries with fields: event_id, timestamp_utc, actor_id, actor_type, action_type, target_id, before_state_hash, after_state_hash, correlation_id, ip_address (if available) And the file is signed with a checksum (SHA-256) provided alongside the download And exports up to 10,000 entries complete within 30 seconds p95 And the download link is single-use and expires after 24 hours And access is denied (403) to non-organizers/non-admins
Retention Policy Enforcement and Legal Hold
Given an organization retention setting of N days When entries exceed N days and are not on legal hold Then entries are purged or redacted according to policy and are excluded from views and exports And Undo is disabled for purged entries with a clear message citing retention policy And retention configuration changes take effect within 24 hours And a daily purge job enforces the policy and logs its actions And entries on legal hold are retained until the hold is cleared
Event Sidebar Summary of Prep Pack Activity
Given a user opens the event sidebar When the Prep Pack Activity Summary is displayed Then it shows counts by action type (detected_reference, attachment_added, link_inserted, permission_change, rollback), the time of last action, and the most recent 5 entries with action_type, target label, actor display name, and relative time And a View Full Log control opens the full activity log view And the summary loads within 500 ms p95 And non-organizers do not see sensitive identifiers for private documents (labels are truncated or anonymized) And tooltips clarify truncated labels without exposing restricted IDs

Role Badges

Labels attendees with lightweight roles (Owner, Facilitator, Decision‑Maker, Scribe, Optional) right in the invite and ICS. Clarifies expectations and reduces “who’s driving?” moments—especially helpful for external or cross‑functional sessions.

Requirements

Role Taxonomy & Governance
"As a meeting organizer, I want to choose standardized roles for attendees so that expectations are explicit and accountability is clear."
Description

Define and enforce a fixed, lightweight role set for meetings: Owner, Facilitator, Decision‑Maker, Scribe, Optional. Provide organization-level settings to enable/disable specific roles and surface concise role definitions and tooltips across the product. Enforce cardinality constraints (max 1 Owner, 1 Facilitator, 1 Decision‑Maker, 1 Scribe; unlimited Optional) with real-time validation. Persist role assignments per event in the TimeMeld data model and expose them in UI, ICS, and provider sync layers. Include conflict detection and resolution prompts when duplicate restricted roles are assigned. Ensure auditability by logging role changes with actor, timestamp, and reason. Support localization of role labels and accessibility-ready color/shape badge variants for distinguishability in low-contrast or color-blind contexts. Outcome: consistent, unambiguous roles that drive clarity and integrate cleanly across all touchpoints.

Acceptance Criteria
Real‑Time Role Assignment with Cardinality Enforcement
Given an event composer with attendees, when a user assigns Owner to attendee A and then attempts to assign Owner to attendee B, then the second assignment is blocked client‑side, an inline error “Only 1 Owner allowed” appears within 200 ms, and no duplicate Owner is stored. Given an event with an existing Facilitator, when a second Facilitator is attempted, then the picker disables the selection and shows a tooltip explaining the 1‑per‑role constraint. Given any number of attendees, when assigning Optional, then no numeric limit is enforced and no validation error is shown. Given the app is offline, when attempting a second restricted role assignment, then the same validation is enforced locally with identical messaging. Given valid role assignments, when the event is saved and reopened, then the exact role assignments persist unchanged.
Org‑Level Role Enable/Disable Governance
Given an org admin disables the Scribe role and saves settings, when a non‑admin opens any role picker, then Scribe is not offered as a selectable option and existing Scribe badges show a tooltip “Role disabled by org.” Given Scribe is disabled at org level, when a client or integrator calls the roles assignment API to assign Scribe, then the request fails with HTTP 400 and error code ROLE_DISABLED. Given Scribe is disabled, when viewing existing events that already contain Scribe, then the badges remain visible (read‑only) and cannot be newly assigned. Given an admin re‑enables Scribe, when users open the role picker, then Scribe is available for selection without requiring a reload of the event editor (settings take effect within the current session).
Conflict Detection and Resolution Prompt
Given attendee A is the current Owner, when a user attempts to assign Owner to attendee B, then a modal appears offering options: Reassign Owner to B or Cancel, with A11y focus trapped in the dialog. Given the modal is shown, when the user confirms Reassign, then A loses Owner, B becomes Owner, no duplicate exists, a success toast appears, and the editor reflects the change immediately. Given the modal is shown, when the user selects Cancel or presses ESC, then no role changes are applied. Given a reassign is confirmed, when the change is executed, then a reason field is required; without a reason, the Confirm action remains disabled.
Persistence and Exposure Across UI, ICS, and Provider Sync
Given roles are assigned in TimeMeld and the event is saved, when the event is reopened in composer and event detail views, then the same badges appear for each attendee with correct roles. Given an event with role assignments, when exporting to ICS, then each attendee includes a vendor property X-TIMEMELD-ROLE with one of [OWNER, FACILITATOR, DECISION_MAKER, SCRIBE, OPTIONAL]. Given a valid ICS containing X-TIMEMELD-ROLE values, when importing into TimeMeld, then the identical role assignments are reconstructed on the event. Given sync to a provider that does not support custom role metadata, when the event round‑trips back to TimeMeld, then all original role assignments are preserved without loss or duplication.
Audit Trail for Role Changes
Given any role is assigned, changed, or cleared, when the change is saved, then an immutable audit record is created with fields: event_id, attendee_id, actor_id, actor_email, action (assign|reassign|clear), role, previous_value, new_value, timestamp (UTC ISO‑8601), reason. Given a user initiates a role change, when they attempt to save without entering a reason, then the save is blocked and an inline error “Reason is required” is shown. Given an admin queries the audit log by event_id, when results are returned, then all role‑change records for that event are listed in chronological order with exact before/after values and actor details. Given the audit API is called with a time‑range and pagination parameters, when results are returned, then they respect the filters and include a stable next/prev cursor or page token.
Localization of Role Labels and Tooltips
Given the user locale is set to es-ES or fr-FR, when viewing role pickers, badges, and tooltips, then labels and concise definitions are displayed in the selected language from the localization resources. Given the user locale is unsupported, when viewing the same UI, then labels and definitions fall back to English. Given ICS export, when roles are written, then X-TIMEMELD-ROLE uses locale‑independent enumerations (OWNER, FACILITATOR, DECISION_MAKER, SCRIBE, OPTIONAL) regardless of UI language. Given a screen reader user, when focusing a role badge, then the aria‑label announces the localized role name (e.g., “Rol: Propietario” in Spanish).
Accessible Role Badges and Interactions
Given role badges are rendered, when evaluated for contrast, then badge text meets WCAG 2.1 AA contrast (≥4.5:1) against background in both light and dark themes. Given color is unavailable or user has a color‑vision deficiency, when badges are viewed in grayscale, then each role remains distinguishable via unique icon/shape patterns verified by automated checks and manual inspection. Given a keyboard‑only user, when navigating the event attendees list, then each badge is focusable in reading order, has a visible focus indicator, and its tooltip is accessible via keyboard without hover dependency. Given a screen reader user, when focusing an attendee with a role, then the announcement follows the pattern “Attendee Name — Role: <Localized Role>”.
Badge Assignment in Scheduler
"As a scheduler, I want to assign and edit roles while picking times so that the invite goes out with clear responsibilities without extra steps."
Description

Add role-assignment controls to the TimeMeld scheduling flow and attendee pane: inline badges, quick-assign dropdowns, keyboard shortcuts, and batch actions (e.g., set selected to Optional). Provide smart suggestions based on past meetings, invitee patterns, and equity scoreboard heuristics (e.g., propose next Owner). Validate constraints in real time, display non-blocking warnings, and auto-resolve when possible (e.g., demote previous Owner to Optional if organizer confirms). Persist edits as draft until the invite is sent. Ensure mobile-friendly interactions and screen-reader support. Outcome: organizers can assign roles without leaving the scheduling context, reducing friction and rework.

Acceptance Criteria
Inline Role Assignment in Attendee Pane
Given I am in the scheduling flow viewing the attendee pane, when I click the role badge next to an attendee, then a dropdown lists Owner, Facilitator, Decision-Maker, Scribe, Optional. Given I select a role from the dropdown, then the attendee’s inline badge updates immediately and the change is saved to the draft. Given I reopen the dropdown for the same attendee, then the currently selected role is preselected. Rule: The UI must reflect role changes within 200ms under nominal conditions and must not block typing or scrolling.
Keyboard Shortcuts for Role Assignment
Given an attendee row has keyboard focus, when I press O/F/D/S/X, then the attendee’s role updates to Owner/Facilitator/Decision-Maker/Scribe/Optional respectively. Given multiple attendees are selected via keyboard, when I press a shortcut, then the role is applied to all selected attendees. Given I press ? while in the scheduler, then a shortcuts overlay appears listing available role assignment shortcuts; pressing Esc closes it. Rule: All shortcut-driven role changes must be functionally equivalent to using the dropdown and update the draft state.
Batch Role Assignment for Multi-Select
Given I select two or more attendees via checkboxes or Shift+Click, when I choose Set Role > Optional from the batch toolbar, then all selected attendees are set to Optional in one action. Given any selected attendee already has the target role, then it remains unchanged and the batch action still succeeds for the rest. Then a confirmation toast indicates how many attendees were updated and provides Undo for 5 seconds. Rule: Batch actions must complete atomically; partial failures surface per-attendee warnings without blocking other updates.
Smart Role Suggestions and Explanations
Given attendees are added or the scheduler opens, then the system surfaces suggested roles inline, including a suggested Owner based on equity scoreboard heuristics. Then each suggestion displays a one-line rationale (e.g., “Rotating Owner; last Owner was Alex”) and a confidence tag (High/Med/Low). Given I click Accept All Suggestions, then all suggested roles are applied to the draft; Reject All clears all suggestions. Given I dismiss a suggestion for a specific attendee, then it does not reappear during the current session unless the attendee list changes.
Real-Time Validation and Auto-Resolve for Owner Conflicts
Rule: Exactly one Owner is allowed per meeting; zero Owners triggers a non-blocking warning; more than one Owner triggers a non-blocking warning. Given I attempt to assign a second Owner, then a non-blocking banner appears within 200ms offering Auto-Resolve: “Make {new} Owner and demote {current} to Optional.” Given I confirm Auto-Resolve, then the previous Owner is set to Optional and the warning disappears. Given I ignore the warning and send the invite, then the send proceeds and a final lightweight reminder offers the same Auto-Resolve option without blocking.
Draft Persistence Until Send
Given I assign roles during scheduling, then the assignments are saved as a draft tied to the tentative meeting and persist across navigation and reload for at least 30 minutes. Given I close and reopen the scheduler to the same draft, then previously assigned roles are restored exactly. Given I click Cancel and confirm discard, then all draft role assignments are removed and not included in any invites. Given I click Send, then the assigned roles are committed to the meeting record and displayed in the invite preview prior to dispatch.
Mobile and Screen-Reader Accessibility
Given a device width between 320px and 768px, then role controls are reachable without horizontal scrolling, tap targets are ≥44x44px, and dropdowns remain within the viewport. Given a screen reader is active, then each role control exposes an accessible name including attendee and current role, and role changes are announced via ARIA live region (e.g., “Owner assigned to Jordan Chen”). Given I navigate with keyboard only, then all role assignment actions (open dropdown, choose role, batch apply, accept suggestions, resolve warnings) are achievable via Tab/Shift+Tab/Enter/Space/Arrow keys with visible focus. Rule: Role assignment UI meets WCAG 2.1 AA for contrast and focus indicators.
ICS Role Encoding
"As an attendee, I want my role to appear in the calendar invite and be visible in my calendar app so that I know my responsibility before joining."
Description

Embed role information into .ics files so all calendar clients can display or at least surface roles. Use human-readable text in DESCRIPTION (e.g., Roles: Owner—A. Lee; Facilitator—R. Kim; Decision‑Maker—J. Patel; Scribe—N. Chen; Optional—list) and add vendor-specific properties for structured data (e.g., X-TIMEMELD-ATTENDEE-ROLE for each ATTENDEE, and X-TIMEMELD-ROLES summary). Preserve compatibility with Google Calendar, Outlook, and Apple Calendar; fall back gracefully where custom properties are ignored. Handle updates and cancellations with correct METHOD values and sequence increments so role changes propagate. Include automated cross-client tests and sample invites. Outcome: roles are visible and portable across calendars, minimizing ambiguity for external attendees.

Acceptance Criteria
Human‑Readable Roles in DESCRIPTION
Given a meeting is created in TimeMeld with attendees assigned roles Owner, Facilitator, Decision‑Maker, Scribe, and Optional When a .ics file is generated for the meeting Then the DESCRIPTION contains a single line that begins with "Roles:" followed by role‑name—display‑name pairs for every assigned role, in this exact order: Owner; Facilitator; Decision‑Maker; Scribe; Optional And each pair uses an em dash "—" between the role and a comma‑separated list of attendee display names; pairs are separated by "; " And unassigned roles are omitted from the Roles line And every display name is taken from the ATTENDEE CN parameter or, if CN is absent, the email local‑part
Structured Role Properties per Attendee
Given ATTENDEE properties exist in the event When the .ics is generated Then for every ATTENDEE there is exactly one X-TIMEMELD-ATTENDEE-ROLE property whose value equals "<CAL-ADDRESS>|<ROLE>", where <CAL-ADDRESS> matches the ATTENDEE value exactly and <ROLE> ∈ {OWNER, FACILITATOR, DECISION_MAKER, SCRIBE, OPTIONAL} And there are no ATTENDEE entries without a corresponding X-TIMEMELD-ATTENDEE-ROLE And there are no X-TIMEMELD-ATTENDEE-ROLE entries for addresses that are not present as ATTENDEE
Event‑Level Role Summary Property
Given roles are assigned to one or more attendees When the .ics is generated Then the event includes exactly one X-TIMEMELD-ROLES property whose value is a semicolon‑delimited list of key=value pairs using uppercase role keys {OWNER,FACILITATOR,DECISION_MAKER,SCRIBE,OPTIONAL} mapped to comma‑delimited mailto: addresses, e.g., OWNER=mailto:a@ex.com;FACILITATOR=mailto:f@ex.com,mailto:g@ex.com And only non‑empty roles are included; there are no empty key=value pairs And the X-TIMEMELD-ROLES value is parseable back to the same role→attendee set found in ATTENDEE and X-TIMEMELD-ATTENDEE-ROLE
Update Propagation for Role Changes
Given an event invite with UID U and SEQUENCE S has been sent When a role assignment changes and an updated .ics is generated and sent Then the updated .ics has METHOD:REQUEST, the same UID U, and SEQUENCE ≥ S+1 with DTSTAMP updated And DESCRIPTION, X-TIMEMELD-ATTENDEE-ROLE, and X-TIMEMELD-ROLES reflect the new assignments And importing the update into Google Calendar, Outlook, and Apple Calendar replaces the existing event rather than creating a duplicate
Cancellation Handling with Correct METHOD/SEQUENCE
Given an event invite with UID U and SEQUENCE S has been sent When the meeting is canceled and a cancellation .ics is generated and sent Then the .ics has METHOD:CANCEL, the same UID U, and SEQUENCE ≥ S+1 with DTSTAMP updated And major clients (Google Calendar, Outlook, Apple Calendar) remove the existing event upon import of the cancellation
Optional and Owner Compatibility via Standard ROLE Parameter
Given attendees are assigned the Optional or Owner roles When the .ics is generated Then ATTENDEE lines for Optional participants include ROLE=OPT-PARTICIPANT And the ATTENDEE line for the Owner includes ROLE=CHAIR And ATTENDEE lines for non‑optional, non‑owner participants include ROLE=REQ-PARTICIPANT
Automated Cross‑Client Tests and Sample Invites
Given continuous integration is executed for the repository When ICS generation tests run Then the test suite produces at least three sample .ics files (new invite, role change update, cancellation) in a versioned samples directory And each sample validates with an iCalendar validator with 0 errors and 0 fatals And tests assert that each sample contains the DESCRIPTION Roles line and the expected X-TIMEMELD-ATTENDEE-ROLE and X-TIMEMELD-ROLES properties
Calendar Provider Sync
"As an organizer, I want roles to stay in sync with Google/Microsoft events so that changes are reflected for everyone without duplicate updates."
Description

Synchronize role assignments with calendar providers when events are created or updated via connected accounts. For Google Calendar, store roles in private extendedProperties and mirror role text in the event description; for Microsoft 365, use singleValueExtendedProperties and body content. Listen to provider webhooks for external edits, reconcile without overwriting unrelated fields, and reapply role formatting if event bodies are modified by clients. Ensure idempotent updates, retry/backoff on API errors, and per-attendee visibility rules for Optional participants. Outcome: roles remain accurate and consistent for all participants regardless of where edits occur.

Acceptance Criteria
Google Calendar: Create Event Roles Sync
Given a TimeMeld user creates a new event with assigned roles and a connected Google account When TimeMeld creates the event via Google Calendar API Then the event must include extendedProperties.private.timemeld.roles as a JSON map of attendeeEmail->role And extendedProperties.private.timemeld.rolesVersion must be a stable hash of the roles payload And the event description must contain exactly one canonical "Roles" section listing each attendee with their role, ordered by role then display name And special characters in names are escaped and preserved And the ICS delivered by Google includes the same Roles section And the operation is idempotent: repeating the same create/update payload produces no duplicate Roles section and triggers no attendee re-notification
Microsoft 365: Create/Update Roles Sync
Given a TimeMeld user creates or updates an event with assigned roles and a connected Microsoft 365 account When TimeMeld calls Microsoft Graph to create/update the event Then singleValueExtendedProperties must include timemeld.roles (JSON map) and timemeld.rolesVersion (stable hash) And event.body.content (HTML) must include exactly one canonical "Roles" section with deterministic ordering and no duplicates And a plain-text rendition of the Roles section is included for ICS consumers And identical subsequent updates are treated as no-ops (no duplicate Roles section and no attendee re-notification)
Webhook Reconciliation on External Edits
Given an event synced by TimeMeld is edited in a provider client (Google/Microsoft) changing non-role fields (e.g., title, time, location) When the provider webhook is received Then TimeMeld fetches the latest event and patches only role-related fields (extended properties and the Roles section), leaving unrelated fields unchanged And if the Roles section was removed or altered by the client, TimeMeld restores the canonical Roles section from extended properties And updates use ETag/If-Match to prevent overwriting concurrent changes And the end-to-end reconciliation completes within 15 seconds at the 95th percentile
Idempotency and No-Op Detection
Given no changes to attendees or roles since the last successful sync When a duplicate webhook is delivered or a scheduled reconciliation runs Then TimeMeld detects a no-op via timemeld.rolesVersion and a computed Roles-section body hash and skips any provider update And no calendar notifications or emails are sent to attendees And an audit log entry records the no-op decision with a correlationId
Retry/Backoff and Error Handling
Given provider APIs return transient errors (429 or 5xx) during a roles sync When TimeMeld performs the update Then it retries with exponential backoff (base 2) and full jitter for up to 5 attempts within a 2-minute window And each retry is idempotent and does not create duplicate Roles sections or re-notify attendees And upon final failure the attempt is marked failed with error details persisted and a follow-up retry scheduled within 10 minutes And a subsequent successful retry results in a single canonical Roles section and correct extended properties
Per-Attendee Visibility for Optional Participants (ICS)
Given an event includes one or more Optional participants When TimeMeld generates and delivers ICS content to attendees Then ICS for Optional attendees shows only their own role label "(Optional)" and redacts other attendees’ role labels as "—" And ICS for non-optional attendees includes the full Roles section with all roles And provider-side extended properties always retain the full roles mapping And redaction does not modify the provider event description or stored roles
Recurring Events: Series vs Instance Role Sync
Given a recurring series has roles defined on the series master When roles are changed on a single occurrence Then the occurrence receives its own timemeld.roles extended properties and updated Roles section without modifying the series master And provider webhooks for the series do not overwrite occurrence-level roles And updates to the series master do not remove occurrence-level role overrides And cancellations or time changes on an occurrence retain its role assignments unless the attendee is removed
Invite & Agenda Rendering
"As an attendee, I want to see role badges prominently in the invite email and agenda so that I can prepare appropriately."
Description

Render role badges prominently in TimeMeld-generated invite emails, event detail pages, and linked agendas. Provide compact, accessible badges with text labels and tooltips; include an optional title suffix/prefix pattern (e.g., [Owner: A. Lee]) configurable per org. Insert a structured roles section at the top of the invite/agenda with anchors for quick navigation. Ensure localization, accessible color contrast, and printable layouts. Support one-click copy to clipboard for role summaries for pasting into docs or chats. Outcome: attendees immediately see who’s driving, facilitating, deciding, and taking notes, improving preparation and meeting flow.

Acceptance Criteria
Invite Email: Role Badges Render and Accessibility
- Given a TimeMeld-generated invite email with at least one attendee per role, When opened in Gmail Web, Gmail iOS, Gmail Android, Outlook Desktop (Win/Mac), Outlook Web, and Apple Mail, Then role badges render with visible text labels and do not wrap or overlap on viewports ≥ 360px wide. - And Then each badge exposes an aria-label "Role: {Role}; Person: {Full name}" and shows a tooltip containing the same text on hover/focus. - And Then badge text and background achieve WCAG 2.2 AA contrast (≥ 4.5:1 for normal text). - And Then the email's plain-text alternative lists roles in the format "[Role] {First initial}. {Last name}" separated by semicolons. - And Then the total email payload added by badge assets is ≤ 25 KB.
Event Detail Page: Roles Section and Anchors
- Given an event detail page, When the page loads, Then a "Roles" section appears directly beneath the event title and start time, within the first viewport at 1366×768, and badges are compact (height ≤ 28 px, 8 px spacing). - And Then each role name is an anchor link (#owner, #facilitator, #decision-maker, #scribe, #optional) that scrolls smoothly to the corresponding attendee list. - And Then anchor targets are reachable via keyboard (Tab to focus, Enter/Space to activate) and visible focus outline meets WCAG 2.2 AA. - And Then deep links to anchors (e.g., /event/123#facilitator) land with the correct section in view. - And Then layout adapts to mobile (≤ 375 px width) by stacking badges without horizontal scrolling.
Linked Agenda: Roles Header and Print Layout
- Given a web agenda linked from the invite, When loaded, Then a Roles header block appears at the top before agenda items, showing badges for each assigned role with text labels and tooltips on hover/focus. - And Then printing from Chrome, Safari, and Firefox on macOS/Windows produces pages where the Roles header is fully visible, uses black text on white background, is not truncated, and fits within one printed page when the agenda body is hidden. - And Then the print stylesheet removes non-essential colors, converts icons to monochrome, disables tooltips, and maintains a minimum 11 pt font size.
Configurable Role Title Pattern (Prefix/Suffix)
- Given an org-level setting "Role title pattern" with options Off, Prefix, Suffix and a template using tokens {role}, {shortName}, {initials}, When a meeting is created or updated, Then the event title is augmented accordingly (e.g., "Sprint Retro [Owner: A. Lee]"). - And Then the pattern is applied to the email subject, the agenda H1, and the iCalendar SUMMARY field. - And Then if the resulting title exceeds 255 characters, the pattern content is truncated with an ellipsis without truncating the base title. - And Then disabling the setting removes the pattern from new outgoing emails and ICS; existing events are not retroactively altered. - And Then per-role inclusion toggles allow excluding Optional roles from the pattern.
Localization of Roles and Tooltips
- Given the viewer's locale is en, es, fr, de, pt-BR, or ja, When viewing the invite email, event page, or agenda, Then role labels and tooltips are displayed in that locale using approved translations. - And Then locale-sensitive punctuation/bracket styles follow the locale's conventions. - And Then if a translation key is missing, the system falls back to English and logs a warning without breaking rendering. - And Then right-to-left locales (ar, he) render badges in RTL order with mirrored layout and preserved anchor IDs.
One-Click Copy: Role Summary
- Given roles are assigned, When the user clicks "Copy roles summary" on the event page or agenda, Then the clipboard receives both text/plain and text/html formats with the string formatted as "Owner: A. Lee; Facilitator: M. Singh; Decision‑Maker: —; Scribe: K. Ito; Optional: N. Rivera" (names based on current attendees). - And Then a success toast "Roles summary copied" appears and is announced via aria-live polite within 2 seconds. - And Then keyboard users can trigger the copy button via Enter/Space and the control has a visible focus state. - And Then if the Clipboard API is unavailable, a fallback textarea select+copy method executes and still results in the same clipboard content.
Resilience and Fallbacks
- Given any role has no assigned attendee, When rendering badges, Then show an "Unassigned" badge with a tooltip "Assign before meeting" and include "—" for that role in copied summaries. - And Then if JavaScript fails to load, server-rendered HTML shows the Roles section with role labels and attendees as plain text. - And Then if CSS fails to load, content remains linearized and readable; anchors still function. - And Then no uncaught errors appear in the browser console during render across latest Chrome, Safari, Firefox, and Edge.
Permissions & Rotation Linkage
"As a team admin, I want role editing permissions and owner rotation suggestions linked to the equity scoreboard so that meetings are fairly owned and controlled."
Description

Tie role editing rights to meeting ownership and workspace policies: by default, Owner and Facilitator can edit roles; admins can override; external attendees cannot reassign roles. Integrate with the equity scoreboard to suggest the next Owner and optionally auto-rotate when scheduling recurring meetings. Provide safeguards if the suggested Owner declines or is external. Surface a lightweight audit trail of role changes in the event history. Outcome: fair, controlled role assignment that aligns with TimeMeld’s ownership rotation and reduces “who’s driving?” confusion.

Acceptance Criteria
Default Role Editing Permissions (Owner & Facilitator)
Given a meeting with designated Owner and Facilitator And no workspace override is enabled When attendees attempt to edit roles in the meeting editor or via API Then only the Owner and Facilitator have enabled controls to add, remove, or reassign roles And all other attendees see role fields as read-only in UI And API attempts by non-Owner/Facilitator return HTTP 403 with error code ROLE_EDIT_NOT_PERMITTED And if no Facilitator is assigned, only the Owner can edit roles
Workspace Policy Configuration for Role Editors
Given a workspace admin opens Role Badges policy settings When the admin selects one policy option from [Owner only, Owner + Facilitator (default), Owner + Facilitator + Decision‑Maker, Admins only] Then new meetings created after saving enforce the selected policy And editing an existing meeting applies the current policy at the time of edit And the policy change is recorded with actor and timestamp in workspace audit logs And users with newly removed permissions immediately lose edit controls upon refresh
Admin Override of Role Editing Rights per Meeting
Given a workspace admin opens a specific meeting When the admin enables "Override role editing rights for this meeting" and selects allowed editors Then the selected users instantly gain role edit permissions for that meeting only And an entry is added to the meeting event history capturing override on/off, selected editors, actor, and timestamp And disabling the override reverts permissions to the workspace policy And API responses for permission checks reflect the override state within 1 second
External Attendees Cannot Reassign Roles
Given an attendee marked as external (outside trusted domains or explicitly flagged) views the meeting When the external attendee accesses the invite or ICS-linked page Then no controls to add, remove, or reassign roles are visible or enabled And API attempts authenticated as the external attendee to modify roles return HTTP 403 with error code EXTERNAL_ROLE_EDIT_FORBIDDEN And system logs a security event for any blocked external edit attempt
Suggested Next Owner from Equity Scoreboard
Given equity scoreboard is enabled for the workspace And a meeting is being created or edited without an assigned Owner When TimeMeld computes the next Owner suggestion Then the "Suggested Owner" is derived from rotation weights and excludes external attendees And the suggestion is presented in under 200 ms for meetings with up to 50 attendees And accepting the suggestion assigns the Owner and appends "Owner set via scoreboard" to event history with actor and timestamp And declining the suggestion records a dismiss event without assignment
Auto‑Rotate Owner for Recurring Meetings with Safeguards
Given a recurring series with "Auto‑rotate Owner" enabled When the next occurrence is generated Then the Owner is auto-assigned per equity scoreboard and must be an internal attendee And if the top candidate is external, the system skips to the next eligible internal and logs the skip reason And if the assigned Owner declines within 24 hours, the system unassigns Owner, notifies Facilitator and prior Owner, and proposes the next eligible Owner for one‑click reassignment And the same person is not assigned Owner for two consecutive occurrences unless an admin override is active
Audit Trail of Role Changes in Event History
Given any change to participant roles (assignment, reassignment, or removal) When the change is saved via UI or API Then the meeting event history records previous role(s), new role(s), actor, timestamp (UTC), and channel (UI/API/import) And the history is visible to Owner, Facilitator, and admins in the meeting History panel And the same data is retrievable via GET /meetings/{id}/history with stable IDs And history visible to external participants redacts internal participant names and emails
Roles API & Webhooks
"As a platform integrator, I want an API and webhooks for role assignments so that I can mirror roles in tools like Notion and Slack."
Description

Expose REST endpoints to read and update role assignments for an event and to list role definitions. Provide outbound webhooks on role_created, role_updated, and role_deleted with secure signing and retry logic. Include fine-grained scopes (read:roles, write:roles) and per-event tokens for external collaborators. Document payload schemas and provide SDK snippets. Outcome: third-party tools (e.g., Notion, Slack, incident bots) can mirror and act on roles, extending Role Badges across the workflow.

Acceptance Criteria
Read roles for an event via REST
Given a valid OAuth2 token with scope read:roles and an existing event with role assignments When the client sends GET /v1/events/{event_id}/roles Then the response status is 200 and Content-Type is application/json And the body contains roles as an array of objects with attendee_id (UUID), role_key (owner|facilitator|decision_maker|scribe|optional), assigned_by (string), and updated_at (RFC3339) And the array reflects the current assignments for the specified event only When the event_id does not exist Then the response status is 404 with error.code = "event_not_found" When the request lacks a valid token Then the response status is 401 with error.code = "unauthorized" When the token is valid but missing read:roles Then the response status is 403 with error.code = "scope_insufficient" When a per-event token for event A is used to read roles for event B Then the response status is 403 with error.code = "event_scope_mismatch" And for a dataset of 100 roles the p95 latency for GET /v1/events/{event_id}/roles is <= 300 ms in staging
Update role assignments for an event via REST
Given a valid OAuth2 token with scope write:roles for event {event_id} When the client sends PUT /v1/events/{event_id}/roles with body { "assignments": [ { "attendee_id": "<uuid>", "role_key": "facilitator" }, { "attendee_id": "<uuid>", "role_key": null } ] } Then the response status is 200 and Content-Type is application/json And the response body returns the full, current set of assignments after applying creates/updates and removals When role_key is not one of owner|facilitator|decision_maker|scribe|optional|null Then the response status is 400 with error.code = "invalid_role_key" When the request is made with a token missing write:roles Then the response status is 403 with error.code = "scope_insufficient" When a per-event token for event A attempts to modify roles for event B Then the response status is 403 with error.code = "event_scope_mismatch" And updates are idempotent: sending the same PUT body twice results in identical role state and a 200 response both times
List role definitions
Given a valid OAuth2 token with scope read:roles When the client sends GET /v1/role-definitions Then the response status is 200 and Content-Type is application/json And the body contains definitions as an array with objects having key (owner|facilitator|decision_maker|scribe|optional), display_name (string), and description (string) And all five standard roles are present exactly once When the request lacks a valid token Then the response status is 401 with error.code = "unauthorized" When the token is valid but missing read:roles Then the response status is 403 with error.code = "scope_insufficient"
Webhook delivery and HMAC signing for role events
Given a subscriber has configured an endpoint URL and shared secret S When a role_created, role_updated, or role_deleted event occurs for an event Then the system sends an HTTPS POST to the subscriber within 5 seconds And the JSON payload includes id (UUID), type (role_created|role_updated|role_deleted), event_id (UUID), attendee_id (UUID), role_key, occurred_at (RFC3339), and attempt (integer) And the request includes headers TimeMeld-Signature (scheme: t=<unix_ts>, v1=<hex HMAC-SHA256 over raw body using S>) and TimeMeld-Event-Id = payload.id And a receiver verifying HMAC with S and tolerance window of 5 minutes accepts the signature as valid When the subscriber responds with any 2xx status Then the delivery is marked successful and no further retries are attempted And deliveries are at-least-once; duplicate payloads include the same payload.id to support idempotency
Webhook retry logic on failure
Given a webhook delivery attempt times out after 10 seconds or receives a non-2xx response When retries are scheduled Then the system retries up to 8 times over approximately 24 hours with exponential backoff (e.g., 1m, 2m, 5m, 10m, 30m, 1h, 6h, 16h) And each retry includes the same payload.id and updated attempt count in the payload and a fresh TimeMeld-Signature header When all retries are exhausted without a 2xx Then the delivery is marked failed with terminal status and reason recorded And if the subscriber later returns 2xx on any attempt prior to exhaustion Then retries cease and the delivery is marked successful
Fine-grained scopes and per-event tokens
Given an OAuth2 token with scope read:roles only When calling GET /v1/events/{event_id}/roles Then the response status is 200 When calling PUT /v1/events/{event_id}/roles Then the response status is 403 with error.code = "scope_insufficient" Given an OAuth2 token with scope write:roles only When calling PUT /v1/events/{event_id}/roles for the permitted event Then the response status is 200 When calling GET /v1/events/{event_id}/roles with a token lacking read:roles Then the response status is 403 with error.code = "scope_insufficient" Given a per-event token issued for event A with scope write:roles When using it to modify roles for event A Then the response status is 200 When using it to read or modify roles for event B Then the response status is 403 with error.code = "event_scope_mismatch"
Documentation, schemas, and SDK snippets
Given the OpenAPI 3.1 specification is published at /docs/openapi.json When validated with a linter (e.g., Spectral default ruleset) Then there are zero errors and no more than 5 warnings And the spec documents endpoints for GET /v1/role-definitions, GET /v1/events/{event_id}/roles, PUT /v1/events/{event_id}/roles, and webhook event schemas with header signing details Given language guides for Node.js and Python When running the provided signature verification snippets against a sample payload and secret Then the verification returns true And request/response examples compile (Node) or run (Python) without errors and produce the documented outputs

Hygiene Score

Real‑time 0–100 quality score that audits title clarity, agenda completeness, conferencing readiness, attachments, and attendee roles. Offers one‑click fixes and optional minimum‑score gating—driving consistent, high‑quality invites that cut “what’s this meeting?” churn.

Requirements

Real-Time Hygiene Scoring Engine
"As a meeting organizer, I want a real-time, explainable hygiene score while drafting invites so that I can improve quality before sending and avoid back-and-forth."
Description

Implements a deterministic 0–100 scoring service that evaluates meeting invite quality in real time from weighted signals (title clarity, agenda completeness, conferencing readiness, attachments, attendee roles). Exposes a client SDK and REST endpoint to compute and stream score updates during event creation and edits with sub-200 ms latency. Supports per-organization weight profiles and default global weights, handles recurring events and updates, and persists score snapshots to the event metadata for auditing and reporting. Ensures idempotent calculations, resilience to partial data (e.g., offline or provider API delays), and clear error states. Outcome: consistent, explainable scores that drive guidance, gating, and analytics across TimeMeld.

Acceptance Criteria
Deterministic 0–100 Score from Weighted Signals
Given a fixed event payload and weight profile When the score is computed across 100 repeated invocations (parallel and sequential) Then the total score is identical each time and is an integer in the range [0,100] Given the same semantic inputs with different field ordering (attendees, attachments) When the score is computed Then the total score and each per-signal contribution are unchanged Given returnBreakdown=true When the score is computed Then the response includes per-signal contributions for titleClarity, agendaCompleteness, conferencingReadiness, attachments, attendeeRoles, which sum exactly to totalScore, and includes weightsUsed with numeric weights for each signal
Sub-200 ms Real-Time Score Updates via REST and SDK
Given a computeScore request via REST or SDK from a regionally colocated client with payload size ≤ 50 KB and no external provider delays When 1000 requests are executed Then p95 latency is ≤ 200 ms and p99 latency is ≤ 300 ms Given a user editing an in-progress event (title, agenda, attendees, conferencing) When 10 successive field changes occur within 2 seconds and the client is subscribed to the score stream Then 10 ordered score updates are received with strictly increasing sequence numbers and the final streamed score equals the score from a direct compute call for the final payload Given the stream connection drops for ≤ 5 seconds When it reconnects Then the client receives the latest score state without duplicate final updates
Per-Organization Weight Profiles with Global Defaults
Given an organization with a custom weight profile version v2 effective now When a computeScore call includes orgId for that organization Then weightsUsed.profileId = v2 and each signal weight equals the stored profile values Given an organization without a custom profile When computeScore is called with that orgId Then weightsUsed.profileId = global-default and weights match the published global defaults Given an admin updates the org’s profile to v3 at time t1 When computeScore is called after t1 Then the response references profile v3 and score differences reflect the new weights; responses before t1 reference the previous version
Idempotent Scoring and Update Ordering
Given the same requestId and identical payload within a 10-minute window When computeScore is called three times Then the returned score and breakdown are identical and exactly one score snapshot is persisted Given different requestIds but an identical payload hash When computeScore is called Then the returned score and breakdown are identical across calls Given two updates received out of order with sequence numbers 5 then 4 When the engine processes them Then the stored score remains the one from sequence 5 and the sequence 4 update is ignored
Resilience to Partial Data and Clear Error States
Given the conferencing provider API times out after 2 seconds When computeScore is invoked Then the response status = PARTIAL, missingSignals includes conferencingReadiness, a totalScore is returned using available signals, and no exception is thrown Given a provider returns a 5xx error for attendee role enrichment When computeScore is invoked Then the response status = PARTIAL if other signals are available; if no signals are available the status = ERROR with error.code populated; in ERROR status, no snapshot is persisted Given previously missing data arrives When a recompute is triggered Then the response status transitions to OK and a new snapshot reflecting the enriched data is persisted
Recurring Events and Series Updates Handling
Given a recurring series with 5 future instances When computeScore is executed at the series level Then 1 series snapshot and 5 instance snapshots are created, each instance snapshot labeled with its instanceId and inheriting series fields Given an update to the agenda of a single instance When recompute runs Then only that instance’s snapshot is updated and the series-level snapshot remains unchanged Given an update to the series template that changes a scoring signal When recompute runs Then all future instances are recomputed and updated; throughput is ≥ 100 instance updates per 2 seconds in the target environment
Score Snapshots Persisted to Event Metadata for Auditing
Given a successful compute with status OK or PARTIAL When the event is saved Then event.metadata.hygieneScore.snapshots append a new record containing totalScore (0–100 integer), perSignal contributions, weightsUsed, profileVersion, status, timestamp (UTC ISO 8601), scoringEngineVersion, and requestId Given the event is edited and saved twice after initial save When snapshots are inspected Then the snapshot count has increased by 2 and earlier snapshot records are immutable (content hash unchanged) Given the latest snapshot is requested for reporting by eventId When retrieved Then the returned record exactly matches the most recently persisted snapshot
Signal Detection Modules (Title, Agenda, Conferencing, Attachments, Roles)
"As a meeting organizer, I want the system to detect missing or low-quality invite elements so that I know exactly what to fix to meet our team’s standards."
Description

Provides modular detectors for each hygiene signal: (a) Title linter checks for length, specificity, action verbs, and anti-patterns. (b) Agenda parser validates presence, structure, and timeboxed items; flags vague content. (c) Conferencing checker verifies a valid link is present, accessible, and mapped to the correct time zone. (d) Attachment inspector confirms required pre-reads/briefs exist and are accessible to all required attendees. (e) Role analyzer ensures at least facilitator/owner and note-taker are assigned; marks optional vs required attendees. Modules run locally first with cloud fallbacks, respect access scopes, support Google Workspace and Microsoft 365, and return normalized findings with confidence scores and remediation hints. Privacy is preserved by processing text locally when possible and redacting sensitive content in logs.

Acceptance Criteria
Title Linter — Length, Specificity, Action Verbs, Anti-Patterns
Given a calendar event title and the default title policy is active When the Title module analyzes the title locally Then it fails "length_bounds" if title length is outside configured min/max (defaults 8–80) And it fails "missing_action_verb" if no action verb from the configured list is present And it fails "anti_pattern_detected" if any configured anti-pattern token is present (e.g., tbd, asap, ???) And it fails "insufficient_specificity" if no specific noun phrase outside the generic stoplist is detected And it passes only if all title rules pass
Agenda Parser — Presence, Structure, Timeboxing, Vague Content
Given an event description/body text When the Agenda module parses content locally Then it passes "agenda_present" if it detects a labeled Agenda section or a bullet/numbered list with at least 1 item And it passes "timeboxed_items" only if each agenda item has a duration in minutes format (e.g., 5m, 10 min) or hh:mm range And it fails "vague_item" for any item comprised solely of terms from the configured vague-phrases list without further detail And it fails "structure_invalid" if items are unstructured paragraphs without separable bullets/numbers
Conferencing Checker — Link Presence, Accessibility, Time Zone Mapping
Given an event with start/end time and timezone, and location/description fields When the Conferencing module scans for conferencing links Then it passes "link_present" when exactly one supported conferencing link is detected (provider list configurable) And it fails "multiple_links" if more than one distinct conferencing link is found And it passes "link_accessible" when a HEAD/metadata check succeeds (HTTP 2xx/3xx or provider API validates meeting id) And it passes "timezone_mapped" when the provider metadata start time (if available) equals the event start time in UTC (±1 minute); otherwise it flags "timezone_mismatch"
Attachment Inspector — Required Pre‑reads Present and Accessible
Given an event with required attendees and zero or more attachment links from supported drives When the Attachments module evaluates attachments Then it passes "attachments_present" when all referenced required artifacts (per configured patterns) are attached And it passes "all_required_can_access" when each required attendee has at least view access to each attachment And it fails "broken_link" for any attachment that returns 4xx/5xx or missing file And it flags "insufficient_scope" without attempting access if the app lacks file-read scope and marks the check as inconclusive
Role Analyzer — Facilitator/Owner, Note‑Taker, Optional vs Required
Given an event with organizer and attendee list (required/optional flags where the provider supports them) When the Roles module analyzes roles Then it passes "facilitator_present" if a Facilitator/Owner is assigned via role field or recognized tag And it passes "note_taker_present" if a Note‑taker is assigned via role field or recognized tag And it passes "attendee_role_marking" if each attendee is marked required or optional (where supported) And it fails the respective rule when any required role is missing or ambiguous
Cross‑Suite Support and Access Scope Compliance
Given equivalent events in Google Workspace and Microsoft 365 with only granted minimal scopes When all signal modules run on each provider Then they produce semantically equivalent pass/fail outcomes for the same inputs And they perform no operations requiring scopes beyond those granted; attempts are recorded as "insufficient_scope" And if a provider-specific capability is unavailable, the module degrades gracefully and marks only the affected rule as "skipped" without failing unrelated rules
Output Normalization, Confidence, Remediation, Local‑First with Privacy Redaction
Given any signal module completes analysis When results are emitted Then each finding conforms to the normalized schema {module, rule_id, outcome in [pass, fail, skipped, inconclusive], confidence [0..1], message, remediation_hint, data_refs[]} And confidence scores are present for every rule outcome And remediation_hint includes at least one actionable suggestion referencing the violated rule And analysis runs locally by default and does not transmit event content off-device And if local analysis fails or is unsupported, a single cloud fallback is attempted and the fallback_reason is recorded And all logs/telemetry redact email addresses, document titles, URLs, and meeting content using the configured redaction policy before storage or transmission
One-Click Auto-Fixes
"As a meeting organizer, I want one-click fixes for issues the score identifies so that I can create high-quality invites with minimal effort."
Description

Delivers actionable fixers tied to each detector to raise the hygiene score with one click: smart title rewrite suggestions, agenda template insertion with timeboxes, auto-insert conferencing link using the user’s default provider, attach recommended docs from recent files, and quick role assignment chips. Fixers preview changes, require minimal permissions, and are reversible. Executing a fix immediately recalculates the score and updates the invite draft. Supports keyboard shortcuts, bulk application, and guardrails to avoid overwriting existing content.

Acceptance Criteria
One-Click Title Rewrite Applies and Recalculates
Given a draft invite with a low title clarity signal and a suggested rewrite is available When the user clicks "Apply title rewrite" Then the invite title is replaced with the suggested title without altering other fields And an undo action is available and restores the original title and hygiene score And the hygiene score is recalculated within 1 second and reflects the improved title clarity And if the title has manual edits in the current session, the fix requires explicit confirmation before applying
Agenda Template Insertion with Timeboxes
Given an invite draft with no agenda content When the user clicks "Insert agenda template" Then an agenda template with timeboxed sections totaling the meeting duration is inserted into the agenda field And existing non-agenda fields remain unchanged And the hygiene score is recalculated within 1 second And if any agenda content already exists, the user is presented with merge options (append, replace, cancel) and no content is overwritten without explicit confirmation
Auto-Insert Conferencing Link Using Default Provider
Given an invite draft without a conferencing link and a default conferencing provider is connected When the user clicks "Add conferencing link" Then a valid conferencing link for the default provider is inserted in the conferencing field And an undo action is available and removes the link And the hygiene score is recalculated within 1 second And if a conferencing link already exists, the fix is not offered or is disabled with an explanation And if the default provider is not connected, the fix prompts a minimal-permission connect flow and does not request broader scopes than required
Attach Recommended Docs from Recent Files
Given the system has access to recent files metadata and recommended documents are available When the user opens the "Attach recommended docs" fix Then the top 3 recommendations are displayed with file title, owner, and last modified And when the user selects one or more and clicks "Attach", the files are attached to the invite And the hygiene score is recalculated within 1 second And if permissions are insufficient, the user is prompted to grant only the minimal scopes needed to attach the selected files And undo removes the attached files without leaving broken references
Quick Role Assignment Chips for Attendees
Given an invite draft with attendees and no roles assigned When the user opens the "Assign roles" fix Then role chips (Owner, Facilitator, Notetaker, Timekeeper, Optional) are displayed for each attendee And selecting a role assigns it to exactly one attendee per role unless the role allows multiples (e.g., Optional) And assignments are saved to the invite metadata and visible to all invitees And the hygiene score updates within 1 second And keyboard navigation allows moving between attendees and roles and applying with Enter/Space
Fix Preview and Undo Consistency
Given any available fix with pending changes When the user clicks "Preview" Then a diff-style preview shows the exact changes that will be applied to the invite And when the user applies the fix, an "Undo" control is shown for at least 30 seconds And clicking "Undo" reverts all changes made by that fix and restores the previous hygiene score with no residual side effects
Bulk Apply and Keyboard Shortcuts
Given multiple applicable fixes are available for the invite When the user selects two or more fixes and presses Cmd/Ctrl+Enter or clicks "Apply all" Then all selected fixes are applied in a single transaction in deterministic order: title, agenda, conferencing, attachments, roles And conflicting fixes are skipped with a non-blocking notice; no existing content is overwritten without explicit confirmation And a single hygiene score recalculation occurs after the batch within 1 second And a single "Undo all" control reverts the entire batch in one action And keyboard shortcuts are discoverable via a tooltip or help panel and operate without focus conflicts
Minimum-Score Gating & Override Workflow
"As an admin, I want to enforce a minimum hygiene score before invites are sent so that our organization maintains consistent meeting quality."
Description

Adds an optional policy that prevents sending or updating a meeting invite below a configurable hygiene threshold. The flow surfaces blocking reasons, offers one-click fixes, and supports time-boxed override with rationale and audit logging. Thresholds can vary by team or meeting template. Handles recurring series edits, external organizers, and cross-domain participants with graceful degradation. Integrates with calendar send actions in Google and Microsoft, and emits events for analytics.

Acceptance Criteria
Block send below threshold with reasons and fixes
Given a user attempts to send or update a meeting invite whose Hygiene Score is below the active threshold for the invite's team or template When they trigger Send/Update in TimeMeld, Google Calendar, or Microsoft Outlook Then the send is blocked before transmission and the UI shows the current score, the required threshold, and a list of failing checks with plain‑language reasons and one‑click fix options And the primary action changes to "Fix issues" and no "Send anyway" option is shown unless policy permits override for this user And the user cannot proceed until the score is at or above the threshold or a permitted override is successfully completed
Real-time one-click fixes update Hygiene Score
Given failing checks are displayed with available one‑click fixes (e.g., add title clarity, add agenda, add conferencing link, attach files, assign attendee roles) When the user applies a fix Then TimeMeld updates the draft invite accordingly and recalculates the Hygiene Score within 500 ms And the failing checks list and score display update immediately to reflect the new state And once the score meets or exceeds the active threshold, the Send/Update action becomes enabled And changes are synchronized back to the connected Google/Microsoft draft without duplication or loss of existing fields
Time-boxed override with rationale and audit logging
Given organizational policy permits overrides and the user has override permission When the user selects Override on a below‑threshold invite Then the user is required to enter a rationale of at least 10 characters and confirm And a time‑boxed override window (policy‑configurable, default 15 minutes) opens during which a single send/update below threshold is allowed And the send/update performed under override is tagged in the invite metadata And an immutable audit record is created capturing timestamp, userId, inviteId, score, failing checks, teamId, templateId, client (Google/Microsoft/TimeMeld), seriesId/occurrenceId if applicable, rationale, and IP And analytics events override_initiated and override_used (or override_expired if not used) are emitted with the same properties And once the window expires or one send occurs, gating is re‑enabled for that invite
Team/Template-specific thresholds and fallbacks
Given an invite is associated with a team and/or created from a meeting template When computing the active hygiene threshold Then TimeMeld applies template‑specific threshold if present, else team threshold, else org default And the UI displays the active threshold value and its source (Template/Team/Org) And changing the team or template updates the active threshold immediately and re‑evaluates the score vs threshold And the active threshold snapshot is persisted with the invite for audit purposes And policy changes apply to future sends/updates and do not retroactively invalidate already sent invites
Recurring series gating and scope-aware fixes
Given a recurring series invite is edited and currently falls below the active threshold When the user chooses to edit "This occurrence" versus "The entire series" Then gating applies only to the selected scope and blocks the scoped send/update until criteria are met or a valid override is used And one‑click fixes applied in occurrence scope affect only that occurrence; series‑scope fixes propagate to future occurrences as allowed by the calendar provider And an override, if used, is logged with seriesId and occurrenceId and does not grant blanket override to other occurrences And partial updates are prevented—the scoped send either succeeds fully or is blocked
External organizers and cross-domain graceful degradation
Given the invite is organized by an external organizer or contains cross‑domain participants limiting edit capabilities When TimeMeld evaluates hygiene checks Then checks requiring unavailable permissions or data are marked Not Applicable and excluded from the score denominator with clear labeling And fix buttons that require disallowed edits are replaced with guidance or request‑access options And TimeMeld does not expose cross‑domain PII beyond what the calendar client already shows And gating does not hard‑block read‑only third‑party updates, but will block TimeMeld‑originated sends/updates that violate enforce policy And audit and analytics records include reason=degraded_capability when degradation occurs
Calendar integration intercept and analytics events
Given the user triggers Send/Update from Google Calendar (Web/Add‑on) or Microsoft Outlook (Web/Desktop Add‑in) with TimeMeld enabled When the Hygiene Score is evaluated against the active threshold Then TimeMeld intercepts the send via provider APIs, preventing transmission if below threshold and no valid override exists And if allowed, the invite is sent exactly once without duplication And integration failures surface a clear error with retry; fallback is safest behavior—block if policy is Enforce, allow if policy is Advisory And analytics events are emitted for gating_shown, fix_applied, gating_cleared, invite_blocked, invite_sent, override_initiated, override_used, override_expired with properties {inviteId, userId, client, score, threshold, teamId, templateId, scope (series/occurrence)}
Scoring UI & Feedback Coach
"As a meeting organizer, I want clear, inline feedback about what’s hurting my score so that I can correct issues without leaving the scheduling flow."
Description

Introduces an unobtrusive score badge and expandable panel within the scheduling UI that shows the current score, per-signal breakdown, weights, and prioritized suggestions. Provides inline highlights in the title and agenda fields, contextual tooltips, and ‘apply fix’ chips. Real-time updates as the user types, with optimistic rendering during provider latency. Fully responsive, accessible (WCAG AA), localized for date/time formats, and instrumented for UX metrics.

Acceptance Criteria
Real-Time Score Update & Optimistic Rendering
Given the scheduler page is open with Title and Agenda fields present And the scoring provider may respond with variable latency When the user types in either field Then the score badge updates within 150 ms with an optimistic estimate if no provider response is available after 300 ms And a syncing indicator is shown on the badge during the optimistic state until the provider response arrives And when the provider response arrives, the score reconciles within 100 ms and differs from the optimistic score by no more than ±5 points And cumulative layout shift caused by score updates is less than 0.1 and no more than 1 visual change per keystroke
Per-Signal Breakdown Panel & Prioritized Suggestions
Given the score badge is visible When the user activates the badge via click or keyboard (Enter/Space) Then an expandable panel opens within 200 ms anchored to the scheduler And it displays the total score (0–100) and the following signals each with weight and subscore: Title clarity, Agenda completeness, Conferencing readiness, Attachments, Attendee roles And suggestions are listed and sorted by projected score gain descending, with the top suggestion focused And collapsing the panel via the same control or Esc closes it within 200 ms and returns focus to the triggering control
Inline Highlights, Tooltips, and Apply-Fix Chips
Given scoring identifies deficiencies in Title or Agenda or Conferencing fields When the user focuses a highlighted field segment Then a contextual tooltip appears within 150 ms describing the issue and how to resolve it And if a one-click fix is available, an apply-fix chip is shown And clicking an apply-fix chip performs the change, updates the field content, and updates the score within 300 ms And an undo control is presented for 5 seconds; activating it reverts the change and restores the prior score And tooltips and chips dismiss on Esc, blur, or after the issue is resolved
Responsive Layout Across Viewports
Given the UI is rendered on different devices When the viewport width is ≥1200 px Then the panel opens as a right-side drawer 360–420 px wide with no horizontal scrolling introduced When the viewport width is 768–1199 px Then the panel opens as a bottom sheet covering 70% of viewport height and all interactive targets are at least 44×44 px When the viewport width is <768 px Then the panel opens as a full-screen modal with the badge pinned within the top app bar And in all viewports, the score badge remains visible and tappable without overlapping native form controls
Accessibility WCAG 2.1 AA Compliance
Given users navigate via keyboard and assistive technologies When tabbing through the scheduler and panel Then focus order follows a logical sequence and every control is reachable and operable via keyboard And the panel/modal traps focus while open and closes with Esc, returning focus to the trigger And all text/icon contrasts are ≥4.5:1; focus indicators are visible (3:1) around interactive elements And dynamic score changes are announced via an aria-live polite region within 1 second without repeating identical messages more than once every 2 seconds And tooltips are accessible on focus and expose name, role, and description to screen readers And automated axe and WAVE scans report no Critical or Serious violations on the feature surfaces
Localization of Date/Time and Number Formats
Given the user’s locale is set to a non-default region When the panel or tooltips reference dates, times, or durations Then time and date strings render in the user’s locale format (e.g., 24-hour vs 12-hour, day/month order) And numbers, percentages, and thousand separators follow the locale conventions And time zone abbreviations reflect the user’s current zone and daylight saving rules And switching the app locale updates all such formats immediately without reload
Instrumentation and UX Metrics
Given analytics is enabled and the user interacts with the scoring UI When the badge is shown, panel is opened/closed, a suggestion is applied/undone, or the score crosses thresholds (e.g., 60, 80) Then events score_badge_viewed, panel_opened, panel_closed, suggestion_applied, suggestion_undone, score_threshold_crossed are emitted with timestamp, anonymized user ID, meeting ID hash, and current score And no raw Title or Agenda text is captured; only lengths and boolean flags are sent And 95% of events are delivered within 5 seconds; overall delivery success ≥98% per session And performance metrics are recorded: time_to_first_score_ms (p95 ≤800), score_update_latency_ms (p95 ≤200), panel_open_latency_ms (p95 ≤150)
Admin Policy & Weight Configuration
"As a product ops admin, I want to tune hygiene weights and policies per team so that the score reflects our operating norms and meeting types."
Description

Offers an admin console for configuring signal weights, minimum-score thresholds, required roles, default agenda templates by meeting type, and conferencing provider preferences. Supports team-level overrides, versioned change history, preview/testing mode, and policy rollout scheduling. Changes propagate to clients within five minutes and can be exported/imported as JSON for backup. Includes permissioning and audit logs.

Acceptance Criteria
Org-Level Signal Weights and Minimum Score Threshold Configuration
- Given an Org Admin is on the Hygiene Policy settings, When they set numeric weights (0–100) for Title Clarity, Agenda Completeness, Conferencing Readiness, Attachments, and Attendee Roles and click Save Draft, Then the system saves a new draft policy and displays normalized weights totaling 100%. - Given any weight is non-numeric, negative, or empty, When saving, Then the save is blocked and field-level errors are shown and no version is created. - Given a Minimum Score Threshold between 0 and 100 is set and the draft is published, Then the effective policy reflects the threshold and the Hygiene Score gating uses it for enforcement.
Required Attendee Roles and Minimum-Score Gating Enforcement
- Given an Org Admin sets required attendee roles per meeting type from [Owner, Facilitator, Note Taker, Decision Maker] and publishes, When a user creates an invite of that meeting type, Then the system validates the presence of all required roles before send. - Given minimum-score gating is enabled and the computed Hygiene Score for an invite is below the configured threshold, When the organizer attempts to send the invite, Then the send is blocked with an error listing unmet criteria. - Given the invite meets all required roles and the score >= threshold, When the organizer sends the invite, Then the send succeeds.
Default Agenda Templates and Conferencing Provider Preferences by Meeting Type
- Given an Org Admin defines a default agenda template for meeting type "Design Review" and publishes, When a user creates a "Design Review" meeting, Then the template content auto-populates the agenda field. - Given an Org Admin sets conferencing provider preferences per meeting type (e.g., Zoom > Google Meet) and publishes, When an organizer without Zoom license creates that meeting type, Then the system selects Google Meet; When the organizer has Zoom, Then Zoom is selected. - Given team-level overrides exist for templates or provider preferences, When a member of that team creates a meeting, Then the team override takes precedence over the org default.
Team-Level Policy Overrides and Inheritance Resolution
- Given an org-level policy is published and a team-level override is created that only modifies signal weights, When evaluating the effective policy for that team, Then the overridden weights come from the team policy and all other settings come from the org policy. - Given a field is not set in the team override, When the org default for that field changes, Then the effective value for the team updates to the new org default. - Given a field is explicitly set in a team override, When the org default for that field changes, Then the team’s effective value remains the team’s explicit value.
Versioned Change History, Rollback, Permissioning, and Audit Logging
- Given policy changes are saved or published, When viewing the change history, Then each change appears as an immutable version with ID, actor, timestamp, scope (org/team), and field-level diff. - Given an admin selects "Rollback to Version X", When they confirm, Then a new draft version is created cloned from Version X; When published, Then it becomes the new effective version. - Given a user without PolicyAdmin permission attempts to create/edit/publish/rollback/import/export/schedule, When they perform the action, Then the system denies with 403 and no version change occurs. - Given any administrative policy action occurs, When viewing Audit Logs, Then an entry exists with actor, timestamp, action, target version, scope, and originating IP; When exporting logs, Then a CSV file is downloaded.
Preview/Testing Mode with Non-Disruptive Evaluation
- Given Preview Mode is enabled for a draft policy, When an admin runs a Hygiene Score simulation against a selected meeting, Then the system shows current score and preview score side by side with contributing signal deltas and no changes are applied to clients. - Given Preview Mode is enabled, When the admin exits Preview without publishing, Then the effective policy remains unchanged. - Given Preview Mode is enabled and the admin publishes the draft, When publishing completes, Then Preview Mode ends and the draft becomes the new effective policy.
Policy Export/Import (JSON), Scheduled Rollout, and 5-Minute Propagation SLA
- Given an admin exports the current policy, When the export completes, Then a JSON file conforming to the policy schema (including version metadata and scopes) is downloaded. - Given an admin imports a policy JSON, When the file is validated, Then a draft policy is created on success; When validation fails, Then field- and path-specific errors are returned and no draft/effective policy is created/changed. - Given a draft policy exists, When the admin schedules activation for a future UTC timestamp, Then the policy becomes the effective policy at that time unless canceled. - Given a policy is published or activated by schedule, When clients poll for configuration, Then clients receive and apply the new effective policy within 5 minutes; When querying client effectivePolicyVersion, Then the version matches the server within 5 minutes.
Hygiene Analytics & Reporting
"As a team lead, I want reports on hygiene scores and their impact on attendance so that I can target coaching and improve meeting effectiveness."
Description

Provides dashboards and exports showing score distributions, trends by team/meeting type, pre/post fix adoption rates, correlation with attendance/no-shows and reschedules, and top recurring hygiene gaps. Enables filtering by timeframe, organizer, and template, and exposes a secure API endpoint for BI tools. Protects sensitive content by aggregating only metadata and redacting free-text fields. Supports CSV export and scheduled email digests.

Acceptance Criteria
Dashboard: Score Distribution by Team & Meeting Type
Given I am an authorized user with Analytics access and a workspace is selected And a timeframe is selected (Last 30 days by default) When I open the Hygiene Analytics dashboard Then I see a histogram of Hygiene Score distribution (0–100) segmented by Team and Meeting Type And each segment displays count and percentage, and totals equal the number of meetings in the filtered dataset (±0 discrepancy) And hover tooltips show exact counts, percentages, and score bucket bounds And no free-text fields (titles, agendas, notes) are displayed—only aggregated metadata And loading completes in ≤5 seconds at p90 for up to 50,000 meetings over 12 months And users without Analytics access receive a 403 error and no data is rendered
Trends Over Time by Team/Meeting Type
Given I have selected a timeframe and at least one Team or Meeting Type filter When I view the Trends widget Then I can toggle Mean and Median Hygiene Score lines over time And I can add up to 5 segments (Teams or Meeting Types) for comparison And missing-data days render as gaps (no interpolation) And all timestamps are displayed in the workspace default timezone and ISO 8601 And tooltips show date, segment, mean, median, and sample size for that day And p90 render time is ≤5 seconds for a 12‑month range with 5 segments And no free-text content is displayed
Pre/Post One‑Click Fix Adoption Rates
Given one‑click fixes are available in the workspace And the dashboard time filter spans at least 14 days before and after the feature enablement date When I open the Fix Adoption widget Then the widget shows Pre vs Post adoption rates (% of invites where ≥1 suggested fix was applied before sending) And the calculation is: adoption_rate = meetings_with_fix_applied / meetings_with_fix_suggested And it displays absolute uplift (percentage points) and relative uplift (%) with sample sizes for each period And filters (Team, Organizer, Template, Timeframe) are applied to both periods consistently And if either period has <100 suggested‑meetings, the widget shows “Insufficient sample” and hides uplift And no free-text content is displayed
Correlation with Attendance, No‑Shows, and Reschedules
Given attendance and reschedule metadata are available for meetings in the selected timeframe When I open the Outcomes Correlation view Then the system computes and displays Pearson correlation (r) between Hygiene Score and attendance rate, no‑show rate, and reschedule rate for the filtered dataset And it also displays binned outcome rates for score buckets [0–49], [50–69], [70–84], [85–100] with counts per bucket And correlations are computed only when sample size ≥200; otherwise show “Insufficient sample” And bucket rows with <20 meetings are greyed and excluded from rate computations And no free-text fields are processed or displayed And p90 compute+render time ≤6 seconds for 100k meetings
Top Recurring Hygiene Gaps
Given the selected filters define a dataset of meetings with Hygiene Score components When I open the Hygiene Gaps table Then I see the top failing checks (e.g., Missing Agenda, Unclear Title, No Conferencing, Missing Attachments, No Roles) ranked by frequency within the filtered dataset And for each check the table shows count, % of meetings affected, and 30‑day trend (sparkline) And clicking a row reveals recommended one‑click fix or template guidance (no raw invite text shown) And sorting by Count or % is available and stable And results contain only metadata about checks, never free‑text samples
Global Filters: Timeframe, Organizer, Template
Given I am on the Hygiene Analytics dashboard When I adjust global filters for Timeframe (Last 7/30/90/180/365, This/Last month, Custom range), Organizer (multi‑select with search), Team (multi‑select), and Template/Meeting Type (multi‑select) Then all widgets on the page update consistently to reflect the selected filters And the active filter state is encoded in the URL (deep link) and is restored on reload or share to another authorized user And clearing filters resets to defaults without stale results And p90 end‑to‑end refresh time after a filter change is ≤3 seconds for datasets up to 50k meetings And unauthorized users cannot access shared deep links (403)
Data Access & Delivery: CSV Export, Scheduled Email Digests, and Secure BI API
Given I have Analytics access When I export CSV from any widget Then the file is UTF‑8, RFC 4180 compliant with headers and includes only metadata columns: meeting_id, date, team, meeting_type, organizer_id, timezone, hygiene_score, checks_failed, fixes_applied, attendance_status, rescheduled, created_at, template_id And it excludes all free‑text fields (title, agenda, notes, attachments names) And exported data respects current filters and timezone and completes within 15 seconds for up to 200k rows When I schedule an email digest (weekly or monthly) Then I can select recipients within the workspace, a dashboard view, and filters And the digest email includes summary KPIs and an attached CSV matching the selected filters And emails are delivered within the scheduled window (±30 minutes) and include unsubscribe/manage‑schedule links When a BI tool calls the Analytics API endpoint /v1/analytics/hygiene with OAuth2 client credentials (scope: analytics:read) Then the API enforces workspace scoping, pagination (cursor), filtering (timeframe, team, organizer_id, template_id), and rate limits (e.g., 600 req/hour/client) And responses are JSON, versioned (x‑api‑version), p95 latency ≤2 seconds for pages up to 5,000 records, and contain only metadata (no free‑text fields) And unauthorized/forbidden requests return 401/403 with no data

Observance Graph

A unified, auto‑updating map of public holidays, regional observances, and org quiet weeks across all attendee locales that feeds TimeMeld’s weighting model. You get accurate, real‑time context baked into proposals—no manual calendar checking, fewer surprise absences, and more respectful scheduling by default.

Requirements

Global Holiday Data Ingestion & Normalization
"As a scheduler using TimeMeld, I want holiday and observance data to be accurate and up to date so that proposed meeting windows don’t land on days attendees are unlikely to attend."
Description

Continuously ingest public holiday and observance data from multiple authoritative sources (government APIs, official ICS feeds, commercial providers) and normalize it into a single canonical schema used by TimeMeld. The pipeline must handle delta updates, de-duplication across sources, conflict resolution via source trust scores, and support for full-day and partial-day observances with explicit start/end times and timezones. Implement robust polling with ETags/If-Modified-Since, webhook subscriptions where available, retries with exponential backoff, and rate limiting. Store observances with metadata (jurisdiction, categories, recurrence rules, confidence, last-updated) in a versioned datastore. Expose a read-optimized service API for downstream consumers (weighting engine, UI) and ensure data lineage auditability for compliance and debugging. Expected outcome: a reliable, up-to-date backbone that powers the Observance Graph with minimal manual maintenance and high accuracy.

Acceptance Criteria
Delta Polling with ETags/If-Modified-Since
Given a source endpoint that advertises ETag and Last-Modified headers When the poller executes on schedule Then it sends conditional GETs using If-None-Match and If-Modified-Since Given the source returns 304 Not Modified When processing completes Then no new versions are created and no write occurs to the datastore Given the source returns 200 OK with a new ETag When processing completes Then only added/changed observances since the last successful poll are upserted as new immutable versions and unchanged records are skipped Given the poller processes a source that does not support ETag/Last-Modified When the poll runs Then the pipeline computes deltas client-side and only writes changed records Given an ingest completes successfully When metrics are emitted Then last_success_timestamp and delta_count are updated
Webhook Event Handling and Reconciliation
Given a provider sends a webhook with signature When received Then the signature is verified using the configured secret and unverified events are discarded Given a valid webhook event with observance changes When processed Then the pipeline fetches and applies the corresponding deltas within 60 seconds Given duplicate webhook deliveries with the same event id When processed Then the operation is idempotent and no duplicate versions are written Given webhook outages or missed deliveries When detected Then the poller performs a catch-up poll within 5 minutes to reconcile missed changes Given out-of-order webhook events When processed Then resulting datastore state is eventually consistent and matches the latest upstream state within 10 minutes
Cross-Source De-duplication and Conflict Resolution via Trust Scores
Given two sources emit the same observance normalized to the same jurisdiction and date When processed Then a single canonical record is produced with merged provenance and the highest-trust source designated as authority Given conflicting fields across sources (e.g., name, start/end time) When resolved Then the value from the source with the highest trust score is selected; ties are broken deterministically by configured source order Given a lower-trust record is currently canonical When a higher-trust update arrives Then a new version is created that supersedes the prior one and the confidence reflects the authority change Given duplicate detection heuristics When validated against a labeled corpus Then match precision is >= 0.98 and recall is >= 0.95 Given a canonical record is formed When stored Then provenance lists all contributing source ids and their individual field contributions
Partial-Day Observances with Explicit Timezones
Given an observance with explicit local start and end times and an IANA timezone When normalized Then store start_at_utc, end_at_utc, start_at_local, end_at_local, timezone, and is_full_day=false Given an observance spanning midnight local or crossing a DST transition When normalized Then UTC times reflect the actual wall-clock duration with no off-by-one-day errors Given a locale with non-hour offsets (e.g., +05:45) When normalized Then conversions are correct to the minute Given overlapping partial-day observances in the same jurisdiction When retrieved via the API Then both are returned distinctly with no unintended coalescing Given an observance marked full-day by upstream When normalized Then is_full_day=true and local day boundaries are respected per timezone
Versioned Datastore and Lineage Auditability
Given any create/update/delete from upstream When written Then an immutable version row is created with version_id, version_created_at, last_updated_source_ts, and soft-delete flags as applicable Given a stored observance When queried for history Then all versions and their diffs are retrievable in order within 200 ms p95 for histories up to 50 versions Given an ingest event When audited Then stored lineage includes source id, request url, request/response headers (incl. ETag/Last-Modified), checksum, and processing job id Given a delete from upstream When processed Then a tombstone version is created and surfaced via the API within 10 minutes Given compliance export is requested When executed Then a complete lineage trail for any observance id is exportable as JSON within 30 seconds
Read-Optimized Service API for Downstream Consumers
Given a query for observances by time window and locale/jurisdiction filters When executed Then the response returns normalized fields (id, name, jurisdiction, categories, start/end utc+local, timezone, is_full_day, recurrence, confidence) with stable pagination cursors Given repeated identical queries within cache TTL When executed Then p95 latency is <= 200 ms and cache hit ratio is >= 0.9 Given consumers request changes since a cursor or timestamp When executed Then only records with version_created_at greater than the cursor are returned along with a new opaque cursor Given clients send If-None-Match ETag on list/get When matched Then the API returns 304 Not Modified with no body Given high-volume clients exceed limits When enforced Then per-client rate limits return 429 with a Retry-After header and are logged with client id
Retry Strategy and Source-Aware Rate Limiting
Given transient upstream failures (HTTP 5xx, timeouts, connection resets) When ingesting Then the system retries with exponential backoff and jitter up to 5 attempts and emits failure metrics Given a provider's documented rate limit of X requests per minute When polling Then the system does not exceed X and spreads requests evenly across the interval Given persistent failures beyond the retry budget When encountered Then a circuit breaker opens for 5 minutes and an alert is dispatched to on-call Given global backoff is in effect across multiple sources When scheduled Then no source starves others and the ingest SLA of applying upstream changes within 15 minutes p95 is maintained
Locale–Jurisdiction Mapping Engine
"As a product manager scheduling across regions, I want attendees’ applicable jurisdictions resolved automatically so that I don’t have to research each person’s local observances."
Description

Determine which jurisdictions’ observances apply to each attendee by mapping their locale signals (profile location, primary calendar region, declared work site, and timezone) to ISO-3166 country/subdivision codes and, where relevant, city-level rules. Support multi-jurisdiction cases (e.g., remote worker residing in one state but attached to a different company site), precedence rules (federal vs. state vs. municipal), and religious/optional observances. Provide deterministic mapping, caching for performance, and an auditable decision trace per attendee. Integrates with user profile services and respects privacy by avoiding IP inference, using only declared attributes and org assignments. Output feeds directly into the Observance Graph and weighting model.

Acceptance Criteria
Deterministic ISO-3166 Mapping from Declared Locale Signals
Given an attendee with declared signals {profile_location, primary_calendar_region, declared_work_site, timezone} When the mapping engine processes the attendee Then the output includes ISO-3166-1 alpha-2 country_code and ISO-3166-2 subdivision_codes corresponding to the declared signals And the same input produces identical output and rule_version across 100 repeated runs And timezone is used only as a disambiguator when higher-priority signals are absent or conflicting And no inputs beyond the declared signals are read or logged And daylight saving time transitions do not change the mapping
Multi-Jurisdiction Assignment for Remote Worker and Site Attachment
Given a remote attendee residing in CA-ON with declared work site US-WA When the mapping engine processes the attendee Then the output enumerates jurisdictions for both residence (CA, CA-ON) and site (US, US-WA) And multi_jurisdiction is true and includes distinct source_tags ['residence','work_site'] And jurisdiction sets are not merged across countries And decision_trace records both paths and the precedence between them
City-Level Rules Resolution and Precedence
Given an attendee located within a municipality that maintains observance rules (e.g., New York City within US-NY) When the mapping engine runs Then the output includes a municipal identifier from the approved city catalog and links it to its parent ISO-3166-2 subdivision And precedence_order is ['federal','subdivision','municipal'] unless an org policy elevates municipal, which is reflected in decision_trace And for same-day overlaps, the higher-precedence level is marked effective and lower levels marked shadowed in the trace
Religious and Optional Observances Inclusion Controls
Given org policy include_religious=false and the attendee has not opted in When the mapping engine runs Then no religious/optional observance jurisdictions are included Given org policy include_religious=true and the attendee has selected traditions ['Jewish','Muslim'] When the mapping engine runs Then religious jurisdictions for the selected traditions are included with type='religious' and are tagged as optional And removing the selection removes those jurisdictions within 1 minute of profile update propagation And decision_trace shows the policy and attendee preference gates used
Caching, TTL, and Performance Budgets
Given a previously computed mapping within TTL=24h for an attendee and unchanged inputs When the mapping engine runs Then the result is served from cache with P95 latency <= 50 ms and includes cache=true in metadata Given a cold start (no cache) When the mapping engine runs Then P95 latency <= 300 ms under 200 rps with P99 <= 500 ms in staging benchmarks And cache keys include profile_id and profile_version, and cache is invalidated within 2 minutes of relevant profile changes And stale-while-revalidate serves the prior result for up to 5 minutes on backend errors and records a revalidation attempt
Auditable Decision Trace and Retention
Given any mapping result When a decision trace is requested by an authorized auditor role Then the trace includes: ordered rules evaluated, input signal values, jurisdiction candidates, inclusions/exclusions with reasons, rule_version, data source versions, timestamps, and correlation_id And the trace redacts PII beyond declared signals, contains no IP addresses, and is retained for 180 days And access is enforced via RBAC and is logged with immutable audit entries
Output Contract to Observance Graph and Weighting Model
Given a successful mapping result When the Observance Graph ingests the output Then the payload validates against schema version 'jurisdiction_map.v1' and contains jurisdictions with types in ['country','subdivision','municipal','religious'] and codes conforming to ISO or approved catalog IDs And ingestion acknowledgment is received and recorded within 1 minute, or retry with exponential backoff continues up to 15 minutes with dead-letter on failure And the weighting model applies the jurisdiction set without schema translation errors (0 ingestion failures over 1,000 test records)
Org Quiet Weeks & Company Calendar Management
"As an org admin, I want to set company quiet weeks that automatically influence scheduling so that teams aren’t interrupted during planned downtime."
Description

Enable org admins to define, import, and manage company-wide quiet weeks and internal observances that should de-weight or hard-block scheduling. Provide an admin UI to create date ranges, partial-day rules, recurring patterns, and exceptions; support CSV/ICS import and version history with effective dates. Allow scoping by department, location, or team. Ensure these entries are merged into the Observance Graph with clear precedence relative to public holidays, and surface them to the weighting engine and UI consumers. Provide APIs/webhooks so HRIS or internal calendars can sync changes automatically.

Acceptance Criteria
Admin Creates Company-Wide Quiet Week (Hard-Block)
Given I am an Org Admin with Calendar Management permission When I create a quiet period with Start = 2025-12-22 00:00, End = 2025-12-26 23:59, Time Zone = Org Default, Rule Type = Hard-Block, Scope = Organization, Reason = "Winter shutdown" and click Save Then an entry with these attributes is persisted with a unique ID And the Observance Graph includes this entry for all org attendees within 60 seconds And the weighting engine excludes any time in that range from all scheduling proposals involving org members And UI consumers display a "Company Quiet Week" indicator for those dates with the reason And if a public holiday also occurs during this period, the period remains blocked (company hard-block takes precedence) And GET /api/v1/observances returns the entry with source = "company", scope = {"type":"organization"}, status = "active"
Partial-Day Quiet Hours within Date Range (De-Weight)
Given an Org Admin creates a quiet rule for 2025-10-01 to 2025-10-05 with Daily Window = 13:00–17:00, Rule Type = De-Weight 60%, Scope = Organization, Time Zone Mode = Attendee Local When proposals are generated for attendees across multiple time zones Then for each attendee, candidate slots that fall within 13:00–17:00 in their local time have a 60% reduction applied to their scheduling weight And candidate slots outside the window are unaffected And proposal scoring output includes an adjustment reason "company-quiet-hours" with value 0.60 for impacted slots And UI consumers show a "Quiet Hours" badge on impacted slots with local times
Recurring Quarterly Quiet Week with Exceptions
Given an Org Admin defines a recurring quiet period: Frequency = Quarterly, Pattern = First full work week, Rule Type = Hard-Block, Start = 2025-01-01, No end And adds an exception excluding 2025-07-01 through 2025-07-07 When occurrences are computed Then the next 12 occurrences are materialized and visible in the admin UI and via GET /api/v1/observances?expand=occurrences And the July 2025 occurrence is omitted due to the exception And adding an inclusion exception for 2025-07-03 reinstates only that date And updates propagate to the Observance Graph within 60 seconds
Scope Quiet Rules by Department, Location, Team
Given HRIS sync has populated user attributes Department, Location, and Teams And an Org Admin creates a quiet rule with Rule Type = Hard-Block and Scope = Department: Engineering, Location: EMEA, Team: Mobile When generating proposals for a meeting that includes at least one attendee matching all specified scope filters Then times covered by the rule are excluded for that meeting And for meetings with no attendees matching the scope filters, the rule does not apply And if an attendee’s attributes change such that they no longer match, the rule stops applying to meetings including them within 5 minutes of the attribute update And GET /api/v1/observances returns the scope filters and affected_attendee_count
Import Quiet Periods via CSV/ICS
Given a CSV with headers: title,start_date,end_date,rule_type,scope_type,scope_values,timezone,recurrence,external_id and an ICS file containing VEVENTs When an Org Admin uploads a CSV or ICS file to the Import dialog and confirms the import Then a preview lists parsed entries with scoped attendee counts and validation errors annotated with row number or UID And rows with duplicate external_id or identical (title, date range, scope) are deduplicated And invalid rows are skipped; the summary reports created, updated, skipped with reasons And confirmed imports create or update entries; ICS all-day events normalize to 00:00–23:59 in the event’s timezone And the Observance Graph reflects imported entries within 60 seconds
Version History and Effective-Dated Changes
Given an existing quiet rule v1 is active When an Org Admin edits the rule, sets Effective From = 2025-11-01 00:00, and changes Rule Type from De-Weight 30% to Hard-Block Then v2 is stored with effective_from = 2025-11-01 and v1 remains active until 2025-10-31 23:59 in the rule’s timezone And audit history records actor, timestamp, and field diffs And queries for the Observance Graph at 2025-10-15 return v1 and at 2025-11-15 return v2 And clicking Rollback creates v3 that restores v1 fields with effective_from = now
HRIS and Internal Calendar Sync via API/Webhooks
Given the organization has configured API credentials and a signed webhook endpoint When an external system POSTs to /api/v1/company-observances with a valid HMAC signature and an Idempotency-Key to create or update a quiet rule Then the API responds 201 Created or 200 OK with resource ID and current version And repeated POSTs with the same Idempotency-Key are idempotent and return the same resource state And internal changes trigger a company.observance.updated webhook within 60 seconds including version, effective_from, and scope And failed webhook deliveries are retried with exponential backoff for at least 24 hours and appear in a delivery log And disabling the integration stops further webhooks and API access returns 401 Unauthorized
Weighting Model Integration with Observance Constraints
"As a scheduler, I want TimeMeld to automatically down-rank or exclude times that fall on attendees’ observances so that proposals are respectful and more likely to be accepted."
Description

Incorporate observance signals into TimeMeld’s ranking engine to de-weight or block proposed meeting windows. Define rules for hard blocks (e.g., full-day national holidays) and soft penalties (e.g., regional observances, partial-day events, optional religious holidays), with additive impact across attendees. Respect meeting criticality and required/optional attendee roles, and support feature flags per workspace. Ensure the scoring adjustments are deterministic, explainable, and performant at proposal time. Provide configuration to tune penalties by org policy and meeting type, and unit-tests to validate boundary cases (time zone midnight crossovers, DST transitions, and half-days).

Acceptance Criteria
Hard Block of Full‑Day National Holidays
Given a candidate meeting window overlaps any portion of a full‑day national holiday for a required attendee in that attendee’s local time zone When the ranking engine evaluates proposals Then that window is excluded from the candidate set and not proposed And the exclusion reason is recorded as hard_block with attendee_id and observance_id Given a candidate window overlaps a full‑day national holiday only for optional attendees When the ranking engine evaluates proposals Then the window is not excluded And a configured hard_block_optional_penalty is applied once per affected optional attendee Given a candidate window crosses midnight UTC but falls on a holiday date locally for a required attendee When evaluating overlap Then the hard block decision uses the attendee’s local calendar date boundaries (00:00–24:00 local) Given a window is hard blocked for any required attendee When multiple rules could apply Then soft penalties are not additionally applied to that window
Soft Penalties and Additive Impact for Regional/Partial/Optional Observances
Given a regional observance applies to an attendee and a candidate window overlaps it by X% of the window duration for that attendee’s local time zone When scoring the window Then apply a soft penalty of configured(regional_penalty) × X to the window score for that attendee Given a partial‑day observance (e.g., 13:00–17:00 local) overlaps a candidate window for Y minutes When scoring the window Then compute overlap_fraction = Y / window_duration and apply configured(partial_day_penalty) × overlap_fraction for that attendee Given an optional religious observance applies to an attendee When scoring Then never hard block the window due to that observance And apply configured(optional_religious_penalty) × overlap_fraction for that attendee Given multiple attendees have observances affecting the same window When producing the final score Then the total observance penalty equals the sum of per‑attendee penalties (no double counting per attendee per observance) And the sum respects configured min/max clamps if defined Given no overlap exists between the window and any observance for any attendee When scoring Then the observance penalty contribution equals 0
Role and Meeting Criticality Awareness
Given an affected required attendee When applying a soft penalty Then multiply the per‑attendee penalty by configured(required_role_multiplier) ≥ 1 Given an affected optional attendee When applying a soft penalty Then multiply the per‑attendee penalty by configured(optional_role_multiplier) ≤ configured(required_role_multiplier) Given a meeting marked as critical per meeting type configuration When computing soft penalties Then multiply the aggregated soft penalty by configured(criticality_multiplier) ∈ (0,1] And never bypass a hard block due to criticality Given a non‑critical meeting When computing penalties Then use configured(criticality_multiplier)=1
Workspace Feature Flag Gating
Given the workspace feature flag observance_weighting is OFF When generating proposals for any request Then the ranking output (order and scores) matches the baseline model without observance adjustments within exact equality And no observance_adjustments appear in explanations Given the workspace feature flag observance_weighting is ON When generating proposals Then observance penalties/blocks are applied per rules And explanations include applied observance_adjustments Given two workspaces with different flag states When generating proposals concurrently Then each workspace’s behavior reflects its own flag value without cross‑contamination Given the flag state is toggled When the next proposal request is processed Then the new behavior takes effect immediately for that request
Configurable Penalty Weights by Org Policy and Meeting Type
Given workspace‑level configuration exists for penalty weights, role multipliers, and criticality multipliers per meeting type When reading configuration at proposal time Then the engine uses the meeting‑type‑specific values if present, else falls back to workspace defaults, else to system defaults Given an admin updates the configuration via API with valid values within allowed ranges When the change is saved Then subsequent proposal requests reflect the new values within 60 seconds or the next cache refresh, whichever is sooner Given an admin submits invalid configuration (out of range or malformed) When processing the update Then the request is rejected with 400 and the previous effective configuration remains in use Given configuration changes When cache invalidation occurs Then the in‑memory configuration snapshot is refreshed without requiring service restart
Deterministic, Explainable, and Performant Scoring
Given identical inputs (attendees, time zones, observances snapshot, configuration, candidate windows) and clock‑independent evaluation When scoring is executed multiple times Then the produced scores, rankings, and explanations are byte‑for‑byte identical And ties are broken by a stable tiebreaker (earlier start_time, then window_id) Given a scored window When returning the explanation Then it includes: window_id, total_observance_delta, and per‑attendee adjustments with attendee_id, observance_id, observance_type, overlap_fraction, role, criticality_multiplier, and delta_applied Given a warm cache of the Observance Graph and configuration When scoring up to 100 candidate windows for up to 20 attendees across up to 6 locales Then end‑to‑end proposal scoring completes in ≤ 250 ms at P95 and ≤ 50 ms at P50 And no external network calls occur on the scoring path Given a cold start without cache When the first scoring run occurs Then end‑to‑end scoring completes in ≤ 800 ms at P95 And the cache is populated for subsequent runs
Boundary Unit Tests: Midnight Crossovers, DST Transitions, Half‑Days
Given a required attendee with a full‑day holiday on 2025‑07‑04 local When evaluating a window 2025‑07‑03T23:30Z–2025‑07‑04T00:30Z that maps into 2025‑07‑04 local Then the window is hard‑blocked for that attendee Given a partial‑day observance 13:00–17:00 local When evaluating windows entirely before, entirely after, partially overlapping, and fully within that range Then computed overlap_fraction is 0, 0, proportional in (0,1), and 1 respectively Given a DST spring‑forward transition where 02:00–03:00 local is skipped When computing overlap with an observance spanning 01:00–04:00 local Then overlap is computed in absolute elapsed minutes and not wall‑clock label counts Given a DST fall‑back transition where 01:00–02:00 repeats When computing overlap for a 90‑minute window crossing the repeat Then the overlap minutes account for the repeated hour once, matching actual elapsed time Given multiple observances overlap for the same attendee (e.g., regional + partial‑day) When scoring Then per‑attendee penalties sum for distinct observances without exceeding configured per‑attendee max if defined
Availability Overrides & Exceptions
"As an attendee, I want to mark myself as available despite a local observance for a specific meeting so that critical discussions can proceed when I’m willing to join."
Description

Allow attendees to override observance-based constraints when they choose to be available. Support two scopes: per-meeting (one-time) and profile-level (temporary window). Overrides must expire automatically, be reversible, and be recorded with minimal disclosure to others (e.g., shown as "available" without exposing the specific observance). Ensure overrides immediately recalculate proposals, propagate to the weighting engine, and are captured in audit logs for traceability. Provide guardrails to prevent org policy violations where hard blocks are mandated.

Acceptance Criteria
One-Time Override on Holiday Updates Proposals
Given an attendee is blocked by an observance on a proposed meeting date/time And a meeting proposal shows that attendee as unavailable due to the Observance Graph When the attendee selects "Available for this meeting only" on that proposal Then the proposal refreshes and marks the attendee as available within 10 seconds And the slot’s weighting changes from blocked to calculable (non-zero) in the weighting engine within 10 seconds And other attendees see the attendee as available without any observance name or reason displayed And an audit log entry is created with user, meeting ID, override scope=one-time, timestamp, and previous/new availability state And the override applies only to the selected meeting occurrence and not to other meetings
Profile-Level Temporary Availability Window Across Observance Period
Given an attendee has an upcoming regional observance that would block proposals for a date range When the attendee creates a profile-level temporary availability window with start and end timestamps Then proposals generated for meetings during that window treat the attendee as available within 10 seconds of saving And the override auto-expires exactly at the end timestamp (respecting the attendee’s profile timezone) without user action And upon expiry, proposals and weights revert within 10 seconds to reflect observance-based constraints And the user can edit or cancel the window before expiry, with changes taking effect within 10 seconds And the override window is recorded in the audit log with scope=profile, window start/end, and change history
Revoke Active Override and Recalculate
Given an attendee has an active availability override (one-time or profile-level) When the attendee revokes the override Then the attendee’s availability reverts to observance-based behavior within 10 seconds in all open proposal views And the weighting engine updates and cached recommendations are invalidated within 10 seconds And an audit log entry records the revocation with user, scope, target (meeting ID or window), timestamp, and previous/new state And revocation is idempotent (a second revoke request has no effect and returns a safe response) And the UI confirms success and reflects the reverted state without exposing observance details
Prevent Override on Org-Mandated Hard Block
Given an organization has a policy-marked hard block period (e.g., company shutdown week) When an attendee attempts to create an availability override that intersects a hard block Then the system blocks the override creation and displays a non-sensitive policy message (no observance details) And no change is applied to proposals or the weighting engine And an audit log entry records the blocked attempt with policy reference and timestamps And API and UI both enforce the block consistently And any existing soft overrides are ignored during the hard block window
Minimal Disclosure in Participant and Calendar Surfaces
Given an attendee’s availability changes due to an override When other attendees view proposals, invites, or attendee chips Then only the availability state (e.g., "available") is shown without naming the observance or reason And exported ICS/Calendar invites contain no observance names or personal notes related to the override And organizer dashboards show aggregate availability counts without per-user observance labels And no terms from the Observance Graph taxonomy (holiday names, region codes) appear in participant-visible surfaces And an automated test verifies redaction across UI, ICS, and API responses
Traceable Audit Log of Overrides
Given overrides must be auditable for compliance When any override is created, updated, revoked, or blocked by policy Then an audit record is written with: actor, scope (one-time/profile), target (meeting ID or window), timestamps (created/updated), action type, and pre/post availability state And policy evaluation outcome (allowed/blocked with policy key) is included And no observance names or sensitive details are stored in the log message fields And audit records are immutable, time-ordered, retained for at least 12 months, and accessible to workspace admins via export/API And audit writes succeed or the user-facing action is rolled back with a clear error
Weighting Engine Propagation and Client Consistency
Given a saved override affects at least one proposed slot When the override is applied Then the weighting engine recalculates affected slot scores and ordering within 10 seconds And all active clients (web, mobile) receive updated proposals or a refresh prompt within 15 seconds And cache layers invalidate affected keys within 10 seconds And in concurrent overrides on the same attendee/slot, last-write-wins is enforced and reflected in audit ordering And monitoring captures latency SLOs with p95 under 10 seconds for recalculation events
Explanations & UI Indicators
"As a scheduler, I want to see why certain times are discouraged or blocked so that I can make informed tradeoffs or adjust the attendee list."
Description

Surface clear, accessible indicators in the proposal UI and slot picker that explain when and why a time is blocked or de-weighted due to observances. Show per-slot badges (e.g., "2 attendees impacted: US Labor Day") with tooltips that list affected jurisdictions and whether the constraint is hard or soft. Provide a drill-down panel with the reasoning trace from the weighting engine and links to the underlying observance entries. Ensure localization, keyboard accessibility, and performance so that explanations render instantly without delaying proposal generation.

Acceptance Criteria
Per-slot Soft Observance Badge and Tooltip
Given a proposed meeting slot is de-weighted by a soft observance affecting exactly 2 of 5 attendees (e.g., US Labor Day) When the slot is rendered in both the Proposal UI and the Slot Picker Then a badge appears adjacent to the slot with the text "2 attendees impacted: US Labor Day" And the badge uses the soft/de-weighted visual style distinct from the hard-block style And focusing or hovering the badge shows a tooltip listing the affected jurisdictions (e.g., "United States — Labor Day"), the constraint type "Soft (de-weighted)", and the impacted attendee count (2) And if multiple observances apply, the badge shows the first observance name and a "+N" suffix, while the tooltip lists all up to 10 with a "+more" summary And the badge content and presence are consistent between the Proposal UI and the Slot Picker
Hard-Blocked Slot Indicator and Behavior
Given a proposed meeting slot overlaps any hard observance (e.g., org quiet week or a hard public holiday) for at least one attendee When the slot is displayed in the Proposal UI and the Slot Picker Then the slot shows a "Blocked" indicator and the time option is disabled for selection And the tooltip explains the reason (e.g., "Hard block: Q3 Quiet Week — Engineering (Org-wide)" or the holiday name) and lists affected jurisdictions And attempts to select the slot are prevented and produce a non-blocking notice explaining the hard block And auto-generation of proposals excludes hard-blocked slots entirely
Reasoning Trace Drill-Down with Source Links
Given a user clicks the "Why?" or equivalent control on a slot with non-zero observance weight adjustments When the reasoning panel opens Then it loads within 200 ms at p95, showing a skeleton state if slower And it lists each contributing observance with: name, jurisdiction/region, date(s), constraint type (hard/soft), affected attendee count, and weight delta applied And the panel provides working deep links to the corresponding Observance Graph entries, opening in a new tab without navigating away And the sum of weight deltas displayed matches the slot’s visible weighting score within ±0.5% And if no observance factors exist, the panel shows a clear "No observance factors" empty state
Localized Indicators and Tooltips
Given the user’s locale is set (e.g., en-US, fr-FR, es-ES) and timezone reflects their region When badges, tooltips, and the reasoning panel are rendered Then all fixed UI strings are localized to the user’s locale, including hard/soft labels and impacted counts And dates/times and numbers follow locale formatting rules (e.g., 24h vs 12h, day/month order) And holiday/observance names display localized names where available, otherwise cleanly fall back to English without broken tokens And pluralization is correct for 0/1/many cases in each supported locale And RTL locales (e.g., ar) render without layout breakage, with icons and reading order correctly mirrored
Keyboard and Screen Reader Accessibility for Explanations
Given a keyboard-only user with a screen reader (e.g., NVDA/Chrome on Windows) When navigating the Proposal UI and Slot Picker Then badges and the "Why?" control are reachable in logical tab order without traps And tooltips open via keyboard (Enter/Space) and on focus, and close via Esc or moving focus And tooltips have role="tooltip" and are associated via aria-describedby so the screen reader announces observance name, jurisdiction(s), impacted count, and hard/soft status And the "Blocked" state is announced with role/state that conveys non-interactive/disabled status And color contrast for badges/indicators meets WCAG 2.2 AA (≥ 4.5:1 text, ≥ 3:1 non-text) and tooltips remain readable on high-contrast modes
Non-blocking Performance of Explanations Rendering
Given a calendar with 50 proposed slots, 20 attendees across 6 locales, and 10 active observances When the Proposal UI loads with explanations enabled Then explanations do not introduce synchronous network calls that block proposal generation And the p95 delta in time-to-interactive versus explanations disabled is ≤ 10 ms And per-slot badge render time at p95 is ≤ 5 ms; tooltip open latency p95 is ≤ 50 ms; reasoning panel first contentful paint p95 is ≤ 200 ms And main-thread CPU time attributable to explanations for the full slot list is ≤ 15 ms And added client bundle size for explanation UI logic is ≤ 50 KB gzipped And data is sourced from a preloaded Observance Graph cache; on cache miss, placeholders render immediately without blocking
Data Freshness, Caching & Resilience Monitoring
"As a reliability engineer, I want observance data health and freshness to be monitored with safe fallbacks so that scheduling remains dependable during upstream issues."
Description

Implement SLAs and monitoring for observance data freshness per jurisdiction with health checks, lag metrics, and alerts on ingestion failures or stale data. Use multi-tier caching (in-memory, edge) with jurisdiction-specific TTLs, and provide eventual-consistency guarantees and last-known-good fallbacks during upstream outages. Record provenance and versioning to enable rollback and replay. Expose status dashboards to admins and integrate with on-call paging. This ensures the Observance Graph remains reliable even under provider outages or network issues and that TimeMeld proposals remain trustworthy.

Acceptance Criteria
Jurisdiction Freshness SLA Monitoring and Alerting
Given each jurisdiction has a configured freshness_SLA_minutes and poll_interval_minutes When the computed ingestion lag for a jurisdiction exceeds freshness_SLA_minutes for 2 consecutive polls Then the jurisdiction status is set to "Stale" and a high-severity alert is sent to the on-call paging system within 60 seconds containing jurisdiction_id, current_lag_minutes, last_success_at, provider_name, and run_id. Given a jurisdiction is in "Stale" When its lag stays at or below freshness_SLA_minutes for 2 consecutive polls Then the status transitions to "Healthy" and a recovery notification is sent. Given multiple jurisdictions breach SLA within a 15-minute window When alerts are emitted Then alerts are deduplicated and grouped per jurisdiction so that no more than 1 page per jurisdiction is sent within the window while retaining detailed events in the incident log. Given the monitoring job fails to execute for 2 consecutive scheduled runs When heartbeats are evaluated Then a "monitoring failure" alert is sent within 2 minutes.
Ingestion Pipeline Health Checks and Failure Alerts
Given the ingestion service performs upstream fetches per jurisdiction When an upstream request returns 5xx or times out and automatic retries (max_retries configured) are exhausted Then an ingestion_failure alert is sent within 60 seconds with jurisdiction_id, endpoint, error_type, attempt_count, and correlation_id, and the failure is reflected as "Degraded" unless lag also breaches SLA (then "Stale"). Given a jurisdiction’s ingestion succeeds When the health endpoint /observances/health is queried Then it returns HTTP 200 with overall_status and per_jurisdiction statuses (Healthy|Degraded|Stale|Outage) plus last_success_at and lag_minutes. Given there have been no successful ingestions for a jurisdiction for outage_threshold_minutes When health is queried Then the status for that jurisdiction is "Outage" and a critical page is sent.
Multi-Tier Caching with Jurisdiction-Specific TTLs
Given a jurisdiction has configured TTLs for in_memory_ttl and edge_ttl When a request for observance data is served and the in-memory cache entry is unexpired Then the response is served from in-memory and includes X-Data-Freshness-Seconds indicating age <= in_memory_ttl. Given the in-memory entry is missing or expired but the edge cache entry is unexpired When a request is served Then the response is served from edge and includes Cache-Tier: edge and X-Data-Freshness-Seconds <= edge_ttl. Given a cache entry has expired and upstream is reachable When a request is served Then the system serves the last value with stale-while-revalidate for up to swr_seconds (configurable) and refreshes asynchronously, ensuring X-Data-Freshness-Seconds <= edge_ttl + swr_seconds. Given upstream returns an error during refresh When serving requests Then stale-if-error applies for up to sie_minutes (configurable) before switching to last-known-good snapshot, and all such events are recorded with reason=stale_if_error.
Eventual Consistency and Last-Known-Good During Upstream Outage
Given an upstream outage is detected for a jurisdiction When serving observance data Then the system serves the last-known-good dataset for that jurisdiction for up to max_stale_hours (configurable) while marking state=Degraded and embedding X-Data-Source: LKG in responses. Given the upstream recovers When a successful ingestion completes Then caches are refreshed and all serving nodes converge to the latest version within 10 minutes, verified by X-Data-Version equality across nodes. Given differences are detected between LKG and latest after recovery When replay is completed Then changes are applied idempotently with no duplicate or missing records, verified by matching record_hash counts before and after. Given max_stale_hours is exceeded and upstream remains down When serving requests Then the system returns HTTP 503 for admin APIs and marks jurisdiction state=Outage while end-user proposals continue using LKG only if within max_stale_hours; beyond that, proposals exclude observance-dependent weighting for that jurisdiction and log a degraded-decision event.
Provenance, Versioning, Rollback, and Replay
Given an observance record is ingested Then it is stored with metadata: jurisdiction_id, provider_name, provider_event_id, fetched_at, valid_on/date_range, source_checksum, data_version, change_type (create|update|delete), and previous_version. Given an administrator issues a rollback for a jurisdiction to data_version N When the command is executed Then the datastore and caches are reverted to N within 2 minutes and subsequent reads return X-Data-Version: N. Given an administrator triggers a replay from checkpoint T When the job completes Then all records from T..now are reprocessed and the resulting dataset hash matches the expected replay hash recorded in the audit log. Given any create/update/delete Then an immutable audit log entry is written with actor (system|admin), timestamp, correlation_id, and diff_summary, and is retrievable via the admin dashboard.
Admin Status Dashboard and On-Call Paging Integration
Given an admin user with role=ObservanceAdmin When accessing the Observance Graph status dashboard Then they see per-jurisdiction cards with lag_minutes, last_success_at, current_status, upstream_state, cache_age_seconds, and active_incident_id, refreshed every 60 seconds. Given the dashboard is loaded When the admin filters by status=Stale or Outage Then only matching jurisdictions are displayed and the total_count updates accordingly. Given the admin clicks a jurisdiction When details open Then a 30-day freshness trend graph and last 100 ingestion events are displayed with timestamps and outcomes. Given the admin clicks "Send test page" When the action is confirmed Then an on-call page is sent and acknowledged by the paging provider API, and the dashboard shows the test event within 60 seconds.

Blackout Guardrails

Automatically flags and enforces hard blackouts on full‑closure days, skipping or pausing affected occurrences in a series. If a session can’t be avoided, it suggests humane alternatives (skip, async summary, or compensating rotation) so you prevent last‑minute cancels and resentment while keeping equity intact.

Requirements

Org Blackout Calendar Sync
"As an ops lead, I want TimeMeld to sync company and regional closure calendars so that meetings never get scheduled on full-closure days."
Description

Integrate TimeMeld with organization-wide holiday and full-closure calendars (Google Workspace, Microsoft 365, ICS feeds) to ingest hard blackout dates per region, country, team, and business unit. Support mapping participants to one or more regions/teams, partial-day closures, and custom company shutdowns. Refresh feed data at least daily with webhook/push support when available, de-duplicate across sources, and expose a unified, read-only "Hard Blackouts" layer in scheduling. Conflicts detected against this layer must be treated as non-bookable for autogenerated proposals and enforcement logic across one-off and recurring meetings.

Acceptance Criteria
Initial Connect and Ingest from GWS, M365, and ICS
Given an admin provides valid read-only credentials for Google Workspace holiday/full-closure calendars, When the connection is saved, Then TimeMeld ingests all events within the next 18 months and the previous 6 months within 10 minutes and records a last-sync timestamp. Given an admin provides valid read-only credentials for Microsoft 365 organization holiday calendars, When the connection is saved, Then TimeMeld ingests all events within the next 18 months and the previous 6 months within 10 minutes and records a last-sync timestamp. Given a public or authenticated ICS feed URL is added, When the feed is validated, Then TimeMeld ingests events respecting time zones and recurrence rules within 10 minutes and records a last-sync timestamp. Given a connection is invalid or permissions are insufficient, When a sync is attempted, Then TimeMeld surfaces an actionable error with provider details and no partial or stale blackout entries are created or updated.
Scheduled Refresh and Webhook/Pull Update Cadence
Given webhook/push is available for the provider, When a blackout event is created, updated, or deleted in the source, Then TimeMeld reflects the change in the Hard Blackouts layer within 5 minutes and updates the last-sync timestamp. Given webhook/push is not available, When 24 hours have elapsed since the last successful sync, Then TimeMeld performs an automatic refresh and applies all changes within 30 minutes. Given an admin triggers a manual refresh, When the refresh completes, Then the Hard Blackouts layer matches the source of truth within 5 minutes and the action is audit-logged with outcome (success/failure).
Participant to Region/Team Mapping Enforcement
Given a participant is mapped to one or more regions, countries, teams, or business units, When generating availability, Then blackout events matching any mapping are applied to that participant (logical OR). Given a participant has no explicit mapping, When generating availability, Then the organization default region/team mapping is applied. Given participants in a meeting belong to different mapped regions, When computing non-bookable windows, Then the union of all applicable blackouts across participants is enforced.
Partial-Day Closures Handling
Given a blackout event covers a partial day (e.g., 13:00–17:00 local time), When generating proposals across time zones, Then no proposed meeting start time overlaps any portion of the blackout window in the participant’s local time. Given a recurring partial-day blackout (e.g., every Friday 15:00–17:00), When enforcing for a recurring meeting series, Then affected occurrences are marked non-bookable and excluded from proposed times. Given a daylight saving time transition occurs, When mapping partial-day blackout windows, Then wall-clock times are preserved in each participant’s local time.
De-duplication and Merge Across Sources
Given the same holiday/closure exists in multiple connected sources, When ingested, Then the Hard Blackouts layer contains a single consolidated event with merged source references and a stable ID. Given overlapping blackout windows from different sources, When computing enforcement, Then the effective block is the strict union of time ranges without gaps. Given two events differ only by title/UID but share identical time bounds and region scope, When ingested, Then only one non-duplicated block is shown. Given source events are updated or removed, When a sync runs, Then the deduplicated representation is updated or deleted accordingly.
Unified Read-Only Hard Blackouts Layer in Scheduler
Given a scheduler view is opened for a meeting with mapped participants, When the Hard Blackouts layer is toggled on (default), Then users see non-editable blackout blocks with tooltips showing name, local time, region/team scope, and source(s). Given a user attempts to edit or drag a blackout block, When the action is performed, Then the UI prevents the change and displays a read-only notice. Given the scheduling API is queried for layers, When requesting context, Then the Hard Blackouts layer is included as read-only with event IDs, time bounds, and source provenance.
Non-Bookable Enforcement for One-Off and Recurring Meetings
Given a proposed time overlaps any participant’s applicable blackout, When generating suggestions, Then TimeMeld excludes that time from autogenerated proposals. Given a user attempts to manually book a time overlapping a blackout, When saving, Then the system blocks the save with a clear error and offers the nearest conflict-free windows. Given a recurring series intersects a blackout on specific occurrences, When finalizing the series, Then those occurrences are automatically excluded from booking and no invites are created for blocked dates.
Series Conflict Auto-Skip
"As a meeting organizer, I want recurring sessions that hit blackouts to be auto-skipped or paused so that we avoid last-minute cancellations and confusion."
Description

Detect when any occurrence in a recurring series intersects a hard blackout for one or more required participants. Automatically skip the conflicting occurrence or pause the series if the blackout spans multiple contiguous instances, without deleting the series or losing metadata (agenda, attendees, equity rotation). Apply standardized event updates: cancel the single instance with reason code "Hard Blackout" and leave a note in the series. Preserve ownership state for compensation and allow one-click conversion to an alternative path (async summary or reschedule) from the notification.

Acceptance Criteria
Single Occurrence Conflict: Auto-Skip with Reason Code
Given a recurring series with at least one required participant whose hard blackout overlaps a single upcoming occurrence When the conflict detection job runs Then the conflicting occurrence is canceled (not deleted) and removed from participant calendars And the cancellation includes reason code "Hard Blackout" following the standardized event update format And a note is appended to the series master referencing the skipped date/time and affected required participants And the series metadata (agenda, attendees list, equity rotation state, series/instance IDs) remains unchanged And no auto-skip is performed if only optional participants are affected by a blackout
Contiguous Conflicts: Auto-Pause Series and Resume
Given two or more consecutive upcoming occurrences each overlap a hard blackout for any required participant When the conflict detection job runs Then the series is marked Paused covering the contiguous conflict window And individual occurrences within the paused window are not created or sent as separate cancellations And a single series-level note is appended indicating the paused date range with reason "Hard Blackout" And participants receive one pause notification indicating the affected range And the series automatically resumes on the first occurrence after the blackout range, preserving cadence and identifiers
Ownership Preservation and Compensation Flagging
Given an occurrence is auto-skipped or the series is auto-paused due to a hard blackout and an owner-of-record exists per equity rotation When the skip/pause is applied Then the owner-of-record is preserved and flagged as "to-be-compensated" for that occurrence And the rotation pointer does not advance due to the skipped/paused occurrence And the equity scoreboard reflects a "Skipped - Hard Blackout" entry for the affected occurrence and displays the compensation marker And the next schedulable occurrence offers to allocate ownership to the flagged owner or apply the team’s compensation policy automatically
Notification with One-Click Alternative Paths
Given an occurrence is auto-skipped or a series is auto-paused due to a hard blackout When notifications are sent to the series organizer and required participants Then the notification contains one-click actions: "Convert to async summary", "Reschedule", and "Record compensation" And selecting "Convert to async summary" creates an async task populated with the original agenda, assigns the owner-of-record, and sets a default due date within 48 hours And selecting "Reschedule" opens suggested windows that exclude all hard blackout windows for required participants and preserve rotation equity And selecting any action writes an audit entry in the series note including action, actor, and timestamp
Timezone-Accurate Conflict Detection
Given a recurring series with required participants across multiple time zones, including during daylight saving transitions When evaluating each upcoming occurrence against participants’ hard blackout windows Then the system checks overlap using each required participant’s local time zone (including all-day blackouts) and treats any overlap greater than 0 minutes as a conflict And DST transition weeks are correctly handled so that occurrences that shift hour do not bypass blackout enforcement And optional participants’ blackouts do not contribute to conflict determination
Idempotency and External Calendar Consistency
Given the conflict detection job is retried or executed concurrently for the same series occurrence When processing the conflicting occurrence Then only one cancellation is created and only one series note is appended, de-duplicated by seriesId and occurrenceId And only one notification is sent per impacted audience And external calendars reflect the instance as canceled with reason code "Hard Blackout" while the series master remains intact (agenda, attendees, and rotation state preserved)
Humane Alternative Suggestions
"As a product manager, I want humane alternatives suggested when a blackout occurs so that we can maintain momentum without burdening teammates."
Description

When a hard blackout blocks a session that is designated as required, generate humane alternatives: (1) skip this occurrence, (2) async summary workflow with templated agenda capture and decision log, (3) compensating rotation so the skipped owner is credited for the next available session, or (4) reschedule to the nearest timezone-weighted ergonomic windows within policy bounds. Present option cards with impact scores (participant coverage, circadian ergonomics, equity delta) and apply the chosen action in one click, updating calendars and the equity ledger accordingly.

Acceptance Criteria
Required Session Blocked by Hard Blackout
Given a recurring session occurrence is marked "Required" and its date overlaps a configured Hard Blackout When the occurrence is opened or schedule generation runs Then TimeMeld displays a "Humane Alternatives" panel within 2 seconds And the original blocked time is labeled "Blocked by Blackout" and disabled for booking And exactly four options are shown: "Skip Occurrence", "Async Summary", "Compensating Rotation", "Reschedule Within Policy"
Option Cards Show Impact Scores
Given the Humane Alternatives panel is displayed When option cards render Then each card displays the following impact scores: Participant Coverage (percentage), Circadian Ergonomics (0-100), Equity Delta (numeric) And no impact score is null or hidden And impact scores are calculated using the same participants and policy context as the series
One-Click Apply and Atomic Updates
Given any option card is selected When the user clicks "Apply" once Then the system performs all related calendar and equity ledger updates atomically (all succeed or all are rolled back) And a success confirmation appears within 5 seconds And an audit log entry is recorded including actor, option chosen, series ID, occurrence date, and resulting equity change And all affected participants receive a single consolidated notification
Reschedule to Nearest Ergonomic Windows Within Policy
Given "Reschedule Within Policy" is selected When candidate windows are generated Then up to 3 nearest candidate windows are presented, sorted by ergonomic score (descending) And each candidate obeys policy bounds: meeting duration, minimum notice, participant working hours, blackout rules, and maximum allowed series drift And each candidate shows local times for all required participants and the projected participant coverage percentage When a candidate is chosen and Apply is clicked Then the blocked occurrence is canceled and a new invite is created at the selected window And the equity ledger remains unchanged
Async Summary Workflow With Templates and Credit
Given "Async Summary" is selected Then an async workspace is created with fields: Agenda (required), Discussion Notes, Decisions (required), Action Items (required), Owner (pre-filled), Due By (default: next business day 17:00 in owner timezone or before next scheduled occurrence, whichever is sooner) And the blocked occurrence is canceled with an "Async Summary" reason And notifications with the workspace link are sent to all required participants immediately When the owner submits the Decisions field before Due By Then the equity ledger credits the owner for one session and the series rotation remains unchanged If the Decisions field is not submitted by Due By Then no credit is applied
Compensating Rotation Assignment and Equity Update
Given "Compensating Rotation" is selected Then the equity ledger immediately credits the current owner for the skipped occurrence And the next non-blackout occurrence in the series is assigned to the same owner And existing invites for that future occurrence update ownership metadata within 1 minute And no duplicate credit is applied if the series ownership is manually edited later And if the immediate next occurrence is blacked out, the assignment rolls forward to the next feasible occurrence
Skip Occurrence Without Credit
Given "Skip Occurrence" is selected Then the blocked occurrence is canceled with reason "Hard Blackout - Skipped" and all required participants are notified And the equity ledger records the occurrence as skipped with zero credit And the series rotation proceeds to the next owner per current schedule with no reassignment
Equity Scoreboard Compensation
"As a team member, I want the equity scoreboard to compensate for blackout skips so that ownership remains fair over time."
Description

Adjust the equity scoreboard to account for blackout-driven skips without penalizing the assigned owner. Record a compensation credit that advances the owner to the next meeting requiring ownership, ensure rotation continuity, and update fairness metrics (e.g., inconvenient-time count, ownership frequency) to reflect the skipped occurrence. Surface a clear rationale and audit trail on the scoreboard and in the series history so that teams understand why ownership changed.

Acceptance Criteria
Compensation Credit Recorded on Blackout Skip
Given a recurring series occurrence with an assigned owner that falls on a configured blackout date And Blackout Guardrails mark the occurrence as skipped When the system finalizes the skip Then the assigned owner receives exactly one compensation credit referencing the occurrence_id and series_id with reason="blackout" And the owner's ownership count does not increment for that occurrence And the owner's inconvenient_time_count does not increment for that occurrence And the rotation pointer advances past the skipped occurrence without reassigning ownership for that date
Credit Application at Next Eligible Occurrence
Given an owner has at least one compensation credit for a series And a future occurrence in the series requires ownership assignment When the schedule is generated for that occurrence Then that owner is assigned as the owner before applying standard rotation And exactly one compensation credit is decremented and linked to that occurrence And the post-occurrence rotation order matches the order that would have applied had the skipped occurrence not existed (rotation continuity preserved)
Fairness Metrics Adjusted for Skipped Occurrence
Given a series occurrence is skipped due to a blackout with an assigned owner X When fairness metrics are recalculated for the series Then X's ownership_frequency does not increase for the skipped occurrence And X's inconvenient_time_count does not increase for the skipped occurrence And the series total_owned_count equals the number of non-skipped occurrences And the metrics treat the skipped occurrence as excluded rather than owned
Audit Trail and Rationale Visibility
Given a blackout-driven skip results in an ownership change When a user with view permissions opens the Equity Scoreboard for the series Then the affected date range shows a visible note "Ownership reassigned due to blackout" with the credited owner and a link to series history And the series history contains an entry with occurrence_id, series_id, prior_owner, credited_owner, action="skip", reason="blackout", actor="system", timestamp, and credit_applied status And both the scoreboard note and history entry are visible within two clicks from the series overview
Multiple Credits and Consecutive Blackout Handling
Given two or more consecutive occurrences in a series are skipped due to blackouts And each skipped occurrence had a designated owner When the skips are finalized Then each designated owner receives exactly one compensation credit per skipped occurrence, stored in chronological (FIFO) order per owner And at most one credit is applied per eligible future occurrence per owner And when the next N eligible occurrences are scheduled (where N equals the number of created credits), the owners are assigned in the same chronological order as the skipped occurrences And rotation continuity for non-credited teammates is preserved
Reversal on Reschedule Within Allowed Window
Given an occurrence was marked skipped due to blackout and a compensation credit was recorded And the occurrence is later rescheduled within the series' allowed working window before the occurrence window expires When the reschedule is confirmed Then the skip status is reversed and the occurrence is reinstated And the previously recorded compensation credit is voided (status="void") and not applicable to future occurrences And fairness metrics are recalculated to reflect the reinstated occurrence And an audit trail entry records the reversal with occurrence_id, action="reversal", reason="reschedule", actor, and timestamp
Admin Overrides & Enforcement
"As an admin, I want to enforce hard blackouts with controlled overrides so that policy is respected while allowing exceptions when justified."
Description

Provide policy controls for hard vs. soft blackouts at the workspace and team levels. Enforce hard blackouts by blocking automated scheduling and manual propose/send actions that violate policy, with clear error messaging. Allow time-bounded, role-gated overrides that require a justification note, capture consent from impacted participants if configured, and log all exceptions in an immutable audit trail. Offer API/SCIM endpoints to manage blackout policies and team mappings programmatically.

Acceptance Criteria
Workspace vs Team Blackout Policy Scope & Precedence
- Rule: System supports creation of hard and soft blackout policies at both workspace and team levels. - Rule: Effective policy resolution enforces any applicable hard blackout; team-level policies may add stricter constraints but cannot downgrade a workspace-level hard blackout to soft. - Rule: Effective policy view for any team displays the merged result, listing source (workspace/team), type (hard/soft), and precedence used. - Rule: Policies support timezone anchoring and recurrence (single date, date range, weekly recurrence); effective windows compute correctly across participant timezones. - Rule: Validation prevents malformed or paradoxical policies; overlapping policies resolve per precedence without runtime errors. - Rule: Permissions restrict policy CRUD to Workspace Admins (workspace scope) and Team Admins (their teams only); unauthorized attempts return 403 with reason. - Rule: Creating, updating, or deleting a policy writes an audit record with actor, timestamp, policy diff, and scope.
Automated Scheduling Enforcement for Hard Blackouts
- Given the automated scheduler evaluates times for a session series When a candidate time overlaps any effective hard blackout for the session's team or workspace Then the system does not place holds, send invites, or create proposals for that occurrence and returns status "blocked_by_blackout" including policy IDs. - Given an occurrence is blocked by a hard blackout When alternatives are computed Then the system suggests humane alternatives (skip this occurrence, async summary, compensating rotation) and records the decision. - Given a hard blackout blocks scheduling When the UI surfaces the block Then an inline message shows policy name, type, effective window, and a link to policy details; message is localized and accessible (meets WCAG AA).
Manual Propose/Send Enforcement for Hard Blackouts
- Given a user attempts to propose or send a time that overlaps an effective hard blackout When they click Propose or Send Then submission is blocked, no invitations are dispatched, and an inline error appears with policy name, type, effective window, and link to details. - Given a manual action is blocked by a hard blackout When the user views options Then the UI provides actions: Skip occurrence, Request override (if enabled), or Switch to async; selecting any action is logged. - Given a soft blackout applies (not hard) When the user attempts to propose or send Then the system allows the action but shows a prominent warning and requires an explicit confirm before proceeding; the warning includes policy reference.
Role-Gated, Time-Bounded Overrides
- Given override capability is enabled When a user without override privileges attempts to create an override Then the system creates a request in Pending state and notifies designated approvers; scheduling remains blocked until approval. - Given a user with an allowed override role (e.g., Workspace Admin, Policy Override Approver) When they create an override Then they must provide justification text, a start and end timestamp (finite duration), and the target scope (event occurrence, series, team); missing any field returns validation errors. - Given an override is approved and active for the specified window and scope When scheduling runs for previously blocked occurrences within that window Then the system permits scheduling and tags all resulting artifacts with the override ID. - Given an override reaches its end timestamp or is revoked by an authorized role When further scheduling attempts occur Then enforcement reverts to normal blackout rules; no backdated scheduling occurs. - Rule: Overrides cannot be created without an end time or for an indefinite duration; requests violating this are rejected.
Participant Consent Capture on Overrides (Configurable)
- Given workspace consent is configured as Required with mode Unanimous When an override is initiated for an occurrence impacting N participants Then the system requests consent from all impacted participants and only activates the override after all have explicitly accepted before the response deadline. - Given workspace consent is configured as Required with mode Quorum (percentage or count) When an override is initiated Then the system activates the override once the configured threshold is met and cancels it if the deadline passes without reaching the threshold. - Given any participant declines or the deadline expires without meeting the configured requirement When the override state is evaluated Then the override is marked Failed and hard blackout enforcement remains in effect. - Rule: All consent responses (accept/decline/timed out) are recorded with actor, timestamp, and channel; the consent requirement used is stored in the audit trail.
Immutable Audit Trail for Exceptions and Policy Changes
- Given any policy CRUD action or override lifecycle event (requested, approved, activated, failed, revoked) When the event occurs Then an immutable audit record is appended capturing actor, action, timestamp (UTC), scope (workspace/team), policy/override IDs, justification, impacted participants, consent summary, and outcome. - Rule: Audit records are append-only; attempts to edit or delete return 403 and do not alter stored data. - Rule: Audit logs are queryable by time range, actor, team, policy/override ID, and outcome, and are exportable as CSV and JSON via API; results are paginated and consistent. - Rule: Each record includes a tamper-evident checksum of its contents; checksum verification endpoint returns Pass/Fail for a supplied record ID.
Programmatic Management via API/SCIM
- Given a client possesses an OAuth2 token with scope blackout:manage When it calls REST endpoints to create, update, list, and delete blackout policies and to map teams to policies Then the API enforces authentication/authorization, validates payloads, applies precedence rules, and returns appropriate HTTP statuses (201/200/400/401/403/404/409) with error codes. - Rule: Create/Update endpoints support idempotency via Idempotency-Key; repeated requests with the same key do not create duplicates and return the original result. - Rule: GET list endpoints filter by scope (workspace/team), type (hard/soft), date range, and support pagination and sorting; responses include effective policy previews when requested. - Rule: SCIM endpoints support provisioning/deprovisioning of team mappings to blackout policies via SCIM 2.0 (RFC 7644) semantics with PATCH operations; invalid references return 404. - Rule: All API mutations create audit records; rate limits are enforced and communicated via standard headers.
Proactive Notifications & Updates
"As an attendee, I want proactive notifications and updated calendar events when a session is skipped due to a blackout so that I’m not surprised and my schedule stays accurate."
Description

Send proactive alerts when upcoming occurrences are affected by hard blackouts (e.g., 7 days and 24 hours prior), via Slack, Microsoft Teams, and email. Include localized times, a summary of who is impacted, and actionable buttons for skip, async summary, compensating rotation, or reschedule. Upon action, automatically update or cancel calendar events with standardized notes and notify all attendees, ensuring accessibility (plain text alternatives) and i18n where configured.

Acceptance Criteria
Time-based Proactive Alerts for Blackout-Affected Occurrences
Given a scheduled session occurrence that falls on a hard blackout date And organization-level notifications via Slack, Microsoft Teams, and email are configured When the system time reaches 7 days before the occurrence start in the session’s canonical timezone Then a blackout alert is sent via Slack, Microsoft Teams, and email to all required attendees and meeting owners within 5 minutes Given the same occurrence remains unresolved (no skip/async/rotation/reschedule recorded) When the system time reaches 24 hours before the occurrence start Then a reminder alert is sent via Slack, Microsoft Teams, and email within 5 minutes And no duplicate alerts are sent for the same window if a previous send succeeded (idempotent by occurrence ID and window) Given a recipient lacks Slack or Microsoft Teams authorization When an alert is issued Then email is sent as the fallback channel and recorded as such in delivery logs Given any channel send fails transiently When the system retries up to 3 times with exponential backoff Then final delivery status is recorded per recipient per channel
Notification Content: Localized Times, Impact Summary, and Actions
Given a recipient with a known locale and timezone receives a blackout alert When the message is rendered Then it includes the meeting title, the reason “Hard blackout,” and the blackout source (holiday/closure name) And displays the occurrence start time in the recipient’s local timezone and locale format And displays the source (canonical) timezone and time for reference And lists impacted attendees with their names and timezones (unique list) And presents clearly labeled actions: “Skip occurrence,” “Async summary,” “Compensating rotation,” and “Propose reschedule” Given the recipient’s client does not support interactive buttons (e.g., plaintext email) When the alert is rendered Then accessible plaintext alternatives with unique action links are included for each action Given the organization or recipient has a preferred language configured When the alert is generated Then all static strings and date/time formats are localized accordingly And all action destinations are accessible behind authenticated links
Skip Occurrence Flow
Given a user with manage permissions selects “Skip occurrence” from the blackout alert When the action is confirmed Then only the targeted occurrence is cancelled in all connected calendars within 60 seconds And the event instance title is prefixed with “[Canceled]” (where supported) and includes the standardized note “Skipped due to hard blackout: <blackout_name>” in the description And cancellation notifications are sent to all attendees via Slack, Microsoft Teams, and email with localized times And the series pattern remains unchanged for future occurrences And an audit log entry is recorded with actor, timestamp, occurrence ID, and channels notified
Async Summary Flow
Given a user with manage permissions selects “Async summary” from the blackout alert When the action is confirmed Then the occurrence remains on the calendar but is converted to an async format within 60 seconds And the title is prefixed with “[Async]” (where supported) And the description is updated with a standardized async template including: purpose, owners, due-by date/time (localized), and a link to the async document And a notification is sent to all attendees via Slack, Microsoft Teams, and email with instructions and the async link And an audit log entry is recorded with actor, timestamp, occurrence ID, and async link
Compensating Rotation Flow
Given a user with manage permissions selects “Compensating rotation” from the blackout alert When the action is confirmed Then the current occurrence is cancelled within 60 seconds with the standardized note “Canceled due to hard blackout — compensating rotation applied” And the equity scoreboard credits ownership to the originally scheduled owner for this occurrence (no penalty) And the next occurrence’s ownership is advanced according to rotation policy And notifications are sent to all attendees and the next owner via Slack, Microsoft Teams, and email detailing the rotation change And an audit log entry records rotation adjustments with before/after owners and timestamps
Propose Reschedule Flow
Given a user with manage permissions selects “Propose reschedule” from the blackout alert When the reschedule flow is opened Then TimeMeld proposes at least 3 timezone-weighted candidate windows that exclude blackout days and participant hard blackouts And when the user confirms a candidate window Then the single occurrence is updated to the new time in all connected calendars within 60 seconds And the event retains conferencing details (where supported) and adds a standardized note “Rescheduled due to hard blackout from <old_datetime> to <new_datetime>” And update notifications are sent to all attendees via Slack, Microsoft Teams, and email with localized new times And an audit log entry captures the reschedule with old/new timestamps and actor
Blackout Impact Analytics
"As a department head, I want analytics on blackout impacts so that I can quantify time saved and refine scheduling policies."
Description

Provide a dashboard and export that quantify blackout effects: meetings auto-skipped/paused, hours avoided, attendance and no-show deltas, equity shifts, and frequency by team/region/timeframe. Enable filters, drill-down to series history, and CSV export for quarterly reviews. Surface KPIs that validate the guardrails’ value and inform policy tuning (e.g., closure coverage gaps, override rates).

Acceptance Criteria
KPI overview renders and computes blackout impact KPIs
Given a user with Analytics access and data in the last 90 days When they open Analytics > Blackout Impact Then KPI cards display: Auto-skipped meetings, Auto-paused meetings, Hours avoided (hrs), Attendance delta (pp), No-show delta (pp), Override rate (%), Coverage gap hours (hrs) And default timeframe is Last 90 Days and default baseline is Previous 90 Days And values equal authoritative aggregates for the current filter set using definitions: - Auto-skipped meetings = count(outcome = auto_skipped_due_to_blackout) - Auto-paused meetings = count(outcome = auto_paused_due_to_blackout) - Hours avoided = sum(duration_minutes where outcome in {auto_skipped_due_to_blackout, auto_paused_due_to_blackout}) / 60 rounded to 2 decimals - Attendance delta = (current avg attendance%) − (baseline avg attendance%) shown with sign and 1 decimal - No-show delta = (current no-show%) − (baseline no-show%) shown with sign and 1 decimal - Override rate = count(outcome = forced_override) / count(affected_occurrences) as percent with 1 decimal - Coverage gap hours = sum(duration_minutes where outcome = forced_override) / 60 rounded to 2 decimals And each KPI has a tooltip showing its formula and data window
Filters apply consistently across KPIs, charts, and tables
Given a dataset with multiple teams, regions, meeting types, and blackout types When the user applies any combination of filters (time range, team(s), region(s), blackout type(s), meeting type(s)) Then all KPI cards, charts, and tables reflect only records matching the filters And a filter pill bar shows the active filters And clearing filters returns the view to defaults And for up to 50,000 affected occurrences, P95 update latency after changing filters is ≤ 1.0s And displayed totals equal the backend API response for the same filters
Drill-down from aggregates to series history and occurrence details
Given an aggregate KPI card, chart segment, or table row When the user selects View details or clicks a data point Then the app opens a Series History view scoped to the same filters and context And the view lists occurrences with columns: datetime_local (ISO 8601), local_tz, outcome, reason, duration_minutes, series_name, owner, attendance_percent, no_show_flag, equity_impact_hours, override_flag And a timeline visualization annotates blackout-triggered events And the totals in the Series History view equal the aggregates from the originating view And selecting a series opens a details panel with all occurrences and rotation/equity changes for that series
CSV export reflects current view and data definitions
Given any current filter and sort state in Blackout Impact Analytics When the user clicks Export CSV Then a CSV file downloads within 10 seconds for up to 100,000 rows And the CSV includes a header row with columns: datetime_utc, local_tz, team, region, meeting_type, series_id, series_name, occurrence_id, outcome, reason, duration_minutes, attendance_percent, no_show_flag, equity_impact_hours, override_flag And the rows, totals, and ordering match the on-screen table under the same filters and sort And datetime_utc is in ISO 8601 with Z, numeric fields use dot decimal, text is UTF-8 encoded, commas/quotes are RFC 4180 escaped, line endings are LF And Hours avoided and Coverage gap hours computed from the CSV reproduce the on-screen KPI values within rounding tolerance
Baseline selection controls attendance and no-show deltas
Given the baseline selector with options: Previous period (default), Same period last year, Custom range, Pre-guardrails When the user changes the baseline option or defines a custom range Then Attendance delta and No-show delta recompute using the selected baseline And tooltips for these KPIs display the selected baseline and formula And if the baseline window has insufficient data (< 30 occurrences), the KPIs show N/A with an info tooltip And sparkline and percent/pp values update consistently across cards and charts
Equity shift metrics and participant-level drilldown
Given equity scoreboard data and guardrail events in the selected window When the user views the Equity section Then the dashboard shows: Mean equity score delta, Median equity score delta, Net hours rebalanced, Count of compensating rotations And a participant drilldown lists user_id, name (masked if policy enabled), equity_score_before, equity_score_after, equity_score_delta, rebalanced_hours And calculations follow definitions: equity_score_delta = current − baseline; net hours rebalanced = sum(hours moved from participants with inconvenience_score ≥ 0.7) within the filter window And the sum of participant rebalanced_hours equals the Net hours rebalanced KPI within rounding tolerance
Access control, privacy, and freshness/performance guarantees
Given a user without Analytics permission When they attempt to access Blackout Impact Analytics Then they receive a 403 error view with no data leakage Given a permitted user When they load the dashboard with up to 10,000 affected occurrences Then P95 initial load time is ≤ 2.0s and P99 ≤ 3.0s And a Last updated timestamp is visible and matches the backend snapshot (difference ≤ 60s) And when tenant policy Mask PII is ON, meeting titles and participant names are masked by default; unmask control is visible only to roles with Unmask permission And KPI values and aggregates are identical regardless of masking state

Stagger Builder

One‑click creation of staggered session sets around holiday clusters. It generates region‑friendly options (e.g., AMER/EMEA this week, APAC/EMEA next), preserves facilitator rotation, and localizes reminders—maintaining momentum and coverage without overburdening any timezone.

Requirements

Holiday Cluster Detection
"As a program manager scheduling across regions, I want the system to detect regional holiday clusters so that I can avoid planning sessions when teams are offline."
Description

Detect and annotate regional holiday clusters across participant locales to inform staggered scheduling. Ingest official public holidays (via providers) and custom organization calendars, map users to regions, and compute blackout windows (e.g., 2+ holidays within a rolling window). Surface cluster metadata to Stagger Builder so generated sessions avoid or compensate for impacted periods. Refresh data daily, cache results for performance, allow admin overrides, and handle DST and locale-specific observances. Output normalized holiday windows per region with confidence flags and reasons for transparency.

Acceptance Criteria
Official Cluster Detection and Blackout Window Computation
Given a region with >=2 provider-sourced public holidays within a configurable rolling window (default 7 days) When detection runs Then a blackout window is created spanning 00:00 local time of the first holiday through 23:59 local time of the last holiday Given overlapping holiday clusters in the same region When detection runs Then overlapping windows are merged into a single blackout window and holiday_count is the count of distinct holidays in the merged window Given a detected cluster When metadata is produced Then it includes region_id, window_start_local, window_end_local, holiday_count, window_days, holiday_names, source_types=["provider"], confidence="high", and reasons including ">=2 official holidays within 7d"
Merge Provider and Custom Organization Holidays
Given custom organization holidays tagged with region codes When merged with provider data Then duplicates are de-duplicated by normalized name+local date+region and holiday_count reflects unique holidays Given only custom holidays form a cluster When detection runs Then a blackout window is created with source_types including "org" and confidence="medium" Given both provider and custom holidays contribute to the same cluster When detection runs Then the blackout window confidence="high" and reasons list both sources (e.g., "provider+org")
Region Mapping and Participant Impact Annotation
Given users mapped to regions and timezones When a cluster is detected for a region Then impacted_user_count and impacted_user_ids for that region are included in the cluster metadata Given a user has a locale-specific override timezone When impact is computed Then local date boundaries use the region timezone for clustering and the override timezone is used only for reminder localization Given a region has no mapped users When clusters are computed Then impacted_user_count=0 and the window is still output for planning
Daily Refresh Schedule and Cache Invalidation
Given a daily refresh schedule at a configurable time When the scheduler runs Then holiday data is re-ingested and clusters recomputed at least once every 24 hours Given cached results exist When source data changes Then caches for affected regions are invalidated within 15 minutes and subsequent API reads return updated clusters Given a cache hit When the API is called Then P95 response time for /holiday-clusters is <=300ms for up to 50 regions and payload size per region is <=10KB
Admin Overrides for Cluster Windows
Given an admin with override permissions When the admin suppresses a detected cluster for a region and date range Then the cluster is excluded from API responses and a reason "admin_override_suppress" is recorded Given an admin adjusts a window’s start/end When detection runs Then the adjusted window takes precedence over computed windows and confidence="override" Given an override expires When its end date passes Then baseline computed clusters automatically resume without manual action and an audit log entry is retained
DST and Locale-Specific Observance Handling
Given a cluster spans a DST transition in the region When window boundaries are computed Then the blackout window covers the correct local calendar days without off-by-one errors Given a holiday observed on a different weekday than its fixed date When detection runs Then the observed date is used for clustering for that locale Given a region uses a non-Gregorian calendar for public holidays via provider When data is ingested Then dates are normalized to ISO-8601 with region-local timezone and included in clustering
Normalized Cluster Metadata API for Stagger Builder
Given Stagger Builder requests /v1/holiday-clusters with regions and planning_horizon parameters When the request is valid Then the response status=200 and includes an array of clusters with fields: region_id, window_start_local, window_end_local, holiday_count, holiday_names, source_types, confidence, reasons, impacted_user_count, computed_at Given the planning_horizon is 0–90 days When the API responds Then only clusters whose windows intersect the horizon are returned Given an invalid region code or missing auth When the API is called Then status=400/401 with an error code and no cluster data is returned
Stagger Plan Generator
"As a global meeting organizer, I want one-click generation of staggered, region-friendly session sets so that we maintain momentum without overburdening any timezone."
Description

Generate multi-week, staggered session sets with one click, alternating region coverage (e.g., AMER/EMEA this week, APAC/EMEA next) while honoring ergonomic time windows. Use TimeMeld’s timezone-weighted scoring to prefer humane hours per region, prevent repeated inconvenient slots, respect working-hours preferences, and incorporate holiday cluster blackouts. Accept parameters (timeframe, cadence, session length, region pairings, participant sets) and produce ranked candidate plans with composite scores (ergonomics, fairness, coverage). Provide deterministic outputs with a seed for reproducibility and guidance on trade-offs (e.g., a plan rationale).

Acceptance Criteria
One‑Click Generation with Parameter Validation
Given a timeframe (either start/end dates or a week_count), a cadence, a session_length, region_pairings, and participant_sets mapped to regions When the user initiates one‑click Generate Stagger Plan Then the system validates required parameters and mutual exclusivity (start/end vs. week_count), non‑empty region_pairings, positive session_length, and that all participants belong to a declared region And on success, the system generates a candidate plan set without further user input and echoes all resolved inputs in the output And on validation failure, the system returns a clear error per invalid field naming the field and violated rule
Alternating Region Coverage by Cadence
Given region_pairings = [AMER/EMEA, APAC/EMEA] and a 6‑week timeframe When a plan set is generated Then assigned pairings alternate in the listed order across scheduled weeks (wk1 AMER/EMEA, wk2 APAC/EMEA, wk3 AMER/EMEA, ...) And no two consecutive scheduled weeks use the same pairing And if a week is skipped due to constraints (e.g., blackouts), alternation continues on the next scheduled week maintaining the original sequence order
Ergonomics/Fairness/Coverage Scoring and Ranking
Given candidate plans are produced When scores are computed Then each plan includes ergonomics_score, fairness_score, coverage_score, and composite_score, each in the range 0–100 with two‑decimal precision And composite_score equals the weighted sum of the component scores as documented in the output metadata within ±0.01 And candidate plans are sorted strictly by composite_score descending And ties are resolved deterministically using the provided seed
Working‑Hours Compliance and Inconvenient Slot Limits
Given each participant has declared working‑hours preferences in local time When sessions are scheduled for each week’s region pairing Then all sessions occur within the overlapping preferred working hours of the participating regions whenever feasible And if any attendee must be scheduled outside their preference to satisfy coverage, the session is marked “inconvenient” for those attendees And no participant accumulates more than 1 inconvenient session within the timeframe And any inconvenient session is explicitly listed in the plan rationale with affected attendees and reasons
Holiday Cluster Blackouts and Week Skipping
Given holiday cluster blackouts are defined per region When generating schedules for a region pairing Then no session is placed on a date blacked out for either region in the pairing And if all feasible days in a scheduled week are blacked out for the pairing, that week is skipped and the alternation pattern is preserved across the remaining scheduled weeks And the plan rationale itemizes each skipped week with regions, blackout dates, and resulting session count changes
Deterministic Output with Seed Reproducibility
Given identical inputs and a fixed seed value When the plan generation is executed multiple times Then the set of candidate plans, their ordering, scheduled times, and all scores are identical across runs And given a different seed with identical inputs, the produced plans may differ only where multiple options are equally valid under constraints, while still satisfying all acceptance criteria And the output echoes the seed used for traceability
Plan Rationale and Trade‑off Guidance for Top Candidates
Given a ranked list of candidate plans is produced When presenting the top 3 candidates Then each includes a human‑readable rationale summarizing: weekly region coverage sequence, per‑region counts of within‑preference vs. inconvenient sessions, blackout impacts (skipped weeks/dates), fairness distribution summary (max/min inconvenient sessions per participant), and key factors affecting ergonomics/fairness/coverage scores And each rationale calls out explicit trade‑offs (e.g., improved coverage vs. increased inconvenience) in bullet points And rationale content is consistent with the underlying schedule data and scores
Facilitator Rotation Preservation
"As a facilitator coordinator, I want the stagger plan to preserve and update rotation fairness so that ownership is distributed equitably across the team."
Description

Preserve and advance facilitator rotation equity when building staggered plans. Integrate with TimeMeld’s shared equity scoreboard to assign facilitators per session consistent with rotation order and timezone comfort. Adjust weights based on inconvenience scores, handle OOO and conflicts with alternates, and record every assignment decision. Update the scoreboard after publishing to reflect credit/debit for inconvenient time slots. Support manual overrides with validation and an audit trail to ensure fairness over time.

Acceptance Criteria
Auto-Assignment Honors Rotation and Timezone Comfort
Given a workspace with a configured rotation order and comfort thresholds and a generated staggered session set across regions When the Stagger Builder auto-assigns facilitators Then each session is assigned to the next facilitator in rotation who meets the workspace comfort threshold for that session’s local time And the rotation pointer advances by one for each session assigned And no session is assigned with an inconvenience score above the workspace maximum And the assignment record includes the rotation index used and the comfort/inconvenience scores considered
Inconvenience Weighting Influences Selection
Given multiple eligible facilitators for a session with calculated inconvenience scores When the difference between the next-in-rotation candidate’s score and a later candidate’s score exceeds the configured skip tolerance Then the later candidate is assigned instead of the next-in-rotation candidate And the skip reason and score delta are recorded in the audit log And the rotation pointer aligns to the assigned facilitator’s rotation position
OOO and Calendar Conflict Alternate Selection
Given the next-in-rotation facilitator is marked OOO or has a hard calendar conflict at the proposed time When auto-assigning facilitators Then the system selects the next available alternate in rotation order who meets the comfort threshold And if no alternates meet the criteria, the session is flagged "Needs Facilitator" with a conflict reason And all evaluated candidates with conflict and comfort statuses are recorded in the audit log
Comprehensive Audit Trail for Assignment Decisions
Given any facilitator assignment, re-assignment, skip, or override When the action occurs Then the system writes an immutable audit entry containing session ID, action type, actor (system/user), timestamp, considered candidates with scores and conflict flags, selected facilitator, rotation indices before/after, and reason code And the audit entry is retrievable via UI and API And non-admin users cannot edit or delete audit entries
Scoreboard Updates on Publish Reflect Equity Debits/Credits
Given a draft staggered plan with facilitator assignments and inconvenience scores per session When the plan is published Then the equity scoreboard applies the configured credit/debit weights per assignment based on inconvenience And the rotation order is updated to start after the last assigned facilitator in the plan And one audit entry per assignment is recorded with equity values before/after and credit/debit applied And the scoreboard update is atomic—either all changes succeed and are visible or none are applied and an error is shown with no partial updates
Manual Override with Validation and Guardrails
Given a user with permission attempts to change a facilitator assignment before publish When a new facilitator is selected Then the system validates comfort thresholds and hard conflicts for the selected facilitator And if validation fails, the user must provide an override reason and have required permissions to proceed And the UI displays the projected equity impact prior to confirmation And upon confirmation, the override is logged in the audit trail and the draft assignment updates without applying credits/debits until publish
Anti-Repeat Inconvenience Within Rolling Window
Given a workspace-defined rolling window and an inconvenience threshold When assigning facilitators across the staggered plan Then no facilitator is assigned more than one session above the inconvenience threshold within the rolling window unless a manual override with reason is provided And if enforcing this rule leaves no eligible facilitator, the session is flagged "Needs Facilitator" for manual selection And the decision path is recorded in the audit log
Localized Reminder Orchestration
"As a participant across timezones, I want reminders localized to my locale and schedule so that I don’t miss sessions or receive pings at unreasonable hours."
Description

Orchestrate reminders localized to each recipient’s timezone, locale, and channel preferences for every session in a stagger set. Convert start times to local formats, respect quiet hours, and vary lead times by region. Include contextual details (region pairing, facilitator, materials) and attach ICS where calendar access is limited. Handle DST transitions, reschedules, and attendance-based nudges. Support email and Slack/Teams with templated, translatable content and per-user notification preferences.

Acceptance Criteria
Timezone and Locale-Accurate Reminder Delivery
Given recipients in multiple timezones and locales and a staggered session set, When reminders are generated, Then each reminder displays the session start converted to the recipient’s local timezone and formatted per their locale (e.g., en-US vs en-GB) including correct weekday and 12/24h clock. Given a DST transition occurs between scheduling and send, When reminders are delivered, Then the local time reflects the correct post-transition offset and matches the canonical UTC start. Given a recipient has an unknown timezone, When generating reminders, Then fall back to the session region default timezone and log a warning. Given a recipient has an unsupported locale, When rendering content, Then use default en-US templates while preserving correct local time conversion.
Quiet Hours Compliance and Deferred Send
Given recipient quiet hours are configured (e.g., 22:00–07:00 local), When a reminder’s scheduled send time falls within quiet hours, Then defer delivery to the earliest allowed window before the session while maintaining the minimum region lead-time threshold. Given no allowable window exists before the event due to quiet hours, When evaluating delivery, Then send at the earliest post-window time and flag the send as "late-send" in logs. Given a manual re-send occurs during quiet hours with no emergency override, When processing, Then queue for the next allowed window instead of sending immediately. Given quiet hours are not configured for a user, When sending, Then apply org default quiet hours; if none exist, send immediately.
Channel Preference Routing with Fallback and ICS Attachment
Given per-user preferences specify a primary channel (Slack/Teams) and secondary email, When sending reminders, Then deliver via the primary channel; if delivery fails or user is not found within 60 seconds, fall back to email without duplicating content. Given the user’s primary channel is email and calendar access is limited, When sending, Then include a .ics attachment with unique UID, correct DTSTART/DTEND in UTC, and METHOD:REQUEST. Given Slack/Teams rate limits or throttling occur, When retrying, Then apply exponential backoff with jitter and ensure at-most-once delivery via idempotency keys. Given a user has opted out of a channel, When routing, Then exclude that channel and use an allowed channel only.
Region-Specific Lead Times Across Staggered Sessions
Given AMER/EMEA sessions require T-24h and T-2h reminders and APAC/EMEA requires T-12h and T-1h, When generating reminders for the stagger set, Then schedule per-region lead times relative to each session’s start in each recipient’s local time. Given a recipient has multiple sessions in the same week, When scheduling reminders, Then avoid overlapping sends within a 15-minute window per recipient by prioritizing the earliest session and deferring others. Given a session is flagged as early-morning (<08:00 local) for a recipient, When generating, Then add an extra T-36h reminder for that recipient only. Given organization overrides region defaults, When generating, Then apply overrides and record the policy source in the audit log.
Reschedule and Cancellation Update Propagation
Given a session is rescheduled, When the change is saved, Then cancel all previously queued reminders and send an update with the new time while honoring quiet hours and lead-time rules. Given a session is canceled, When the change is saved, Then send a single cancellation notice and retract/invalidate the .ics event; no further reminders are sent. Given a recipient already received a reminder for the old time, When sending the update, Then include an "Updated" label and show old vs new local time. Given multiple reschedules occur within 24 hours, When processing, Then coalesce changes and send at most one update per recipient per hour.
Templated, Translated Content with Required Context
Given the recipient’s locale is supported, When rendering the reminder, Then use the localized template and translate static strings while interpolating dynamic fields: region pairing, facilitator, materials link, session title, and join link. Given any dynamic field is missing, When rendering, Then substitute a safe fallback label and log a validation warning without blocking send. Given Slack/Teams as the channel, When rendering, Then use rich blocks/cards with a CTA to "View Session" and a compact summary; for email, include accessible HTML and a plaintext alternative. Given templates change over time, When deploying, Then version templates and reference a specific version in each reminder for reproducibility.
Attendance-Based Nudge Logic
Given a recipient has not RSVP’d or accepted the invite within the region-defined N hours before the session, When evaluating nudges, Then send a single nudge respecting quiet hours and channel preferences. Given a recipient has two consecutive absences in the last four sessions, When scheduling, Then add a pre-session accountability nudge to the facilitator and optionally the recipient’s manager if configured, respecting opt-outs. Given the recipient confirms attendance after a nudge is queued but before send, When processing, Then cancel the queued nudge. Given repeated non-responsiveness, When evaluating, Then cap nudges at one per week per recipient and include an "adjust preferences" link.
One-click Invite Automation
"As an organizer, I want approved stagger sets to automatically create the right invites and attendee lists per region so that I don’t spend time manually managing calendars."
Description

From an approved stagger plan, automatically create and manage calendar invites across Google Workspace and Microsoft 365. Generate distinct events per session with correct attendee lists by region, conferencing links, time zone metadata, and concise titles (e.g., “[Stagger] AMER/EMEA Sprint Sync”). Detect conflicts and propose nearest alternatives within acceptable windows. Apply recurrence with exceptions where needed, propagate updates on edits, attach agendas, and capture RSVPs back into TimeMeld for attendance tracking.

Acceptance Criteria
One-click invite creation across Google and Microsoft
Given an approved stagger plan with sessions, region mappings, attendee lists, and authorized Google Workspace and Microsoft 365 connectors When the user clicks "Create Invites" Then TimeMeld creates a distinct calendar event for each session in the plan And the event is created on the designated organizer calendar for that session's provider And all listed attendees for that session's regions are invited And iCalendar invitations are delivered to all attendees regardless of provider interoperability And start and end times are saved in the session's designated time zone
Conferencing link per session
Given conferencing defaults are set in the plan (Google Meet or Microsoft Teams) or overridden per session When invites are created Then each event includes a unique conferencing link matching the organizer's provider And no two events in the stagger set share the same join URL And the join link is visible and accessible to all invited attendees
Title and time zone metadata formatting
Given regions and session name are defined in the plan When invites are created Then each event title matches the template "[Stagger] {regions} {sessionName}" And the event time zone is set using the correct IANA identifier for the session And the ICS payload contains VTIMEZONE/TZID matching the event's time zone And the agenda from the stagger plan is attached to each event (file or link)
Conflict detection and nearest alternatives
Given acceptable windows and key-attendee rules are defined in the plan When a conflict is detected for a session during invite creation Then TimeMeld proposes at least one alternative slot within the acceptable windows, ordered by proximity to the original time And each proposal respects regional working hours and ergonomic constraints And conflicted sessions are held for user decision (accept proposal, choose another time, or proceed anyway) before creation And a conflict report is recorded for audit
Recurrence with exceptions
Given a session is marked recurring with frequency and exception dates from holiday clusters When invites are created Then a recurring series is created using RRULE reflecting the specified cadence And EXDATEs are added for all exception dates And alternate slots on exception weeks are created as standalone events And daylight saving transitions are honored without shifting local start times
Propagation of edits to existing invites
Given the stagger plan is modified after invites are created When the user triggers "Sync Updates" Then existing events are updated in place (time, title, attendees, conferencing) without creating duplicates And per-occurrence edits and exceptions are preserved And updated invitations/notifications are sent according to provider norms And a change log entry is written for each updated event
RSVP capture and attendance sync to TimeMeld
Given invites have been sent for a session When attendees respond Accept, Tentative, or Decline in Google or Microsoft Then TimeMeld ingests the response and maps it to a unified status And the session's RSVP list in TimeMeld is updated within 5 minutes And subsequent changes to responses are reflected in TimeMeld within 5 minutes
Stagger Plan Preview & Editor
"As a product manager, I want to preview and tweak the stagger plan with holiday overlays and ergonomics visible so that I can confidently approve a balanced schedule."
Description

Provide an interactive preview of the proposed stagger plan with week-by-week, region-grouped views, holiday overlays, and ergonomic score indicators. Allow drag-and-drop adjustments, locking of sessions, swapping of region pairings, and inline validation (fairness, conflicts, quiet hours). Display facilitator rotation impacts and warnings when equity regresses. Support draft saving, version comparison, and a single approval action to publish invites and reminders. Ensure accessibility and role-based permissions for viewing and editing.

Acceptance Criteria
Preview shows week-by-week region groups with holidays and ergonomic scores
Given a generated stagger plan spanning at least two weeks and multiple regions When the user opens the Stagger Plan Preview Then the preview displays each week as a distinct section with sessions grouped by region Given a session that falls on or overlaps a recognized holiday for its region When the preview renders Then the session shows a holiday badge that references the correct region and date Given any session in the preview When the preview renders Then an ergonomic score indicator is visible for that session and matches the backend-provided score value Given regional display timezone settings exist When session times are shown Then each session displays the correct local date/time using its region’s configured display timezone
Editing sessions via drag-and-drop with locking and inline validation
Given the preview editor is open When the user drags a session to a new valid time slot Then the session is moved to the new slot and validations and ergonomic scores are recalculated Given the user attempts to drop a session into a slot with a hard conflict (calendar conflict or outside scheduling window) When the drop occurs Then the drop is blocked, an inline error tooltip identifies the specific constraint, and the session remains in its original slot Given the user drops a session into a slot that breaches a soft constraint (quiet hours or fairness threshold) When the drop occurs Then the move is allowed and a warning badge appears describing the issue Given a session is locked by an editor When automatic reflow or other edits occur Then the locked session’s time and region pairing do not change Given a session is locked When a user attempts to drag it Then the drag is prevented and a tooltip instructs the user to unlock before moving
Swapping region pairings across weeks
Given two consecutive weeks with distinct region pairings When the user selects Swap Pairings for those weeks Then the region pairings are exchanged and the preview updates session times and ergonomic scores accordingly Given a proposed swap introduces any hard conflict When the user attempts the swap Then the swap is blocked and a specific conflict reason is displayed with links to affected sessions Given a swap is completed successfully When the preview refreshes Then facilitator rotation order is preserved relative to the sessions involved
Facilitator rotation updates and equity regression warnings
Given an edit changes a session’s timing or region pairing When the change is applied Then the facilitator rotation panel updates to show deltas in ownership counts per facilitator Given the edit causes equity to regress beyond the configured threshold When the change is applied Then a prominent warning is displayed and the user must confirm to proceed Given an edit does not cause equity regression beyond the threshold When the change is applied Then no equity warning is shown and the rotation indicators remain in a non-warning state
Draft saving, version history, comparison, and restore
Given an edited plan with unsaved changes When the user clicks Save Draft Then a new draft version is created with timestamp and author and the plan state is persisted Given at least two draft versions exist When the user selects Compare between version A and version B Then the diff view highlights changed sessions, region pairings, facilitators, and ergonomic score deltas for each affected session Given the user is viewing a comparison When they click Restore on version A Then the current working draft is replaced with version A and a new version entry records the restore action
Single approval action publishes invites and localized reminders
Given a draft passes all hard validations When the approver clicks Approve & Publish Then calendar invites are created for all sessions and reminders are scheduled with localization rules applied per region Given hard validation errors exist on the plan When Approve & Publish is clicked Then publishing is blocked and a list of errors is displayed with links to the affected sessions Given publishing completes successfully When the process finishes Then the plan status becomes Published, the preview becomes read-only, and an audit entry records the approver and timestamp
Role-based permissions and accessibility compliance
Given a user with Viewer role When they open the Stagger Plan Preview & Editor Then they can view the preview and version history but cannot edit, lock, swap, or approve Given a user with Editor role When they open the Stagger Plan Preview & Editor Then they can edit, lock, swap, and save drafts but cannot Approve & Publish Given a user with Approver role When they open the Stagger Plan Preview & Editor Then they can perform all editor actions and Approve & Publish Given the interface is used with a screen reader and keyboard When navigating all controls Then all interactive elements have accessible names, roles, and states, are reachable in logical tab order, and meet WCAG 2.1 AA contrast requirements Given any informational indicator (holiday badge, ergonomic score, warning) When it receives keyboard focus Then an accessible description is announced conveying the same information available visually
Outcomes Analytics & Audit Log
"As an ops lead, I want visibility into coverage, fairness, and attendance outcomes so that I can prove impact and refine future scheduling strategies."
Description

Deliver post-scheduling analytics and a complete audit trail for generated stagger sets. Report coverage by region, facilitator load/fairness indices, ergonomic score distribution, attendance and no-show rates, and changes vs. baseline scheduling. Provide filters by time period and team, export to CSV, and shareable dashboards. Capture generation inputs, chosen plan, overrides, and rationale to enable compliance and continuous improvement of the Stagger Builder.

Acceptance Criteria
Regional Coverage & Ergonomic Distribution Dashboard
Given a generated stagger set with sessions tagged by AMER, EMEA, and APAC and ergonomic scores And I select a specific Team and a Time Period in Outcomes Analytics When I open the Regional Coverage view Then the dashboard displays coverage percentages per region that sum to 100% (±1% rounding tolerance) And session counts per region match the underlying dataset for the selected filters And the ergonomic distribution displays median, p10, p90, and a 10-bin histogram And all displayed values match the analytics API values for the same filters within 0.5% And all timestamps are rendered in the org default timezone with UTC offsets indicated
Facilitator Load & Fairness Indices
Given facilitators are assigned to sessions within the filtered stagger set When I open the Facilitator Load view Then each facilitator shows total sessions, sessions per week (last 4 weeks), and upcoming sessions And the fairness index is calculated as the Gini coefficient over sessions per facilitator for the selected window And the displayed Gini value matches the backend computation within 0.01 And facilitators more than 1 session above the team average in the window are flagged as Overloaded And a definition tooltip for the fairness index is present and accurate
Baseline Comparison (Changes vs. Baseline Scheduling)
Given a selectable baseline source of Previous Comparable Period or Pre‑Stagger Snapshot exists for the chosen team and time window When I enable Show Changes vs Baseline Then deltas for region coverage, fairness index, ergonomic median, attendance rate, and no‑show rate are displayed next to current values And each delta is computed as Current − Baseline and color‑coded (green for improvement, red for regression) And improvements are defined as: higher attendance rate, lower no‑show rate, lower fairness Gini, higher minimum region coverage, and higher ergonomic median And the baseline source and date range are clearly labeled And if no baseline exists for any metric, the metric shows No baseline available and is excluded from delta summaries
Attendance & No‑Show Rates Calculation
Given calendar invite responses exist for scheduled sessions and a conferencing provider presence integration is connected When I open Attendance Analytics for the selected team and time period Then attendance rate is calculated as Joined attendees ÷ Accepted attendees, and no‑show rate as (Accepted − Joined) ÷ Accepted And displayed rates match combined calendar and provider data within 1 percentage point for each session and aggregate And sessions lacking provider data are marked Data unavailable and excluded from aggregates by default, with a toggle to include them as zeros And attendance metrics are finalized within 24 hours after session end
Filters and CSV Export (Analytics and Audit Log)
Given I have applied Team and Time Period filters (and optional tags) on an analytics or audit log view When I click Export CSV Then a CSV is downloaded within 5 seconds containing only rows matching the active filters And all date/time fields are ISO 8601 UTC (e.g., 2025-09-11T15:04:05Z) And numeric fields use dot decimal and no thousands separators And Analytics export includes columns: session_id, team_id, team_name, region, ergonomic_score, facilitator_id, facilitator_name, scheduled_start_at, scheduled_end_at, attendance_rate, no_show_rate, fairness_gini_window, plan_id, generated_at, baseline_delta_attendance, baseline_delta_no_show, baseline_delta_fairness_gini, baseline_delta_ergonomic_median And Audit export includes columns: event_id, timestamp, actor_user_id, actor_name, action_type, inputs_json, chosen_plan_id, override_fields_json, rationale_text, previous_value_json, new_value_json, ip_address, request_id And the exported row count equals the number of rows indicated in the UI for the same filters
Audit Trail Completeness & Immutability
Given a stagger set is generated, overridden, or published When any of these actions occur Then an audit entry is written with fields: timestamp (UTC ISO 8601), actor_user_id, actor_name, action_type, inputs_json, chosen_plan_id, changes_before_after, rationale_text (required for overrides), request_id, and content_hash And audit entries are append‑only; attempts to edit or delete return 403 and create a new audit entry indicating the denied attempt And the audit log is filterable by plan_id, actor, action_type, team, and date range and returns results within 2 seconds for up to 100k entries And the audit timeline renders in chronological order with deterministic tiebreakers for identical timestamps And audit data has a retention of at least 24 months; older entries are exported to cold storage and remain exportable via CSV
Shareable Dashboards & Access Control
Given I have view permission for a team’s analytics dashboard When I create a share link Then I can set an expiration (7, 30, or 90 days) and optionally allow CSV export And the generated URL is tokenized, view‑only, and scoped to the selected team and time period And viewers via the link cannot change team scope and cannot access audit logs unless explicitly enabled And revoking the link invalidates access within 60 seconds And share link create, view, and revoke events are captured in the audit log with actor and IP

QuietWeek Mesh

Detects declared quiet weeks and low‑activity periods across teams, then proposes cadence adjustments—pre‑load, pause, or stretch—ranked by projected attendance and equity impact. You keep operating rhythms healthy without cramming work into compromised weeks.

Requirements

Quiet Week Detection Engine
"As a team ops lead, I want TimeMeld to automatically detect our teams’ quiet weeks from calendars and PTO systems so that scheduling logic can proactively adjust recurring meetings without manual tagging."
Description

Continuously aggregates declared quiet weeks and out-of-office (OOO) signals from shared organization calendars, HRIS/PTO systems, and region-specific public holidays; normalizes them to team scopes and time zones to identify quiet ranges per team. Supports manual declarations via UI and API, deduplicates overlaps, retains source and confidence metadata, and updates detections daily. Exposes the results to TimeMeld’s scheduling pipeline with change logs. Enforces data minimization by using only busy/free and configured labels, never reading event contents.

Acceptance Criteria
Multi-Source Quiet Signal Aggregation and Normalization
Given an organization has connected shared calendars, HRIS/PTO integration, and regional holiday sources configured, and teams defined with member lists and time zones When the detection engine runs Then it ingests signals from calendar free/busy with configured labels, HRIS/PTO OOO periods, and regional public holidays, recording a fetch status per source And it computes quiet ranges per team with fields: team_id, range_start_utc, range_end_utc, team_timezones[], coverage_percent, sources[], confidence_score, last_updated_at And range_start_utc and range_end_utc correspond to full-day boundaries in the team's primary time zone and are stored in UTC And coverage_percent equals impacted_members divided by total_active_team_members times 100, rounded to the nearest integer And confidence_score is between 0.0 and 1.0 and greater than 0.0 when at least one valid source contributes
Overlap Deduplication and Confidence Consolidation
Given multiple source signals overlap in time for the same team When the engine consolidates detections Then time-overlapping periods are merged into a single quiet range And the merged range retains a sources[] array with each contributing source and its occurrence count And there are no two quiet ranges for the same team that overlap in time And confidence_score reflects combined evidence and remains within [0.0, 1.0]
Manual Quiet Range Declarations via UI and API
Given a user with Scheduler Admin role declares a quiet range for a team via the UI or API with a valid date range and label When the declaration is submitted Then the system persists the declaration with source=manual, actor_id, and timestamp And the declaration appears in the next detection output for that team and contributes to coverage_percent and confidence_score And overlapping manual declarations take precedence over lower-confidence automatic signals during the overlap And the user can update or cancel the declaration, and the change is reflected in the next detection output
Daily Detection Refresh and Change Logs
Given the detection engine is operational When 24 hours have elapsed since the last run or new manual declarations are received Then a detection run executes and recalculates quiet ranges per team And a change log entry is written for each addition, modification, or removal, including team_id, before, after, reason, sources, and timestamp And change logs are accessible via API and are ordered chronologically
Data Minimization and Privacy Enforcement
Given calendar integrations are connected When the engine accesses calendar data Then it requests and uses only free/busy state and configured label metadata and does not read or persist event titles, descriptions, attendee lists, or content And attempts to access disallowed fields are blocked and logged with reason and correlation_id And stored records for detections contain no event content fields and pass an automated scan that verifies absence of PII beyond team membership and time blocks
Regional Holiday Mapping and Team Scope Resolution
Given a team has members assigned to specific regions and time zones When regional public holidays occur within the evaluation window Then holiday signals are attributed to affected members only and contribute to coverage_percent accordingly And holiday-derived quiet ranges align to the local dates of the respective regions and are stored as UTC ranges And if a team spans multiple regions, the union of applicable regional holidays is considered in detection
Scheduling Pipeline Consumption of Quiet Ranges
Given TimeMeld’s scheduling pipeline requests quiet ranges for a team and time window When the pipeline calls the quiet range API Then the API returns HTTP 200 with a list of quiet ranges matching the window, including team_id, range_start_utc, range_end_utc, coverage_percent, confidence_score, and sources[] And results are sorted by range_start_utc and include a monotonically increasing version or ETag and last_updated_at And the API also returns change logs for the requested window when include_changes=true is provided
Low-Activity Heuristics
"As a product manager, I want the system to identify likely low-activity periods based on signals like OOO density and working-hours overlap so that I can plan ceremonies around those dips."
Description

Identifies low-activity periods by analyzing historical calendar density (free/busy), OOO ratios, and working-hours overlap across time zones over a trailing window (e.g., 8 weeks). Optionally ingests auxiliary signals (e.g., ticket volume or deploy freezes) when configured. Produces candidate date ranges with confidence scores and tunable thresholds per team, with safeguards such as minimum sample sizes and policy-based exclusions for launches or incidents.

Acceptance Criteria
Data Sufficiency and Safeguards
Given trailing_window_weeks=8, min_history_weeks=6, min_day_coverage=0.8, and min_sample_size=5 When a team has history_weeks < 6 OR active_members < 5 OR any history week has day_coverage < 0.8 Then the system returns zero candidate ranges and records reason="insufficient_data" for the team and does not compute confidence scores Given sufficient data per the above safeguards When candidate generation runs Then a run record is stored with ran_with_safeguards=true
Policy-Based Exclusions: Launches and Incidents
Given a policy_exclusions list of date ranges tagged as launch or incident When a generated candidate overlaps an exclusion by ≥ 1 calendar day Then the candidate is discarded and a discard_reason="policy_exclusion" referencing the policy IDs is emitted Given a candidate range that abuts but does not overlap an exclusion (end_date == exclusion.start_date - 1 OR start_date == exclusion.end_date + 1) When validation runs Then the candidate is retained
Confidence Score Computation and Bounds
Given normalized signal scores s_cal, s_ooo, s_overlap in [0,1] and weights w_cal, w_ooo, w_overlap ≥ 0 with w_cal + w_ooo + w_overlap = 1 (default weights 0.5/0.3/0.2) When a candidate is produced Then confidence = round(s_cal*w_cal + s_ooo*w_ooo + s_overlap*w_overlap, 2) and 0.00 ≤ confidence ≤ 1.00 Given s_cal and s_overlap held constant and s_ooo2 > s_ooo1 with unchanged weights When confidence is recomputed Then confidence2 ≥ confidence1 Given identical inputs When computation is repeated Then the same confidence value is returned Given s_cal=0.7, s_ooo=0.6, s_overlap=0.4 and default weights When confidence is computed Then confidence = 0.61
Tunable Thresholds per Team and Persistence
Given team T with default thresholds density_threshold=0.6, ooo_threshold=0.25, overlap_threshold=0.5 When an admin updates T's thresholds to density_threshold=0.55, ooo_threshold=0.30, overlap_threshold=0.45 Then subsequent candidate generation for T uses the new thresholds and the values persist across runs and service restarts Given a threshold update event When generation runs within 1 minute of the change Then the new thresholds are applied (no stale cache) Given a team without overrides When generation runs Then org-level defaults are used Given an audit log When thresholds change Then an entry records team_id, actor_id, old_value, new_value, and timestamp
OOO Ratio Signal Integration
Given OOO events mapped to members with contractual working hours H per member per week When computing OOO_ratio = sum(OOO_hours)/sum(H) for a week Then s_ooo = min(1.0, OOO_ratio / ooo_threshold) and is in [0,1] Given partial-day OOO and overlapping OOO events When computing OOO_hours Then overlaps are de-duplicated and partial days are prorated by hours Given OOO ingestion is disabled for an org When generating candidates Then the OOO signal is marked unavailable and weights are renormalized over available signals (confidence excludes s_ooo)
Working-Hours Overlap Across Time Zones
Given members with time zones and working-hours windows per weekday When computing average pairwise overlap hours over a week Then overlap_ratio = avg_overlap_hours / avg_possible_hours and s_overlap = min(1.0, max(0.0, (overlap_threshold - overlap_ratio)/overlap_threshold)) such that lower overlap yields higher s_overlap Given a DST transition during the evaluated dates When overlaps are computed Then local UTC offsets are applied per date so overlap reflects actual clock changes Given all members share the same time zone and working hours When overlaps are computed Then s_overlap = 0 (no low-activity signal from overlap)
Candidate Date Range Generation and Format
Given planning_horizon_weeks=8 and min_range_days=3 When low-activity signals exceed thresholds on contiguous days Then the system emits non-overlapping candidate ranges with fields {start_date, end_date, confidence} where duration ≥ 3 days, sorted by start_date ascending Given two candidate ranges separated by a 1-day non-qualifying gap When generation runs Then the ranges remain separate (no merging across non-contiguous periods) Given no day meets thresholds When generation runs Then zero candidate ranges are emitted
Cadence Adjustment Generator
"As a scrum master, I want proposals to preload, pause, or stretch our recurring ceremonies across quiet weeks so that we avoid cramming or meeting during compromised weeks."
Description

Generates proposals for recurring meeting series that intersect quiet or low-activity ranges, offering three options: preload (advance the nearest session into the prior week), pause (skip occurrences within the range), or stretch (temporarily extend the interval until the range ends). Respects series constraints, participant working-hour overlap, host availability, minimum lead time, and conflict limits to avoid cramming adjacent weeks. Outputs machine-readable proposals with rationale and any detected conflicts.

Acceptance Criteria
Three Proposal Options for Quiet-Range Intersections
Given a recurring meeting series with at least one occurrence intersecting a declared quiet or low-activity range When the Cadence Adjustment Generator runs Then it produces exactly three proposal types for the series: preload, pause, and stretch And each proposal references the seriesId and enumerates affected occurrence IDs and UTC date-times And each proposal states the decision scope (only occurrences within or immediately adjacent to the range)
Preload Honors Minimum Lead Time and Avoids Cramming
Given the next scheduled occurrence falls within the quiet/low-activity range And a configurable minimumLeadTimeHours is set for the series And a perWeekMaxOccurrences limit is configured When a preload proposal is generated Then it advances exactly one affected occurrence into the immediately preceding calendar week And the proposed new slot startTimeUTC is at least minimumLeadTimeHours in the future from generationTime And the prior week’s total scheduled occurrences for the series does not exceed perWeekMaxOccurrences after applying the preload And the preload does not shift any other future occurrences beyond their original cadence outside the quiet range
Pause Skips Quiet-Range Occurrences While Preserving Cadence
Given multiple occurrences of the series fall within the quiet/low-activity range When a pause proposal is generated Then it lists all occurrence IDs/dates to be skipped within the range And it leaves post-range recurrence alignment unchanged (the first occurrence after the range matches the original cadence anchor) And no new occurrences are added to adjacent weeks as part of the pause
Stretch Extends Interval Without Exceeding Limits
Given a baseline recurrence interval (e.g., weekly) and a maxStretchMultiplier is configured When a stretch proposal is generated Then inter-occurrence intervals are temporarily extended so that no occurrence falls within the quiet/low-activity range And no adjusted interval exceeds baselineInterval * maxStretchMultiplier And after the range ends, the recurrence reverts to the original cadence and anchor And all adjusted dates are output as UTC with source timezone metadata
Enforcement of Working-Hour Overlap, Host Availability, and Conflict Limits
Given participant working-hour windows, meeting duration, and required attendees are defined And host availability and existing calendar events are known And a weeklyConflictLimit is configured for adjacent weeks When evaluating candidate times for any proposal type Then each proposed time provides at least duration minutes of overlap within declared working hours for all required participants And the host is free for the entire duration with required buffer rules satisfied And applying the proposal does not cause adjacent weeks to exceed weeklyConflictLimit for the series
Machine-Readable Output with Rationale, Ranking, and Conflicts
Given proposals are generated for a series When they are returned to the caller Then the JSON payload for each proposal includes: proposalId, seriesId, type (preload|pause|stretch), affectedOccurrences[], proposedSlots[], generationTimeUTC, parametersUsed, rationale { text, projectedAttendanceScore, equityImpactScore, timezoneConvenienceScore }, conflicts[] And proposals include a rankIndex and are sorted by projectedAttendanceScore desc, then equityImpactScore desc, then timezoneConvenienceScore desc And proposals with non-empty conflicts[] are flagged as isConflictFree=false and may be ranked below conflict-free options
No Intersection or No Feasible Option Handling
Given a series has no occurrences intersecting a declared quiet/low-activity range When the generator runs Then it returns no proposals for that series And given a series does intersect but all options violate constraints (lead time, availability, overlap, conflict limits) When the generator runs Then it returns a no_feasible_proposal result with a machine-readable reasons[] list covering each violated constraint
Attendance and Equity Scoring
"As a meeting owner, I want each proposal scored for attendance and equity impact so that I can pick the option that maximizes turnout while keeping times fair across time zones."
Description

Scores each proposal by predicting attendance using historical participation, OOO likelihood, overlap-hours ergonomics, and conflict risk, while simultaneously computing equity impact using TimeMeld’s ownership rotation model. Produces scalar scores and deltas versus the status quo to enable transparent ranking and to prevent repeated inconvenient slots for the same cohorts.

Acceptance Criteria
Compute Scalar Scores and Deltas for Proposal Batch
Given a batch of meeting proposals and a defined status quo slot When the Attendance and Equity Scoring service runs Then each proposal contains attendance_score (0–100), equity_score (0–100), combined_score (0–100), delta_attendance_vs_status_quo (numeric), and delta_equity_vs_status_quo (numeric) And scores are deterministic for identical inputs and configuration (same seed) And proposals missing required inputs (participants, time window, status quo) are flagged with a validation error and are not ranked
Penalize OOO and Calendar Conflict Risk
Given a proposal where at least 15% of invitees (or ≥2 people, whichever is higher) are marked OOO for the slot When scoring is computed Then attendance_score is reduced by at least 15 points versus the same proposal with no OOO flags Given a proposal with hard calendar conflicts for invitees When scoring is computed Then attendance_score is reduced by ≥5 points per conflicted invitee up to a maximum conflict penalty of 25 points Given two otherwise identical proposals differing only in aggregate conflict probability When scored Then the proposal with higher conflict probability receives a strictly lower attendance_score
Ergonomics Penalties for Off-Hours Overlap
Given a proposal where more than 30% of invitees fall outside 09:00–17:00 local time for the slot When scoring is computed Then attendance_score includes an ergonomics penalty of at least 10 points Given a proposal where any invitee falls outside 07:00–20:00 local time When scoring is computed Then an additional high-risk ergonomics penalty of at least 5 points is applied Given two otherwise identical proposals, one with higher within-9–5 overlap across timezones When scored Then the higher-overlap proposal receives a higher attendance_score
Equity Impact via Ownership Rotation and Inconvenience Distribution
Given a status quo history of the last 6 meetings with recorded inconvenient slots per cohort (team/timezone) When equity_score is computed for a new proposal Then proposals that reduce the standard deviation of inconvenient_slot_count across cohorts yield a delta_equity_vs_status_quo > 0 And proposals that increase concentration (any cohort’s count increases by ≥1) yield a delta_equity_vs_status_quo < 0 Given two proposals with identical attendance factors When equity_score is compared Then the proposal that reduces repeated inconvenience for the same cohort receives an equity_score at least 10 points higher
Combined Score, Weighting, Ranking, and Tie-Breaks
Given attendance_score and equity_score for each proposal When combined_score is computed Then combined_score = 0.7 × attendance_score + 0.3 × equity_score by default Given a set of proposals with computed combined_score When ranked Then proposals are ordered by combined_score descending And ties are broken by higher equity_score, then by higher attendance_score Given configuration to override weights When new weights are applied Then combined_score reflects the new weights and ranking updates accordingly
Rescoring Latency and Freshness on Calendar Update
Given up to 50 proposals and 30 invitees When a participant’s calendar or OOO status changes Then rescoring completes within 2 seconds at p95 and rankings refresh accordingly Given a changed conflict state for any invitee When rescored Then affected proposals reflect updated attendance_score deltas within the same operation (no stale status quo deltas)
Ranked Suggestions and Review UI
"As a team coordinator, I want a ranked list of suggestions I can review, tweak, and bulk apply with clear impact previews so that I can make fast, informed decisions."
Description

Displays a ranked list of proposals per team or series with clear rationale (attendance delta, equity delta, affected dates, confidence) and provides controls to accept, decline, edit, bulk-apply, or snooze. Supports real-time recalculation on edits, a diff view of calendar impact, and a reversible audit trail. Accessible in the web app and embeddable into Slack for decision-making in channel.

Acceptance Criteria
Ranked Proposals List With Rationale Fields
Given a team or series with at least one detected quiet period When the Review UI loads Then proposals are displayed in a single ranked list sorted by projected attendance delta (descending), then equity delta (descending), then confidence (descending) And each proposal displays attendance delta as a signed percentage, equity delta as a signed score, affected dates as a list of ISO dates with local day names, and confidence as a 0–100% value And the rank order matches the backend API priority for the same input set And when no proposals exist, the empty state "No proposals" is shown with a refresh action
Action Controls: Accept, Decline, Edit, Bulk-Apply, Snooze
Given a visible proposal and a user with edit permissions When the proposal row renders Then controls for Accept, Decline, Edit, Bulk-Apply, and Snooze are enabled; otherwise they are disabled with a tooltip explaining why When Accept is confirmed Then the proposal applies, calendar updates are queued, the item shows Accepted, and an audit record is created When Decline is confirmed Then no calendar changes occur, the item shows Declined, a reason is required, and an audit record is created When Bulk-Apply is executed on a selected set Then all selected proposals apply atomically; on any failure, no changes persist and the error list is shown When Snooze is set (duration or until date) Then the proposal is hidden from default view and resurfaces at the configured time
Real-Time Recalculation on Edits
Given a user edits proposal parameters (dates, attendees, constraints) When changes are saved Then rank and rationale fields recalculate and render within 2 seconds And updated fields are highlighted and rank movement (+/− positions) is shown And dependent proposals display consistent updated values with no stale data And an "Updated just now" timestamp reflects the refresh time
Calendar Impact Diff View
Given an unaccepted proposal When the user opens the Diff view Then before/after lists show added, moved, and skipped meetings with local times for all affected participants And timezone offsets match the effective dates for each participant And the diff shows invite counts and predicted attendance change per event And the user can export the diff as CSV and print a PDF with the same content
Reversible Audit Trail
Given any action (Accept, Decline, Edit, Bulk-Apply, Snooze) When the action completes Then an audit record captures actor, UTC timestamp, action, before/after payloads, and reason (if provided) And the user can filter and search the audit trail by actor, action, date range, and team/series And the user can revert any single action; after revert, calendar and ranks return to the prior state and a reversal record links to the original And redo is available immediately after an undo
Slack In-Channel Review and Actions
Given a Slack channel with the TimeMeld app installed and permissions granted When /timemeld review is invoked or an automated post triggers Then an interactive message shows the top 5 ranked proposals with rationale fields and action buttons When an action is taken in Slack Then the web UI reflects the change within 5 seconds and the audit trail logs the source as Slack And permission denials return an ephemeral error without posting to the channel And Edit opens a Slack modal allowing parameter changes with live validation
Accessibility, Performance, and Resilience
Given up to 100 proposals When the Review UI loads on a broadband connection Then initial contentful paint occurs within 1.5 seconds and interaction latency is under 100 ms for list actions And all interactive elements are keyboard navigable with visible focus, ARIA labels, and WCAG 2.1 AA contrast And the UI functions on latest Chrome, Firefox, Safari, and Edge And if recalculation services are unavailable, a non-blocking error is shown and retry preserves unsaved edits
Auto-Execution and Calendar Sync
"As an engineering manager, I want approved changes to update our Google/Outlook calendars and notify participants automatically so that I don’t have to manually reschedule events."
Description

Applies approved adjustments by updating or canceling calendar events and series via Google Workspace and Microsoft 365 APIs, sending updated invites and notifications in participants’ local time zones. Preserves meeting metadata (links, agendas), respects RSVP states, enforces conflict checks and minimum lead time, and implements idempotent retries with user-visible error handling for API failures.

Acceptance Criteria
Apply Pre-Load Adjustment to Recurring Series (No Conflicts, Meets Lead Time)
Given an approved pre-load adjustment affecting the next 2 occurrences of a weekly series And all required attendees have no "busy" conflicts with the proposed earlier times And the earliest moved occurrence starts at least 24 hours from now in the organizer's calendar time zone When TimeMeld executes the adjustment via Google Workspace or Microsoft 365 APIs Then the series is updated so that the next 2 occurrences move to the proposed times And the meeting's conferencing link, agenda URLs, description, and attachments remain unchanged And updated invitations are sent to all attendees with times displayed in each recipient's local time zone And existing attendee RSVP statuses (Accepted/Declined/Tentative) are preserved And no duplicate events or invitations are created
Pause Adjustment Cancels Occurrences During Quiet Week (Idempotent)
Given an approved pause adjustment for a series within a declared quiet week window When TimeMeld executes the cancellation Then the targeted occurrences are canceled with ICS METHOD:CANCEL notifications sent to all attendees in their local time zones And future series beyond the pause window remains intact And no orphan calendar holds remain on any attendee calendar And if the API call is retried with the same idempotency key within 24 hours, no additional cancellations or duplicate emails are produced And the audit log records the occurrence IDs canceled and notification counts
Stretch Cadence From Weekly to Biweekly With Minimum Lead Time
Given an approved stretch adjustment changing a weekly series to biweekly And the next eligible occurrence under the new cadence starts at least 24 hours from now When TimeMeld updates the recurrence rule on Google Workspace and Microsoft 365 Then the RRULE is updated to every 2 weeks starting from the next eligible date And any existing series exceptions (modified or skipped occurrences) remain unchanged And updated invitations are sent with local-time display for all recipients And meeting metadata (conferencing links, agenda links, description, attachments) is preserved
Conflict Check Blocks Auto-Execution for Required Attendees
Given an approved adjustment that would move an occurrence And one or more required attendees have an overlapping "busy" event by at least 1 minute at the proposed time When TimeMeld evaluates conflicts Then auto-execution is blocked and no calendar changes are made And the organizer receives a user-visible error within 10 seconds listing conflicted attendees and time windows And the adjustment remains pending for manual resolution
Local-Time Notifications Across DST and Extreme Time Zones
Given attendees across time zones including UTC-11, UTC+0, UTC+14, and a region entering or leaving DST within 7 days When TimeMeld sends update or cancellation notifications Then each recipient sees the correct local start/end times in the email and calendar UI And ICS files include correct VTIMEZONE/TZID entries so clients render the same times And no recipient sees a displayed time that differs from their calendar's computed local time by more than 0 minutes
Idempotent Retries With Backoff on API Errors
Given a transient 5xx or 429 response from Google or Microsoft during execution When TimeMeld retries with exponential backoff (initial 1s, max 32s) up to 5 attempts using a stable idempotency key Then exactly one calendar mutation is committed if a retry succeeds And no duplicate invites or cancellations are sent And on final failure, the organizer is notified with an actionable error message and a retry link And the system records error code, request ID, and retry count in the audit log
Preserve RSVP States and Metadata on Time Change
Given a time change is applied to an occurrence or series When the update is committed Then existing attendee RSVP statuses remain unchanged in both Google and Microsoft calendars And conferencing links (Google Meet/Microsoft Teams/Zoom), agenda links, description, and attachments remain unchanged And only the date/time/recurrence fields are modified And no additional events or attendees are added or removed by the update
Policy Engine and Admin Controls
"As an admin, I want to set org-wide policies and exclusions for QuietWeek Mesh so that the feature behaves consistently and respects compliance requirements."
Description

Provides org- and team-level policies governing QuietWeek Mesh behavior, including sources of truth, required lead time, blackout periods, excluded meetings, and minimum attendance thresholds. Enables admins to set default actions (e.g., pause non-critical ceremonies during quiet weeks), override heuristics, manage RBAC, capture consent for data sources, and export logs for compliance and audits.

Acceptance Criteria
Data Sources & Consent Management
Given an Org Admin selects HRIS, PTO calendars, and project boards as data sources, When saving the policy, Then the system validates API credentials and required scopes and confirms success only if all validations pass. Given a new data source requires end-user consent, When users next sign in, Then they are prompted with a consent modal showing purpose, scope, and retention, and can Accept or Decline. Given a user declines consent, When QuietWeek Mesh computes proposals, Then the user’s personal data is excluded and calculations fall back to team-level aggregates with a visible "consent-restricted" flag. Given a user withdraws consent, When revocation is submitted, Then processing of that user’s data stops within 5 minutes and historical records are flagged as "revoked" without further use. Given consent records exist, When an admin opens the consent ledger, Then each entry shows user, data source, status (Granted/Declined/Revoked), timestamp, and versioned policy text hash.
Lead Time Policy Enforcement
Given org lead time policy = N business days, When QuietWeek Mesh proposes cadence adjustments, Then no proposal schedules or moves a meeting with less than N business days’ notice. Given an adjustment would violate lead time, When an admin attempts approval, Then the system blocks the action and suggests the next valid dates respecting lead time. Given multi-time-zone participants, When computing business days, Then the owner’s locale calendar and org holidays are applied consistently. Given critical meetings allow exceptions, When a user with Override permission supplies justification, Then scheduling within lead time is allowed and the exception is logged with user, reason, and timestamp.
Blackout Periods Enforcement
Given team blackout windows are configured, When proposals overlap a blackout, Then affected ceremonies are paused or stretched per policy and no invites are issued within blackout windows. Given overlapping org-level and team-level blackouts, When conflicts occur, Then the stricter blackout prevails and the proposal shows the governing rule. Given a blackout period ends, When the end time passes, Then normal cadence resumes automatically without manual intervention. Given recurring blackouts (e.g., last week of quarter), When saved, Then recurrence rules are respected for at least the next 12 months of proposals.
Default Actions and Excluded Meetings During Quiet Weeks
Given org defaults specify pausing non-critical ceremonies and stretching weekly 1:1s to biweekly in quiet weeks, When a quiet week is detected, Then proposals apply these defaults with projected attendance and equity impact scores. Given a meeting is tagged as Excluded, When generating proposals, Then that meeting is not paused, stretched, or rescheduled by QuietWeek Mesh. Given an exclusion rule matches by title regex, organizer, or label, When policy runs, Then the match is applied consistently and listed under "Exclusions applied" with the rule reference. Given multiple defaults conflict, When precedence rules are configured, Then the higher-precedence default governs and the decision rationale is recorded.
Minimum Attendance Thresholds Enforcement
Given team minimum attendance threshold = T%, When projecting attendance for proposed times, Then any slot below T% is marked non-compliant and excluded from suggestions unless an authorized override is supplied. Given no available slot meets T%, When proposals are generated, Then the system recommends pause or pre-load actions per policy with explicit rationale. Given RSVPs update attendance, When projected attendance drops below T% before start, Then the organizer is alerted with policy-compliant options (cancel, rebook, proceed) and the chosen action is logged.
Admin Override of Heuristics with RBAC
Given a Team Admin requests to override a proposal outcome, When justification and an expiration date/time are provided, Then the override is applied until expiry and recorded with user ID, timestamp, scope, and reason. Given a Member (non-admin) attempts to change policy or apply an override, When the action is attempted, Then access is denied with a 403-equivalent message and no state change occurs. Given an override expires, When the expiry time passes, Then default heuristics resume automatically and stakeholders are notified of the reversion. Given roles (Org Admin, Team Admin, Member), When loading the policy UI and APIs, Then controls and endpoints are permitted only per role and all unauthorized requests are rejected server-side.
Compliance Log Export and Auditability
Given an Org Admin requests an audit export for a date range, When selecting CSV or JSON and filters (teams, actions, users), Then the export includes policy changes, overrides, proposals, approvals, and consent events with timestamps, actor IDs, IP, and before/after values. Given export size ≤ 100k records, When the export is requested, Then it completes within 30 seconds and is available for download with a checksum for integrity verification. Given retention policy = 24 months, When exporting beyond retention, Then only available records are included and a truncation notice is provided. Given a verifier computes the checksum on download, When compared with the provided checksum, Then the values match indicating export integrity.

Client Holiday Sync

For external meetings, infers customer holidays from domain, locale, and meeting region signals or via optional ICS import. Proposals automatically avoid culturally sensitive days and half‑days, improving show‑rates and demonstrating respect for customers’ local norms.

Requirements

Holiday Source Aggregation & Normalization
"As a remote product manager scheduling client calls, I want TimeMeld to automatically know which days in my client’s region are holidays or half-days so that my proposed times never fall on culturally sensitive dates."
Description

Aggregate public holiday data from multiple trusted sources (country/region calendars, cultural observance datasets, and vendor APIs) and normalize them into a canonical "observance window" model that supports full days, half-days, regional exceptions, and effective-dated corrections. Implement de-duplication and precedence rules across sources, cache results with scheduled refresh, and expose an internal API for the scheduling engine. This ensures TimeMeld has accurate, up-to-date holiday windows to avoid in external meeting proposals and integrates seamlessly with existing proposal generation flows.

Acceptance Criteria
Source Merge With Precedence and De-duplication
Given three holiday sources with precedence VendorAPI > CountryCalendar > CulturalDataset And all three provide a US-wide full-day holiday on 2025-07-04 with similar names When the aggregation job runs for region=US and date=2025-07-04 Then exactly one canonical observance window exists for region=US and date=2025-07-04 And canonical.source_of_truth = "VendorAPI" And canonical.source_ids contains the identifiers from all contributing sources And canonical.display_name is set from the highest-precedence source value And no duplicate windows remain for the same region and date Given two sources supply overlapping windows for the same holiday where one is US-wide and another is US-CA only When the higher-precedence source is US-CA only Then the canonical region scope equals US-CA (the higher-precedence scope) Given two entries with name variants that normalize to the same key (e.g., "US Independence Day" vs "Independence Day") And their local date ranges and regions overlap When aggregation runs Then they are merged into one canonical window
Canonical Observance Window Model Expressiveness
Given a full-day holiday in GB on 2025-12-25 When normalized Then the window has type=full_day, start=2025-12-25T00:00:00+00:00, end=2025-12-26T00:00:00+00:00, region_code="GB" Given a half-day afternoon holiday in DE-BY on 2025-12-24 When normalized Then the window has type=half_day, start=2025-12-24T12:00:00+01:00, end=2025-12-24T24:00:00+01:00, region_code="DE-BY" Given a country-level holiday in AU with a regional exception where AU-QLD does not observe When normalized Then the model contains an exclusion for region_code="AU-QLD" And API queries for AU-QLD on that date return zero windows while other AU regions return one Given a holiday with a weekend observation shift (falls on Sunday, observed Monday) When normalized Then the model represents the observed window on Monday with observed_shift=true and links to the nominal date
Effective-Dated Corrections and Versioning
Given a canonical window exists for JP on 2026-02-11 version=1 And a correction arrives moving observance to 2026-02-12 with effective_from=2025-10-01T00:00:00Z and reason="Government decree" When the correction is applied after 2025-10-01T00:00:00Z Then the canonical window for queries executed at or after effective_from is version=2 with start/end on 2026-02-12 local And the superseded version remains queryable in audit logs for at least 12 months And the change is recorded with actor, timestamp, reason, old_value, new_value And cache entries for affected keys are invalidated within 60 seconds of correction commit
Timezone Normalization and Boundary Handling
Given a half-day morning holiday in NZ on 2025-04-03 (DST in effect if applicable) When normalized Then start and end reflect local wall time with correct DST offset for region_code="NZ" Given a query window 2025-12-24T22:00:00Z to 2025-12-26T02:00:00Z for region_code="NZ" When the API is called Then the response includes the 2025-12-25 full-day observance expressed with ISO-8601 timestamps and correct UTC offsets Given a country spans multiple time zones and only a country code is requested (e.g., US) When the API is called for a range containing a holiday Then the response contains windows at the most specific known sub-region granularity (e.g., US-CA, US-NY) rather than a single ambiguous country-level time span
Caching, Refresh, and Stale-While-Revalidate
Given holidays are cached per (region_code, date_range) key for fast lookup When the cache is warm Then P95 API latency for a 1-month range and up to 50 regions is <= 200 ms Given a scheduled refresh runs daily at 03:00 UTC When sources are reachable Then the cache is refreshed for a rolling horizon of 24 months forward and 3 months back without increasing error rates above baseline Given an upstream source returns 5xx When the cache contains prior data Then stale data may be served for up to 72 hours with a stale=true flag in metadata while a background revalidation is attempted Given multiple concurrent misses for the same key When a refresh is in progress Then only one refresh is executed and others await or receive stale data (cache stampede prevention) Given a correction is applied to any window When committed Then affected cache keys are invalidated within 60 seconds and subsequent calls return corrected data
Internal API Contract for Observance Windows
Given the scheduling engine calls GET /internal/observance-windows with params start, end (ISO-8601), and regions (list of ISO-3166-1 alpha-2 or ISO-3166-2 codes) When the request is valid and within a range <= 36 months Then the API responds 200 with a JSON array of windows sorted by start asc containing fields [id, name, region_code, type, start, end, observed_shift, sources, version, last_updated] Given invalid params (missing start/end, malformed ISO-8601, unknown region codes, or range > 36 months) When the API is called Then the API responds 400 with a machine-readable error code and message Given a cache hit When the API is called Then P95 latency is <= 200 ms and P99 <= 500 ms for up to 50 regions and a 1-month range Given the query includes the optional filter half_days=exclude When the API is called Then only full_day windows are returned Given the query includes the optional param include_metadata=true When the API is called Then each window includes sources with [source_name, source_id, precedence] and a merged=true flag if de-duplication occurred
Resilience, Data Quality Monitoring, and Alerts
Given any source ingestion job fails or exceeds a freshness threshold (no successful pull for >24 hours) When monitoring evaluates the system Then an alert is generated to on-call with source identifiers and impacted regions Given more than 20% of regions for any source are stale (>24 hours) or the aggregation pipeline errors exceed 5% in a 1-hour window When monitoring evaluates Then a high-severity alert is generated and a runbook link is included Given malformed or conflicting source records are detected When aggregation runs Then offending records are sent to a dead-letter queue with reason codes and do not block successful records Given partial source outages occur When the API is called Then the response includes an x-holiday-staleness header per region with last_refresh_age seconds for any region exceeding 24 hours and a warnings array in the body when include_metadata=true
Domain & Locale Inference Engine
"As a solutions engineer meeting with a global customer, I want TimeMeld to infer the client’s locale from available signals so that holiday awareness works even when I don’t know their exact regional calendar."
Description

Infer a client’s likely country/region and locale by combining signals from participant email domains, participant time zones, declared meeting region, and optional CRM/account metadata. Compute a confidence score and provide fallbacks (e.g., per-invitee locale confirmation) when confidence is low. Support multi-national organizations by mapping domains to multiple locales and choosing the best fit based on attendee distribution. Expose a service endpoint consumed by the proposal generator and persist only minimal, privacy-preserving metadata needed for scheduling.

Acceptance Criteria
High-Confidence Locale Inference from Consistent Signals
Given an input payload where at least two invitees share the same corporate domain and all invitee time zones map to the same country and the CRM account country matches that country and a meeting region is declared consistent with that country When the inference endpoint is called Then the service returns HTTP 200 with per-invitee locale codes in ISO 639-1/3166-1 format and an organization_suggested_locale equal to that country And the confidence_score is >= 0.85 And the response includes signal_sources listing domain, time_zone, meeting_region, and crm_account And p95 latency is <= 300 ms under 50 rps in staging load tests
Ambiguous Domain Resolves by Attendee Distribution
Given a domain mapped to multiple locales in the knowledge base and invitees’ time zones span at least two countries and the majority of invitees map to Locale A When the inference endpoint is called Then organization_suggested_locale is Locale A And confidence_score is between 0.50 and 0.84 inclusive And invitees mapped to non-majority locales are returned with confirmation_required = true And the response lists alternatives with scores for at least the top two locales
Low-Confidence Triggers Per-Invitee Confirmation
Given any invitee has a free-email domain (e.g., gmail.com, yahoo.com) or missing/invalid time zone or conflicting signals such that computed confidence_score < 0.50 When the inference endpoint is called Then each affected invitee is marked confirmation_required = true with a suggested default derived from meeting_region if present And the response includes confirmation_token and expires_at for each required confirmation And the proposal generator integration flag block_finalization = true until confirmations or a manual override is received And no persistent record is written beyond a short-lived (<= 24h) confirmation state
Privacy-Preserving Persistence and Retention Controls
Given inference persists metadata When storing any record Then only a salted hash of domain, locale code, signal weights, and timestamps are stored; no full email, IP, or raw time zone strings And data retention TTL defaults to 90 days and is configurable per account And a DELETE by account_id purges all related records within 24 hours And all logs redact email-like strings and IP addresses
Tie-Break Using Declared Meeting Region
Given attendee distribution across locales is a tie and a meeting region is provided When the inference endpoint is called Then organization_suggested_locale equals the declared meeting region locale And confidence_score is set between 0.50 and 0.70 And all invitees not matching the chosen locale are flagged for confirmation
Service Endpoint Contract and Reliability
Given a POST to /inference/v1/locale with a payload containing invitees[email, timezone], meeting_region, and optional crm_account_id When the payload is valid Then the service returns HTTP 200 with a schema including per_invitee[{email_hash, locale, confidence, confirmation_required}], organization_suggested_locale, alternatives, and correlation_id And requests including an Idempotency-Key header are processed idempotently for 24 hours And invalid payloads return HTTP 400 with error codes; rate limits return 429 with standard headers And p95 latency <= 400 ms and p99 <= 800 ms under 100 rps in performance tests
Explainability and Audit Trace
Given an inference result is produced When fetching the response Then it includes top_3_signal_contributions with weights that sum to <= 1.0 and a human-readable explanation string And every response includes a correlation_id that can retrieve a redacted audit trace for seven days And audit logs contain no PII and pass automated redaction checks with zero known false negatives
Proposal Generator Holiday Filter
"As an operations lead coordinating cross‑regional reviews, I want proposals to automatically exclude holidays and half-days for all participants so that I don’t accidentally suggest unworkable times."
Description

Extend the proposal generation algorithm to apply holiday and half-day exclusion windows per attendee locale before scoring and ranking meeting times. Support mixed-region meetings by intelligently merging windows (e.g., union of hard conflicts, downweight for minor observances), align half-day observances to local business hours, and ensure no hard conflicts appear in proposed slots. Provide guardrails when no valid options exist by automatically suggesting alternative weeks or asynchronous alternatives, and return structured explanations for the UI.

Acceptance Criteria
Exclude Hard Holidays per Locale Before Scoring
Given a meeting request with multiple attendees across different locales and time zones When the proposal generator computes candidate time slots Then it must exclude any slot that overlaps any attendee’s full-day hard holiday window as determined in that attendee’s local time And it must exclude any slot that overlaps ICS events classified as Holiday/OOO/Unavailable for any attendee And exclusions must be applied before any scoring or ranking occurs And zero proposed slots may overlap a hard holiday or ICS hard block for any attendee
Mixed-Region Merging: Union of Hard Conflicts and Downweighting Minor Observances
Given attendees from multiple regions with a mixture of hard holidays and minor/cultural observances When generating and scoring candidate slots Then the union of all hard-conflict windows across attendees is excluded from consideration And minor observances do not exclude slots but apply a configurable penalty weight (w_minor) to the slot score for each affected attendee And when two slots have equal base score, the slot intersecting fewer minor observances ranks higher And if at least one valid slot exists that intersects no minor observance, at least one such slot appears in the top 5 proposals
Half-Day Observances Aligned to Local Business Hours
Given an attendee has a half-day observance on date D When computing exclusions for D Then the excluded window must align to that attendee’s local business hours per locale rule (e.g., afternoon-only blocks from local 12:00 to business close, morning-only blocks from business open to 12:00), or to explicit hours from ICS when provided And any candidate slot overlapping an attendee’s half-day excluded window is removed before scoring And for mixed-region meetings, a slot is valid only if it avoids the half-day excluded window for all attendees once converted into each attendee’s local time
ICS Holiday Import Overrides Inference and Respects Time Zones
Given an external attendee supplies an ICS feed with holidays/OOO When ICS-derived events conflict with inferred holidays or locale defaults Then ICS events take precedence for determining exclusion windows and half-day hours And ICS RRULE expansions and VTIMEZONE data must be honored so that local times are correctly interpreted across DST transitions And duplicate holidays detected in both ICS and inference are de-duplicated without double-penalizing or double-excluding And if ICS parsing fails, inference is used and a machine-readable reason "ics_parse_error" is attached to the response without crashing proposal generation
Guardrails When No Valid Options Exist
Given the union of hard exclusions results in zero valid candidate slots within the requested planning window When the proposal generator completes Then it must return zero proposals and include at least two suggested alternative week ranges (ISO 8601 start/end) that contain valid capacity based on current constraints And it must include at least one asynchronous alternative suggestion with a reason code (e.g., "try_async_update") And it must include a machine-readable reason code "no_valid_options" plus a per-attendee blocking summary (attendee_id, count_by_reason) And the API response status remains 200 with an empty proposals array and populated guardrails payload
Structured Explanations for UI and Auditing
Given proposals are generated with exclusions and penalties applied When returning the API response Then each proposed slot includes an explanations array with entries containing: code (enum: excluded_by_holiday, excluded_by_half_day, downweighted_by_minor_observance, none), source (enum: inferred, ics), affected_attendee_ids, locale_or_region, tz, and weight (for penalties) And the response meta includes an exclusions_summary with counts by reason and by attendee And the payload declares schema_version "holiday_explanations.v1" and validates against the published JSON Schema And for any slot impacted by a minor observance, the explanation includes the observance name and the exact penalty weight applied
Client ICS Import & Sync
"As an account manager with named enterprise accounts, I want to link the client’s official holiday calendar so that TimeMeld respects their exact observances without me manually tracking them."
Description

Offer an optional path to subscribe to client-provided holiday calendars via ICS/CalDAV URL or OAuth connections (Google/Microsoft). Parse RRULE, EXDATE, and TZID correctly, handle updates and cancellations, and auto-refresh on a schedule. Scope subscriptions per contact, account, or domain with explicit consent, deduplicate against public sources, and provide robust error handling and fallbacks when feeds are unreachable. This supplements inference with authoritative client-specific calendars to improve accuracy.

Acceptance Criteria
Manual ICS/CalDAV URL Subscription with Scoped Consent
Given a valid ICS/CalDAV URL and the user selects scope (Contact, Account, or Domain) and checks an explicit consent box, When the user clicks Subscribe, Then the subscription is saved with the chosen scope and consent timestamp/auditor recorded. Given the subscription is saved, When the initial fetch runs, Then events within the next 18 months are imported and stored with preserved UID, TZID, DTSTART/DTEND, SUMMARY, RRULE, and EXDATE where present. Given imported events contain all‑day and partial‑day entries, When proposals are generated for meetings involving the scoped client, Then proposed windows exclude times that overlap the event intervals in the event’s local TZ (all‑day blocks the full day; partial‑day blocks the overlapping interval). Given a malformed or unreachable ICS URL, When Subscribe is attempted, Then the user sees a validation error without creating a subscription and no network call is persisted as active.
OAuth-Based Holiday Calendar Subscription (Google/Microsoft) with Calendar Selection
Given the user initiates Google/Microsoft OAuth, When consent is granted with read‑only calendar access, Then a refresh/access token is stored securely and linked to the user and target scope (Contact/Account/Domain). Given multiple calendars are available, When the user selects one or more calendars to subscribe, Then only the selected calendars are synced and labeled with their source (Google/Microsoft) and scope. Given OAuth setup completes, When initial sync runs, Then holiday events for the next 18 months are imported and meeting proposals for the scoped client avoid those dates/times. Given OAuth is declined or scopes are insufficient, When setup completes, Then no subscription is created and the user is shown a clear failure message with retry option.
Recurrence Rules, Exceptions, and Timezone Fidelity
Given an event with RRULE (e.g., yearly on 01-01) and TZID=Region/City, When occurrences are expanded for the planning window, Then each occurrence is computed in the event’s TZID and respects DST transitions. Given an event with EXDATEs specified, When expansion occurs, Then the listed dates/times are excluded from the generated occurrences. Given an all‑day event defined via DTSTART;VALUE=DATE and DTEND;VALUE=DATE, When stored, Then it blocks the entire local calendar date(s) for the event TZ. Given a partial‑day holiday (e.g., 13:00–17:00 local time), When proposals are generated, Then only meeting windows overlapping that local interval are excluded, and non‑overlapping windows the same day remain eligible.
Continuous Sync: Auto-Refresh, Updates, and Cancellations
Given an active subscription, When 24 hours elapse since last successful sync, Then the system refreshes the feed using ETag/If‑Modified‑Since where supported and jittered scheduling (±1 hour) to avoid thundering herds. Given the source feed adds or modifies events, When the next refresh completes, Then new/changed events are reflected within 5 minutes of sync completion and existing proposals are recalculated accordingly. Given the source feed cancels an event (UID removed or STATUS:CANCELLED), When the next refresh completes, Then the corresponding event is removed from consideration and future proposals no longer exclude that time. Given repeated refreshes with unchanged content, When sync runs, Then processing is idempotent and no duplicate events are created.
Deduplication Across Sources and Precedence Rules
Given the same holiday exists in both a client‑provided subscription and a public/inferred source for the same date/time, When building the exclusion set, Then the client‑provided event takes precedence and is kept while the public/inferred duplicate is suppressed. Given multiple client subscriptions overlap (Contact, Account, Domain), When duplicates are detected by matching UID or by normalized key {local date range, normalized summary, TZ}, Then only one exclusion is applied with precedence Contact > Account > Domain. Given near‑duplicates differ slightly in SUMMARY casing or whitespace, When normalization runs, Then they are deduplicated if times and TZ match. Given deduplication occurs, When proposals are generated, Then each date/time window is excluded at most once (no over‑blocking).
Error Handling and Fallback When Feeds Are Unreachable
Given a subscription fetch returns 4xx/5xx or times out after 15 seconds, When sync runs, Then the subscription health is set to Unhealthy with the error code and next retry scheduled with exponential backoff up to 24 hours. Given a subscription is Unhealthy, When proposals are generated, Then the system falls back to public/inferred holidays for that scope and does not use stale client events older than 7 days. Given a feed recovers on a subsequent attempt, When sync succeeds, Then health returns to Healthy, backoff resets, and proposals again consider the client‑provided events. Given persistent failures for 14 consecutive days, When policy enforcement runs, Then owners are notified and the subscription is paused until manually resumed.
Consent Revocation, Token Revocation, and Data Deletion
Given a user with manage permissions opens a subscription, When they click Revoke Consent, Then OAuth tokens (if any) are revoked, ICS URLs are disconnected, and the subscription status becomes Revoked. Given consent is revoked, When cleanup runs, Then all cached client‑provided events for that subscription are purged within 15 minutes and removed from exclusion logic. Given consent is revoked, When proposals are generated afterwards, Then only public/inferred holidays apply for that scope. Given revocation completes, When audit logs are viewed, Then an entry shows who revoked, when, which scope, and which data was purged.
Explainability & Overrides UI
"As a product manager preparing executive briefings, I want to see which dates were excluded and why, and optionally override minor observances, so that I can balance respect for norms with tight deadlines."
Description

In the proposal composer and review views, show why specific dates/times were excluded (holiday name, region, source, and confidence) and allow per-meeting controls to include or downweight minor observances or half-day windows when appropriate. Provide a "request exception" note option to share context with the client and log any overrides to an audit trail. This transparency builds trust, enables informed adjustments, and helps teams handle edge cases without disabling protections.

Acceptance Criteria
Show Exclusion Reasons in Composer and Review
Given a meeting with excluded time slots due to detected holidays, When the user opens the Proposal Composer or Review view, Then each excluded slot shows: holiday/festival name, region/locale (ISO code), source type (Inferred: domain/locale/region or ICS import), and confidence as a 0–100% value. And the reason is available inline and via a "Why excluded?" icon tooltip, and is screen-reader readable. And where multiple signals exist, Then the primary reason is shown with a "+N more" indicator that expands to list all contributing signals with individual confidences. And explanations render within 1 second after the view loads or slots refresh.
Source Detail Fidelity (Inferred vs ICS)
Given an exclusion sourced from an ICS import, When the user inspects the reason, Then the source displays "ICS" with calendar name (if available) and the ICS event summary, and provides a link to view event details. Given an exclusion based on inferred signals, When inspected, Then the source displays "Inferred" and lists contributing signals (email domain, attendee locales, meeting region) with weights, and the displayed confidence matches the model output within ±1%. Given both ICS and inferred evidence exist for the same date, Then ICS is labeled as the primary source and inference listed as secondary contributors.
Per-Meeting Minor Observance Controls
Given a meeting with potential minor observances, When the organizer opens Holiday Sensitivity controls, Then options include: Exclude (default), Downweight 25%, Downweight 50%, Downweight 75%, Include. When the organizer changes this setting, Then proposed windows recompute and the slot scoring reflects the change within 3 seconds without page reload. And the chosen setting persists to the meeting record and is restored on revisit and in shared review links.
Half-Day Window Overrides
Given a region-marked half-day holiday on a date, When the organizer enables "Allow morning only" or "Allow afternoon only", Then proposed windows on that date include only times within the selected half relative to the region's local time. When "Allow full day (exception)" is selected, Then previously excluded times on that date become eligible and are marked with an "exception requested" badge. If multiple attendee regions have different half-day definitions, Then the stricter window is applied unless a per-region override is explicitly set.
Request Exception Note Flow
Given the organizer includes a slot that violates a holiday rule, When they proceed to send proposals, Then a modal prompts for a "request exception" note (required 10–500 characters) with preview. When sent, Then the note is appended to outbound proposal emails and calendar invite descriptions, and is visible to internal participants in the thread UI. And the note, author, timestamp, and associated override IDs are stored and linked in the meeting's audit trail. If the organizer cancels sending, Then no note is stored and overrides revert unless explicitly saved.
Audit Trail for Overrides
Given any change to holiday sensitivity, half-day overrides, inclusion of excluded slots, or exception notes, When the change is saved, Then an immutable audit entry is created with: meeting ID, actor ID, timestamp (UTC ISO 8601), setting name, previous value, new value, affected date-times (ISO), client domain(s), and optional note ID. Audit entries are visible in the meeting Audit tab within 2 seconds of change and are exportable to CSV for a selected date range. Attempts to edit or delete audit entries are blocked; any rollback action generates a new compensating entry.
Permissions and Validation Guardrails
Given a user without organizer role or "Schedule Override" permission, When viewing the Proposal Composer or Review view, Then override controls are disabled with a tooltip explaining required permission, and API attempts return 403 without side effects. Given an override would propose times outside the organizer's defined working hours, When the user attempts to save, Then a confirmation dialog appears summarizing the impact; proceeding records the confirmation in the audit trail; cancelling leaves settings unchanged. All validations return user-facing errors within 500 ms and are localized to the interface language.
Privacy, Compliance & Retention Controls
"As a security-conscious ops leader, I want strong privacy controls and transparent data handling for holiday inference and imports so that our client data is protected and compliant with company policies."
Description

Implement privacy-first handling of all inference signals and imported calendars: minimize stored PII, encrypt data at rest and in transit, record granular consent, and provide admin settings for retention windows and feature opt-outs. Support user-triggered export/delete, maintain audit logs for access and overrides, and document data flows to support compliance readiness (e.g., SOC 2, GDPR). Ensure clear in-product disclosures when enabling ICS imports and domain-based inference.

Acceptance Criteria
PII Minimization for Client Holiday Sync Inputs
Given Client Holiday Sync processes domain, locale, and region signals or an imported ICS file When parsing and persisting inference inputs Then the system stores only allowlisted fields: domain_hash, locale_code (ISO 639-1), region_code (ISO 3166-1 alpha-2), holiday_calendar_key, consent_record_id, created_at, updated_at And the system does not store raw emails, attendee names, event titles/descriptions/locations, full ICS blobs, or IP addresses extracted from ICS files And the raw ICS file is deleted from transient storage within 15 minutes of successful processing And any derived cache entries contain no raw PII and are keyed by non-reversible IDs And attempts to persist a non-allowlisted field are rejected and do not log the field value
Encryption in Transit and at Rest for Holiday Sync Data
Given production or staging environments Then all network connections that transmit inference inputs, consent records, or derived holiday data enforce TLS 1.2+ with HSTS and PFS ciphers And all persisted allowlisted fields are encrypted at rest using KMS-managed AES-256 keys with rotation ≤ 90 days And backup snapshots and search indexes containing these fields are encrypted with the same KMS policy And service-to-service communication for these data paths uses mTLS with certificate rotation ≤ 24 hours And an operational health endpoint reports encryption_enabled=true and mTLS_enabled=true
Explicit Consent and In-Product Disclosures
Given a user attempts to enable ICS import or domain-based holiday inference for a workspace When the toggle is activated Then the user must view a disclosure describing data categories, purposes, retention, and subprocessors and explicitly check a consent box before enabling And a consent record is created capturing subject_user_id, scope (ics_import|domain_inference), policy_version, legal_basis, timestamp (UTC), and controller_org_id And the feature remains disabled until consent is recorded And when consent is withdrawn, processing stops within 5 minutes and previously stored inputs and derived data for that scope are purged within the configured retention SLA
Admin Retention Windows and Feature Opt-Outs
Given an org admin opens Privacy & Compliance settings When they configure retention windows for imported ICS artifacts and derived holiday inferences (e.g., 30/90/365 days) and save Then a purge job runs at least daily to delete records older than the configured windows and logs the count purged per data class And retention for audit logs is managed separately and is not shortened by these settings And when the admin disables ICS import and/or domain-based inference, new ingestion is blocked and existing scheduled jobs are cancelled within 5 minutes And while disabled, any API call to ingest ICS or infer by domain returns 403 and no data is stored
User Data Export and Deletion (GDPR/CCPA)
Given a user requests a data export for Client Holiday Sync Then a machine-readable export (JSON/CSV) is generated within 24 hours containing consent records, inference input metadata, derived holiday flags, and access events related to that user, with no raw ICS content And a secure download link is provided to the requester and expires after 7 days Given a user requests deletion Then all related records are deleted from primary storage within 24 hours and from caches within 15 minutes, backups are scheduled for purge per backup retention policy, and a confirmation receipt is issued And deletion is enforced with tombstoning to prevent re-creation from historical jobs or reprocessing
Audit Logging of Access and Overrides
Given any read or write access to Client Holiday Sync inputs, consent records, or derived inferences When the access or override occurs Then an audit event is appended recording actor_id, role, action, resource_type/id, fields_changed, lawful_basis, timestamp (UTC), source_ip, and user_agent And audit logs are append-only and tamper-evident via hash chaining, with daily integrity verification passing without gaps And authorized auditors can query logs by actor, subject, time range, or action, returning results within 5 seconds at the 95th percentile And audit log retention is configurable with a minimum of 365 days
Compliance Documentation and Data Flow Visibility
Given a release includes changes to Client Holiday Sync data handling When a pull request is merged Then the data flow diagram, data inventory/ROPA entry, and subprocessors list are updated and linked in the compliance portal before deployment And CI blocks deployment for missing documentation updates And the in-product disclosure modal links to the current documentation version And evidence artifacts (key management policy, access review results, purge job reports) are exportable as a SOC 2 evidence bundle on demand

Observance Sensitivity

Applies soft weighting for partial observances (e.g., religious evenings, half‑days, school breaks) instead of blanket blocks. Time windows shift earlier or later with clear impact scores, resulting in humane overlaps that boost attendance without unnecessary cancellations.

Requirements

Observance Data Model & Ingestion
"As a remote team member, I want my cultural or family observances recognized without blocking my whole day so that proposed meetings avoid my inconvenient periods while leaving flexible options."
Description

Create a canonical, region-aware data model for partial-day observances that supports public holiday APIs, religious calendars, school schedules, and user-imported ICS feeds. Normalize events into typed segments with attributes (category, start/end rules, partial-day windows, confidence), deduplicate across sources, and map users to relevant observances via locale, team affiliation, and self-declared preferences. Expose observance segments as soft-weight signals rather than hard blocks to the scheduling engine and UI, with daily refresh and change detection to keep data current.

Acceptance Criteria
Canonical Observance Segment Model Established
Given a raw event from a supported source, When normalized, Then an ObservanceSegment is stored with fields: id, category ∈ {public_holiday,religious,school,custom}, locale, source, start_rule (RFC5545), end_rule or duration, partial_day_windows[] (local_start, local_end, utc_offset), confidence ∈ [0.0,1.0], and provenance. Given a partial-day event with local hours (e.g., 17:00–20:00), When normalized, Then at least one partial_day_window exists and all times correctly account for DST transitions. Given an all-day event annotated as evening observance, When normalized, Then it yields a partial_day_window matching the annotated evening hours. Given invalid or missing required fields in the source event, When normalization runs, Then the event is rejected with a validation error and logged; no ObservanceSegment is stored.
Multi-Source Ingestion and Normalization Pipeline
Given configured connectors for a public holiday API, a religious calendar, a school schedule, and a user-provided ICS, When ingestion runs, Then events are fetched, parsed, and normalized into ObservanceSegments with ≥99% success rate over a 1,000-event sample per source. Given rate limits or transient HTTP failures, When retries are applied, Then exponential backoff with jitter is used and the job succeeds within 3 retries or records a retriable failure with error code and next-at timestamp. Given ICS feeds with timezone identifiers, When parsed, Then produced segments contain correct timezone and utc_offset data matching the Olson ID. Given the daily schedule, When the ingestion job runs, Then for 100k total events processing completes within 30 minutes end-to-end with p95 per-event parse time ≤50 ms.
Cross-Source Deduplication and Merge
Given two segments with time-window overlap ≥50% on the same date and matching category for the same locale or user, When deduplication runs, Then they merge into a single segment with confidence = max(confidence), provenance = union(sources), and source_priority resolving conflicts by user_custom > school > religious > public_holiday. Given segments that overlap <50%, When deduplication runs, Then they remain separate segments. Given identical segments from the same source, When deduplication runs, Then duplicates are collapsed by id without data loss. Given a merge operation, When persisted, Then an audit record captures input_ids, output_id, merge_reason, and timestamp.
User-to-Observance Mapping
Given users with locale, team affiliation, and self-declared preferences, When mapping runs, Then each user is associated with segments where (segment.locale matches user.locale OR segment is global) AND (segment.category is enabled in user preferences) AND (segment.team_scope matches user's team when present). Given a user opt-out for a specific observance or category, When mapping runs, Then corresponding segments are excluded for that user. Given ambiguous or missing locale for a user, When mapping runs, Then fallback applies in order: user.self_declared_locale → calendar_locale → team_default → org_default. Given a dataset of 10k users and 50k segments, When the mapping job executes, Then it completes within 5 minutes with peak memory usage ≤2 GB and produces a mapping accuracy ≥99% against a curated gold set.
Soft-Weight Signal Exposure to Engine and UI
Given active mapped segments for a user on a target day, When the scheduling engine scores candidate windows, Then windows inside partial_day_windows have their desirability reduced by the segment penalty and are not treated as hard blocks. Given two or more overlapping segments, When scoring, Then penalties combine via capped additive logic with a maximum total penalty of 0.8. Given a scored window returned via API, When inspected, Then the payload includes weight_details with segment_id, category, local_time_window, confidence, and applied_penalty. Given the UI time grid, When the user views the day, Then impact badges appear for affected windows with labels from segment.category and tooltips showing local start–end times.
Daily Refresh and Change Detection
Given new or changed source events, When the daily refresh runs at 02:00 UTC, Then added, modified, and deleted ObservanceSegments are detected by id or content hash and upserted/removed accordingly. Given a change to an ICS feed prior to the next daily run, When webhook notifications are received, Then incremental ingestion updates affected segments within 15 minutes end-to-end. Given any change, When versioning is applied, Then segment.version increments and downstream caches are invalidated within 5 minutes. Given a failed run, When monitoring evaluates, Then an alert is sent to on-call and the job retries up to 3 times; on final failure the run status is recorded as Fail with error details in the run log.
Partial-Day Boundary & Sunset/Sunrise Computation
"As an engineer who observes Friday evening rituals, I want TimeMeld to understand when my evening starts in my location so that meeting suggestions shift earlier that day without blocking the entire afternoon."
Description

Compute dynamic partial-day boundaries for observances that begin or end at civil or solar times (e.g., after sunset, Friday evenings, early dismissals). Implement timezone-aware astronomical calculations and regional rule sets, with fallbacks to user-provided windows. Persist computed boundaries per user-date and expose graded sensitivity segments (pre-observance wind-down, core observance, post-observance) to the scoring engine. Recompute on travel or timezone changes and handle DST transitions deterministically.

Acceptance Criteria
Accurate Sunset-Based Boundary Computation
- Given a user with resolved latitude/longitude and an observance that begins at sunset, when boundaries are computed for a specific local date, then the computed civil sunset timestamp is within ±2 minutes of the QA reference ephemeris for that location/date and is stored with the correct IANA timezone. - Given rule-defined offsets for pre/core/post (e.g., pre: −60m, core: +0m, post: +90m from sunset), when computation runs, then pre/core/post segment start/end times exactly reflect those offsets relative to the computed sunset. - Given a high-latitude date where sunset is not present, when computation runs, then the defined fallback (e.g., civil twilight or fixed local time) is applied and the boundary is persisted with source=rule_fallback and fallback_type recorded.
Regional Rule Application for Partial-Day Observances
- Given a user assigned to a region with an active partial-day rule (e.g., Friday evening observance), when computing boundaries, then the regional rule is applied with its precedence and constraints (earliest_start, latest_end, min_duration) and the persisted record includes rule_id and rule_version. - Given both regional and organization policy rules match the same date, when precedence is evaluated, then organization policy overrides regional unless the regional rule is explicitly additive, and the winning rule is recorded in metadata. - Given a date with no matching regional or org rule, when computation runs, then no rule-derived boundary is created and the system awaits user-provided windows (source remains unset).
Fallback to User-Provided Windows
- Given a user supplies a partial-day window for a specific date, when computation runs, then pre/core/post segments are derived from that window using the configured offsets and persisted with source=user_provided and a reference to the input window id. - Given both computed (astronomical/rule) boundaries and a user-provided override exist with policy=override, when computation runs, then the user-provided window fully replaces computed boundaries; with policy=merge, merge logic combines segments deterministically per documented order (user > org > regional > astronomical) and records merge_result. - Given invalid user input (e.g., end < start or missing timezone), when validation occurs, then the input is rejected with a specific error code, no boundary is updated, and the previous valid boundary (if any) remains active.
Persistence per User-Date with Sensitivity Segments
- Given boundaries are computed, when persisted, then exactly one record per user_id + local_date exists containing start/end for pre/core/post, source, inputs (lat, lon, tz, algorithm), rule identifiers, offsets, and a deterministic boundary_id (hash of user/date/inputs). - Given the same inputs are recomputed, when upsert runs, then the operation is idempotent: no changes to persisted times or boundary_id, and updated_at remains unchanged beyond allowed clock skew. - Given an API read for a single user-date, when requested, then the service returns the persisted segments and metadata within p95 ≤ 50 ms for cached reads and p95 ≤ 150 ms for cold reads.
Recomputation on Travel/Timezone Changes
- Given the user’s timezone or coordinates change, when the change is detected, then all boundaries for future dates within a configurable horizon (default 14 days) are recomputed within 60 seconds, and only records with changed times are updated and emit boundary_updated events. - Given recomputation near local midnight, when date boundaries are selected, then the user’s local calendar date (not UTC date) determines which user-date records are recomputed. - Given inputs did not materially change (same tz, same coords), when a recomputation job runs, then no boundary records are modified and no events are emitted (no-ops).
Deterministic Handling Across DST Transitions
- Given a date on which DST starts (spring forward), when segments are computed, then pre/core/post do not overlap or collapse; each segment is persisted with unambiguous UTC instants and the correct post-shift offset. - Given a date on which DST ends (fall back), when segments cross the repeated hour, then both occurrences are mapped to unique UTC instants; retrieval shows correct local times with disambiguation via offset. - Given the same inputs are processed across deployments, when recomputing any DST date, then outputs (segment instants and metadata) are identical to prior results (deterministic) and a content hash matches the previously stored value.
Weighted Impact Scores Exposed to Scoring Engine
- Given pre/core/post segments exist, when the scoring engine requests impact for a candidate slot, then the returned weights apply configured penalties (e.g., core=High, pre=Medium, post=Low, outside=None) and include the segment label used in scoring. - Given a proposed meeting window overlaps any segment, when suggestions are generated, then the system shifts the window earlier/later to minimize total weighted penalty and returns the delta impact and rationale in the suggestion payload. - Given a day without boundaries, when scoring is requested, then neutral (no penalty) scores are returned and no shifts are applied.
Soft-Weight Scoring Engine Integration
"As a product manager scheduling cross-functional syncs, I want slot scores to reflect teammates’ partial observances so that I can pick humane overlaps that maximize attendance."
Description

Extend the slot scoring model to apply soft penalties during observance segments, combining them with existing timezone ergonomics, equity rotation, and availability inputs to produce a composite comfort score per window. Provide explainable scores with component breakdowns and tunable ceilings so high-priority meetings can still be scheduled when necessary. Add guardrails to avoid repeatedly assigning low-comfort slots to the same participant and ensure deterministic results for identical inputs.

Acceptance Criteria
Composite Comfort Score with Soft Observance Penalties
- Given a 60‑minute candidate window where one required participant overlaps a 30‑minute partial observance, When the engine scores the window with defaults (observanceWeight=30, observancePenaltyCeiling=20), Then the window’s total score decreases by 15 (±1) versus the same window with no overlap, and the observancePenalty component equals 15. - Given a candidate window with 0% observance overlap for all required participants, When the engine scores the window, Then the observancePenalty component equals 0 and the total score equals the sum of other components within ±1. - Given two windows identical except observance overlap ratios of 25% and 75% for the same participant, When scored with the same config, Then the higher‑overlap window has a strictly lower total score by at least 10 points (±1) and not more than the configured ceiling difference (≤20).
Explainable Scoring Breakdown (API and UI)
- Given a scoring API request for N candidate windows, When it returns, Then each window object contains: windowId, startTime, endTime, totalScore (0–100), components=["ergonomics","availability","equity","observancePenalty","priorityModifier"] with numeric values whose sum equals totalScore within ±1, and perParticipant=[{participantId, personalComfort (0–100), observanceOverlapMinutes}]. - Given a window with observance overlap for participant "Alice" labeled "Shabbat evening", When the breakdown is requested via API or UI, Then the observancePenalty component includes a rationale that names "Alice" and "Shabbat evening" and quantifies overlap minutes. - Given two identical scoring requests, When executed twice, Then the breakdown order of components, perParticipant entries, and their values are identical and stable.
Tunable Penalty Ceilings and Priority Overrides
- Given org config observancePenalty.ceiling default 20 (allowed range 0–50) and meeting priority in {normal, high, urgent}, When scoring, Then the effective observance penalty is min(observanceWeight*overlapRatio, ceiling) multiplied by a priority factor {1.0, 0.5, 0.0} respectively. - Given the same window and inputs except priority normal vs high vs urgent, When scored, Then totalScore(urgent) ≥ totalScore(high) ≥ totalScore(normal) and all totals are within 0–100. - Given ceiling set to 0, When scored, Then observancePenalty equals 0 and no candidate window is filtered due to observance.
Low-Comfort Guardrails and Rotation Fairness
- Given tracking of the last 5 scheduled meetings per team, When a participant has 2 consecutive meetings where their perParticipant.personalComfort < 40, Then on the next scheduling run the engine applies an additional +10 penalty to any candidate window that would give that participant personalComfort < 40 unless all candidates violate this threshold. - Given two candidate windows within 5 points of each other, and the higher‑scored window would produce a third consecutive perParticipant.personalComfort < 40 for participant P while the lower‑scored window would not, When selecting the top window, Then the engine selects the lower‑scored window to avoid repetition. - Given a series of 10 schedules under similar constraints, When evaluated, Then no participant is assigned more than 1 low‑comfort (<40) slot consecutively unless no feasible alternative exists in that run.
Deterministic, Stable Scoring and Selection
- Given identical inputs (participants, calendars, observance definitions, configuration, time horizon, tie‑break seed="default"), When scoring and selecting the top K windows twice, Then the API responses are byte‑identical including window order and component values. - Given two windows with equal totalScore, When ordered, Then they are sorted by ascending startTime then ascending windowId. - Given parallel execution with concurrency > 1, When compared to single‑threaded execution, Then the set and order of window scores are identical.
Partial Observance Handling without Blanket Blocking
- Given a candidate window that partially overlaps an observance for at least one participant, When scoring, Then the window is included in the results and its observancePenalty is proportional to the overlap ratio computed in each participant’s local time and aggregated across participants as a weighted mean (required=1.0, optional=0.5). - Given a 60‑minute window where Bob has 30 minutes overlap, with defaults observanceWeight=30 and ceiling=20, When scored, Then the observancePenalty contribution from Bob equals 15 and the aggregated penalty equals 15 if Bob is the only required attendee overlapping. - Given two windows whose start times differ by 5 minutes around an observance boundary, When scored, Then the absolute difference in observancePenalty is ≤ ceiling*0.1 (e.g., ≤2 with default ceiling 20), ensuring a smooth transition.
Participant Preferences, Privacy & Overrides
"As a participant, I want control over how my observances influence scheduling and what is shown to others so that my privacy is respected while still improving meeting times."
Description

Offer per-user controls to opt in/out, declare or import observances, set discretion levels, and temporarily override weights for specific dates or meetings. Minimize sensitive data storage and surface only anonymized impact hints to organizers unless explicit consent is given. Provide quick one-click responses in invite flows (e.g., “Okay to schedule,” “Prefer earlier,” “Prefer later”) that adjust weights for the specific meeting while preserving global settings.

Acceptance Criteria
Opt-In/Out and Discretion Levels for Observances
Given a user opens Settings > Preferences > Observances When they toggle Observance Sensitivity to On Then partial-observance weighting is applied to that user’s availability within 60 seconds for new proposals and existing drafts are rescored And the setting persists across sessions and devices When they toggle Observance Sensitivity to Off Then observance-based weights are excluded within 60 seconds and existing drafts are rescored When they set Discretion Level to Private Then no individual labels or hints are shown anywhere to organizers; only cohort-level aggregates subject to k≥3 When they set Discretion Level to Anonymized Then organizers see only aggregated impact hints without identifying individuals When they set Discretion Level to Share with organizer Then the organizer can see this participant’s observance name/category and affected windows for relevant meetings And an audit log entry is recorded for each change with user, old value, new value, timestamp
Import Observances with Minimal Storage
Given a user connects an external calendar (Google or Outlook) and opts to import observances When the import runs Then TimeMeld stores only start time, end time, timezone offset, and normalized category for observance windows And TimeMeld does not store event title, description, attendees, or location from the source calendar And access tokens are stored encrypted at rest and scoped to read-only free/busy or observance metadata And a consent screen lists data fields to be stored and requires explicit confirmation before first import When the user disconnects the external calendar Then tokens are revoked with the provider and deleted from TimeMeld within 60 seconds And previously imported observance windows remain only as normalized windows without source metadata And newly created proposals are rescored within 60 seconds of import completion
Anonymized Impact Hints to Organizers
Given an organizer drafts a meeting with participants who have Observance Sensitivity enabled at Private or Anonymized levels When candidate windows overlap participants’ observance windows Then the organizer sees only aggregated impact hints (e.g., Impact: Low/Medium/High, Shift: earlier/later suggestion) without any participant identity And no observance names or categories are displayed unless the participant’s Discretion Level is Share with organizer And aggregated hints are shown only when at least 3 participants contribute to the aggregate (k-anonymity ≥ 3); otherwise show “insufficient data” And no per-participant observance data is persisted to the meeting record unless consent is Share with organizer And unit tests verify no PII fields (names, specific observance titles) appear in organizer surfaces under Private/Anonymized settings
One-Click Invite Responses Adjust Meeting-Specific Weights
Given an invite includes one-click actions: Okay to schedule, Prefer earlier, Prefer later When a participant clicks Okay to schedule Then no meeting-specific weight adjustment is applied for that participant and global settings remain unchanged When a participant clicks Prefer earlier or Prefer later Then a meeting-specific weight delta is applied only to that meeting’s scoring for that participant within 30 seconds And the participant’s global preferences and discretion level remain unchanged And the organizer sees only aggregated counts of responses (e.g., 2 prefer earlier) unless participants have Share with organizer consent And if multiple responses are submitted by the same participant, the most recent response supersedes prior ones And meeting-specific responses expire when the meeting is scheduled or canceled And an acknowledgement is displayed to the participant confirming the applied preference
Temporary Per-Date or Per-Meeting Overrides
Given a participant creates a temporary override (e.g., mark 2025-09-15 16:00–20:00 as Avoid or Okay) via their Preferences or via the invite flow When scheduling evaluates windows intersecting the override Then weights are adjusted according to the override only for the specified date range or target meeting And the override requires start time, end time, and type (Avoid/Favor) and rejects invalid ranges And overrides can be edited or canceled by the participant and changes take effect within 60 seconds And overrides auto-expire at the specified end time and no longer influence future scoring And an audit log captures create/update/delete with user, scope (date or meeting), and timestamp
Explicit Consent to Share Observance Details
Given a participant attempts to share observance details with an organizer When prompted with a consent dialog Then the dialog lists exactly what will be shared (observance name/category, affected windows) and with whom (organizer of specified meeting) And the default is opt-out (unchecked) And consent can be granted per-meeting or globally and is recorded with scope and timestamp And withdrawal of consent immediately removes per-person observance details from organizer surfaces for future views and rescoring And historical audit logs retain only consent events and not the sensitive observance content And tests verify that organizer views show per-person details only when consent scope matches the meeting
Impact Visualization in Slot Picker
"As a meeting organizer, I want to quickly see how observances affect each proposed time so that I can choose higher-comfort slots without guesswork."
Description

Enhance the slot picker with clear, non-intrusive indicators of observance impact: color-graded comfort bars, badges, and tooltips explaining the rationale behind scores. Offer earlier/later nudges and auto-generated alternative windows with higher comfort scores. Ensure accessibility compliance, responsive behavior across devices, and consistent rendering in calendar add-ons and embedded views.

Acceptance Criteria
Comfort Bar Displays Impact Scores Clearly
- Given the slot picker lists suggested times for attendees with partial observances, When the list renders, Then each slot displays a comfort bar with a numeric score from 0 to 100 that matches the computed comfort value within ±1. - Given defined score bands, When a slot score is 0–39, 40–69, or 70–100, Then the bar uses the Low/Medium/High color token respectively and maintains a contrast ratio ≥ 4.5:1 against the background. - Given accessibility requirements, When color is used to convey comfort, Then the bar also includes a pattern/icon indicator so information is not color-only. - Given a user hovers, focuses, or taps a slot, When the interaction occurs, Then the bar highlights within 100 ms and does not cause cumulative layout shift > 0.1. - Given a slot lacks a computed score, When it is rendered, Then show an N/A neutral bar style and a tooltip stating “Score unavailable—try refreshing.” - Given any viewport ≥ 320 px width, When the list renders, Then bar, score label, and time text do not overlap or overflow; ellipsis is applied to overflowing text.
Observance Badges and Tooltips Explain Rationale
- Given a slot is affected by partial observances, When it is displayed, Then a badge appears next to the time with an icon representing the observance category. - Given pointer, keyboard, or touch interaction, When the badge is hovered, focused, or tapped, Then a tooltip opens within 200 ms and remains until focus moves, tap outside, or Esc is pressed. - Given the tooltip content, When it opens, Then it lists: observance type(s), count and percentage of attendees impacted, severity (minor/moderate/significant) derived from score deltas, and a one-line rationale. - Given multiple observances affect the same slot, When the tooltip renders, Then it aggregates causes and shows per-cause contribution percentages ordered by impact. - Given performance constraints, When the tooltip is triggered, Then first contentful paint of tooltip occurs in < 100 ms on mid-tier devices.
Earlier/Later Nudges Increase Comfort
- Given a slot is selected and there exists a higher-comfort slot within the same day, When the user taps “Earlier” or “Later,” Then the UI proposes the nearest higher-scoring slot in that direction and displays the predicted score delta (e.g., +8). - Given hard constraints (working hours, hard blocks), When computing a nudge target, Then no proposed slot violates hard constraints or organizer-defined bounds. - Given no higher-comfort slot exists in the chosen direction, When the user taps the nudge, Then the control is disabled with an inline explanation “No better slot available.” - Given a nudge proposal is shown, When the user accepts it, Then the selection updates, the comfort bar and score refresh accordingly, and any invite preview reflects the new time.
Auto-Generated Alternative Windows with Higher Comfort
- Given the slot picker initializes, When alternatives are available, Then show up to 3 alternative windows with higher average comfort than the current selection, each with start–end times, comfort score, and attendee overlap count. - Given multiple alternatives, When they render, Then they are sorted by descending comfort score and secondarily by earliest start time. - Given partial observance weighting, When alternatives are generated, Then soft-weighted observances are reflected in the displayed scores and rationales. - Given a user selects an alternative, When they confirm, Then the main selection updates and the alternatives list refreshes to exclude the chosen window.
Accessibility Compliance for Impact Indicators
- Given WCAG 2.2 AA requirements, When the slot picker is used with keyboard only, Then all interactive elements (slots, badges, nudges) are reachable in a logical Tab order with visible focus indicators. - Given screen reader usage, When focus lands on a slot, Then the slot is announced with time, timezone, and “Comfort score X out of 100” plus any observance summary via aria-describedby. - Given tooltips, When they open, Then they are programmatically associated to the triggering element and dismissible via Esc and focus loss without trapping focus. - Given color usage, When conveying comfort levels, Then non-color cues (icons/patterns) are present and contrast ratios meet or exceed 4.5:1 for text and 3:1 for non-text elements. - Given motion sensitivity, When animations occur (e.g., bar highlight), Then they respect prefers-reduced-motion and provide a non-animated alternative.
Responsive and Add-on/Embed Consistency
- Given a viewport ≤ 480 px width, When the slot list renders, Then comfort bars switch to compact style with numeric label, badges wrap below the time, and no horizontal scrolling is introduced. - Given a viewport ≥ 768 px width, When the slot list renders, Then full-size bars with labels are shown and badges align on the same row as the time. - Given the UI is rendered within a calendar add-on or embedded iframe, When the slot picker loads, Then visual measurements (bar length, line height, spacing) remain within ±2 px of web rendering and color tokens match design specs. - Given performance budgets, When the slot picker first appears, Then LCP ≤ 2.5 s on a simulated 4G profile and tooltip interaction latency < 100 ms. - Given locale differences, When times are displayed in embedded contexts, Then formats follow the viewer’s locale without altering computed comfort scores.
Privacy-Safe Rationale Content
- Given observance impact is shown, When badges/tooltips present rationale, Then no personally identifiable information is displayed; only aggregated counts, roles, or timezones are shown. - Given only one attendee is impacted, When the rationale is presented, Then it states “1 attendee impacted” without naming or uniquely identifying the person. - Given calendar privacy settings mark an observance as private, When rationale is displayed, Then it shows “Private observance” instead of the specific type. - Given analytics/logging, When tooltip data is captured, Then personal identifiers and free-text observance details are redacted.
Admin Sensitivity Policies & Weight Tuning
"As an ops lead, I want to set consistent observance sensitivity policies for our company so that scheduling remains humane while meeting our operational needs."
Description

Provide organization-level controls to set default sensitivity, included observance categories, min/max penalty weights, and exceptions for critical incidents. Ship presets (conservative, balanced, high-sensitivity), support per-team overrides with inheritance, and record all changes in an audit log. Expose policy configuration via API for automation and compliance workflows.

Acceptance Criteria
Org Policy Creation with Default Sensitivity and Weight Bounds
Given I am an org admin with Policy:Manage permissions When I create an org-level Observance Sensitivity policy with default_sensitivity='balanced', included_categories=['religious_evenings','half_days','school_breaks'], min_penalty=0.10, max_penalty=0.60 Then the policy is persisted with a unique policy_id and version And validation enforces 0.0 <= min_penalty <= max_penalty <= 1.0 And a GET org policy API returns the same values within 2 seconds of save And all teams without overrides resolve to this policy within 2 minutes And the admin UI displays the Active Policy banner reflecting the saved values
Preset Selection and Application
Given I am on the Admin > Sensitivity Policies page When I apply the 'High-Sensitivity' preset Then the form pre-populates included_categories=['religious_evenings','half_days','school_breaks'], min_penalty=0.20, max_penalty=0.90, default_sensitivity='high' And I can modify any pre-populated field before saving And saving persists the modified values, not the untouched preset label And applying 'Balanced' preset yields min_penalty=0.10, max_penalty=0.60 with the same categories And applying 'Conservative' preset yields included_categories=['religious_evenings'], min_penalty=0.05, max_penalty=0.30
Critical Incident Exception Window
Given an org policy is active When an admin creates a Critical Incident exception with scope='org', reason='Sev1 outage', start=now, end=now+24h Then scheduling proposals generated during [start,end] do not apply observance penalties (effective penalty=0) for the scoped entities And creation requires a non-empty reason and an end time <= 72h after start And the exception can be cancelled early, after which penalties resume immediately And the exception is recorded in the audit log with actor, scope, reason, window, and source
Per-Team Overrides and Inheritance
Given Team A inherits the org policy When a team admin for Team A overrides included_categories to ['religious_evenings','school_breaks'] and min_penalty=0.15 Then Team A’s effective policy reflects those overrides, while other fields inherit from the org And subsequent org changes to inherited fields propagate to Team A within 2 minutes And subsequent org changes to overridden fields do not overwrite Team A’s overrides And toggling 'Revert to Inherit' on a field restores inheritance and removes the override And GET effective policy for Team A returns source metadata per field: 'org' or 'team'
Audit Logging of Policy and Exception Changes
Given audit logging is enabled by default When any policy or exception is created, updated, or deleted via UI or API Then an append-only audit entry is stored with id, timestamp (UTC), actor_id, actor_type, source (UI|API), scope (org|team_id), action (create|update|delete), changed_fields with before/after values, reason (if provided), and version And audit entries are immutable (no update/delete endpoints) And GET /v1/audit/policy?since=<ts> returns entries in descending time order with pagination and a next_page token And entries are visible in the Admin UI within 60 seconds of the action
Policy Configuration API and Validation
Given a service account with scope policy:write When it calls PUT /v1/policies/org with a body that violates bounds (min_penalty=0.7, max_penalty=0.6) Then the API responds 400 with code='INVALID_BOUNDS' and a descriptive message And successful updates return 200 with the saved resource, policy_id, and ETag And subsequent updates require If-Match with the last ETag; mismatches return 409 'ETAG_MISMATCH' And GET endpoints require policy:read and return 403 for insufficient scope And requests are rate-limited at 120 rpm per token with 429 responses including Retry-After
Scheduling Engine Enforcement of Policy Weights
Given a test calendar with participants across time zones and registered partial observances And the org policy has included_categories=['religious_evenings','half_days'], min_penalty=0.10, max_penalty=0.50 When meeting proposals are generated for a 2-week horizon Then each proposed slot’s observance impact score is within [0.10, 0.50] when any penalty applies And removing 'half_days' from included_categories eliminates its contribution to impact scores in subsequent proposals And activating a Critical Incident exception sets impact scores to 0.0 for the scoped entities during the exception window
Equity Rotation & Attendance Feedback Loop
"As a team lead, I want recurring meetings to adapt based on attendance data and observance impact so that the burden is shared fairly and attendance improves over time."
Description

Incorporate observance penalties into the equity rotation to distribute any remaining inconvenience over time for recurring meetings. Capture attendance, tardiness, and reschedule events to adjust future weights and rotation suggestions, creating a closed-loop improvement system. Provide reports that highlight attendance gains, distribution of inconvenience, and residual hotspots for action.

Acceptance Criteria
Rotation Applies Observance Penalties Across Series
Given a recurring meeting series with at least 8 scheduled occurrences and at least 3 participants with observance calendars enabled When the system generates the rotation for the next 8 weeks Then each participant’s cumulative inconvenience score (including observance penalties) is within ±10% of the team average And any slot intersecting a partial observance is assigned to a given participant at most once within the 8-week window And the rotation suggestion includes an audit log listing penalty sources and per-participant inconvenience totals for each occurrence
Attendance, Tardiness, and Reschedule Capture
Given an occurrence has completed When attendance data is ingested from calendar and conferencing telemetry Then each invitee is marked as Attended, Absent, or Partial (>=50% of scheduled duration) And tardiness is recorded as minutes late; mark Tardy if join time is >5 minutes after scheduled start And a reschedule event is recorded if the start time shifts by >=10 minutes post-confirmation And all records are persisted within 15 minutes of meeting end with >=99% success over a rolling 7-day window
Closed-Loop Weight Adjustment Before Next Scheduling
Given feedback (attendance, tardiness, reschedules) exists for the last occurrence When computing candidate window weights for the next occurrence Then windows with attendance >=90% and median tardiness <=3 minutes receive a 10% penalty reduction And windows with attendance <70% or any reschedule receive a 20% penalty increase And per-iteration weight changes are bounded to ±25% of the prior weight And the computation completes within 2 seconds for teams up to 20 participants
Equity Ownership Rotation Updates With Feedback
Given ownership is assigned per occurrence in a recurring series When updated weights are applied after each occurrence Then across the next 6 scheduled occurrences, no participant holds more than 1 occurrence above the mean ownership count And weeks with active observance penalties for a participant do not assign ownership to that participant And any manual organizer override updates the equity ledger and recomputes remaining ownership within 1 second
Equity & Attendance Reporting
Given at least 4 occurrences have completed in the last 90 days When the user generates the Equity & Attendance report Then the report displays attendance trend (%), average tardiness (minutes), reschedule rate (%), inconvenience distribution Gini coefficient, and top 3 residual hotspot windows And filters by team, participant, and date range are available and functional And export to CSV produces a file whose metric values match the event store within ±0.5%
Impact Visibility and Rationale on Suggested Windows
Given a user opens rotation suggestions for a recurring meeting When candidate time windows are displayed Then each option shows an Impact Score (0–100) with breakdown of observance penalty, ergonomics, equity offset, and attendance forecast And an inline rationale references data from the last 4 occurrences And all score and breakdown elements meet WCAG 2.2 AA contrast and include accessible text alternatives

Owner Heads‑Up

Proactive DM and email to the next facilitator with one‑tap Confirm, Swap, or Defer. Includes date/time in their locale, the agenda preview, and prep checklist with a confirm‑by timer. Reduces last‑minute scrambles and gives owners clear, timely context to prepare.

Requirements

Multi-Channel Heads-Up Delivery
"As a meeting facilitator, I want to receive a proactive DM and email with key meeting details so that I can prepare and act without hunting through my calendar."
Description

Send proactive heads-up notifications to the next meeting facilitator via Slack/Teams direct message and email, bundling meeting title, date/time in their locale, agenda snippet, and prep checklist. Respect user notification preferences and quiet hours, with intelligent channel fallback if a DM cannot be delivered. Implement delivery retries, rate limiting, and bounce handling. Support workspace-level OAuth for chat apps and SPF/DKIM/DMARC for email, ensuring reliable, compliant delivery that aligns with TimeMeld’s scheduling graph.

Acceptance Criteria
Chat DM Heads-Up Delivery (Slack/Teams)
Given a next facilitator determined by TimeMeld’s scheduling graph and a connected Slack or Microsoft Teams workspace with valid workspace-level OAuth When the configured heads-up lead time is reached and the facilitator’s DM notifications are enabled and outside quiet hours Then TimeMeld sends a direct message containing the meeting title, date/time localized to the facilitator’s locale, the first 500 characters of the agenda, and the prep checklist with a confirm-by countdown And the message includes one-tap actions for Confirm, Swap, and Defer as distinct buttons linked with secure, user-scoped tokens And delivery status is recorded as Sent with provider message ID and timestamp And Slack messages render via Block Kit and Teams messages render via Adaptive Cards with content parity And message content is sanitized (no executable HTML/JS) and contains no sensitive data beyond meeting metadata
Email Heads-Up Fallback and Bounce Handling
Given a chat DM cannot be delivered due to missing OAuth, user not found, DMs disabled, provider outage, or sustained rate limiting When the facilitator’s email notifications are enabled and outside quiet hours Then an email is sent with subject "[TimeMeld] Heads‑Up: {Meeting Title} on {Localized Date}" containing meeting title, localized date/time, the first 500 characters of the agenda, the prep checklist, and a confirm-by countdown with actionable Confirm, Swap, and Defer links/buttons And the email passes SPF and DKIM with DMARC alignment (Authentication-Results shows spf=pass, dkim=pass, dmarc=pass for the sending domain) And hard bounces are recorded, the address is suppressed for future sends, and a fallback is re-evaluated; soft bounces trigger up to 3 retries with exponential backoff And all bounce and complaint events are stored with reason codes and timestamps And delivery, open (if enabled), and click events are captured and associated to the notification
Channel Selection, Preferences, and Quiet Hours
Given the facilitator has channel preferences (e.g., Slack, Teams, Email) and quiet hours configured in TimeMeld When a heads-up is due Then TimeMeld selects the highest-priority allowed channel that is available (valid OAuth for chat, deliverable email) and outside quiet hours And channels explicitly opted out by the user are never used And if all channels are blocked by quiet hours, the notification is queued and sent at quiet hours end; the confirm-by countdown reflects the delayed send And if the initially selected channel fails definitively, the next eligible channel is attempted once within the send window without violating quiet hours
Delivery Retries, Idempotency, and Rate Limiting
Given a transient error (e.g., 429, 5xx, network timeout) occurs during send When retrying Then TimeMeld uses exponential backoff with jitter for up to 3 attempts per channel and respects provider-specific rate limits And each heads-up is keyed with an idempotency token so duplicate triggers do not produce multiple messages per channel And no facilitator receives more than 1 heads-up per meeting and no more than 3 notifications per hour across channels from this feature And metrics are recorded for attempts, successes, failures, latency, and retry outcomes
Workspace-Level OAuth for Slack and Teams
Given a workspace admin installs the TimeMeld app with workspace-level OAuth in Slack or Microsoft Teams When tokens and scopes are granted Then tokens are stored encrypted at rest, least-privilege scopes are requested, and token refresh occurs before expiry And send-time permission checks verify required scopes; missing scopes prevent sending on that channel and log a structured reason And uninstall or consent revocation immediately disables sending for that workspace and triggers eligible fallback per user preferences
Action Links: Confirm, Swap, Defer Instrumentation
Given the facilitator clicks Confirm, Swap, or Defer from a DM or email When the action endpoint is invoked Then the request is authenticated via a time-bound, single-use token tied to the user and meeting (valid until meeting start or 24 hours, whichever comes first) And the selected action updates TimeMeld’s scheduling graph and meeting ownership state accordingly And the user receives immediate feedback (<=2s) with updated status; in-channel messages are updated, and email actions redirect to a confirmation page And duplicate or expired tokens are rejected with an informative message and no duplicate state change And all actions are logged with user, meeting, channel, timestamp, and outcome
Content Packaging and Locale Rendering
Given the facilitator’s profile includes locale, time zone, and time format preferences When composing the heads-up content Then dates and times are rendered in the facilitator’s time zone with correct DST and 12/24-hour format per preference, and weekday/month names localize to the user’s locale And the agenda snippet is truncated to 500 characters without breaking multibyte characters; prep checklist renders up to 5 items with preserved links And templates are consistent across channels with equivalent information density and accessibility (alt text where applicable, minimum color contrast), and links are sanitized
One-Tap Confirm/Swap/Defer Actions
"As a facilitator, I want to confirm, swap, or defer the meeting with one tap so that I can manage ownership quickly on the go."
Description

Embed secure, one-tap action controls in DM and email that let recipients confirm ownership, request a swap, or defer. Use signed, expiring deep links with SSO/session handoff and CSRF protection to execute actions idempotently. Provide immediate success/failure feedback in-channel, and fall back to a lightweight web action page if the client does not support interactive components. Capture optional notes (e.g., proposed alternate owner or defer reason) and persist state for downstream updates.

Acceptance Criteria
One-Tap Confirm via DM
Given a facilitator receives a DM containing one-tap Confirm, Swap, and Defer controls with a signed, expiring deep link And the deep link is valid, unexpired, and bound to the facilitator and meeting When the facilitator taps Confirm Then ownership is assigned to the facilitator and persisted with timestamp, actor ID, and meeting ID And the action is executed idempotently so repeated taps or retries do not change the final state And an in-channel success message is posted within 3 seconds reflecting the new owner and meeting status And a confirmation email notification is sent to the facilitator And an audit event is recorded including action type, result, and metadata
One-Tap Swap Request with Proposed Alternate
Given a facilitator receives a DM/email with a one-tap Swap control and signed deep link And the link is valid and the meeting is in an actionable state When the facilitator taps Swap Then the client surfaces an input to capture an optional note and an optional proposed alternate owner (search or email) And on submit the system validates the proposed alternate as eligible and available or returns a clear error in-channel And the meeting state updates to Swap Requested with the note and proposed alternate persisted And relevant stakeholders are notified (current owner, scheduling bot/workflow) And the action is idempotent; duplicate submissions do not create multiple requests And an in-channel success message appears within 5 seconds summarizing the request
One-Tap Defer with Reason and Target Window
Given a facilitator receives a one-tap Defer control with a signed, expiring deep link When the facilitator taps Defer Then the client prompts for an optional defer reason and a target window (e.g., next sprint/week or specific date) And upon submit the meeting status updates to Deferred Pending Reschedule and the confirm-by timer is adjusted or paused per policy And all inputs (reason, target window) are persisted with actor and timestamp And attendees/owner group receive a notification about the deferment And the action is idempotent; repeat taps show current deferred state without side effects And an in-channel success confirmation is posted within 5 seconds
Deep Link Security, Expiry, and CSRF Protection
Given one-tap actions use signed deep links containing claims (user ID, meeting ID, action, nonce, expiry) When a link is expired (past configured TTL or confirm-by deadline), tampered, or not bound to the actor/meeting Then the action is rejected, no state changes occur, and an in-channel/web error explains the reason and recovery path And replay attempts using the same token are rejected and logged with reason code And SSO/session handoff authenticates the actor when a valid IdP session exists; otherwise the user is prompted to sign in And the fallback web action page requires a valid session and enforces CSRF tokens on POST And all security failures are recorded with correlation IDs for audit
Fallback Web Action Page for Unsupported Clients
Given the recipient’s client does not support interactive components or cannot open the deep link natively When the recipient follows the action link Then a lightweight web action page loads within 2 seconds on a 4G connection (p95) and is mobile-friendly And it displays meeting title, local date/time in the recipient’s locale, agenda preview, and prep checklist And it exposes Confirm, Swap, and Defer controls with the same validations and protections as in-channel And accessibility meets WCAG 2.1 AA for controls, focus order, labels, and contrast And on completion it shows clear success/failure and offers a return to DM/email thread link
Idempotent Execution and Concurrency Control
Given the recipient or multiple actors trigger the same action multiple times or in parallel When conflicting actions occur (e.g., Confirm vs Defer) within a short window Then only the first valid action commits atomically and subsequent attempts return an Already Processed response with the current state And no duplicate calendar invites, notifications, or audit entries are produced And each action uses an idempotency key scoped to (meeting, actor, action) and deduplicates within its TTL And race conditions are logged with correlation IDs for observability
In-Channel Immediate Feedback and Error Handling
Given any one-tap action (Confirm, Swap, Defer) is initiated from DM or email When the action succeeds Then a success message appears in-channel within 5 seconds summarizing the new status, owner (if applicable), and next steps When the action fails Then an error message appears in-channel explaining the failure reason and presents Retry and Open Web Page options And the feedback content respects the recipient’s locale for date/time formatting And the thread reflects the final state if the action is later completed via fallback
Locale-Aware Date/Time Rendering
"As a global teammate, I want meeting times shown in my local format and timezone so that I can instantly understand when the meeting occurs."
Description

Render all dates and times in the recipient’s local timezone and preferred locale, including 12/24-hour format, weekday labels, and DST adjustments. Provide a secondary hover or inline hint of the canonical meeting timezone for clarity. Ensure consistent formatting across DM and email templates and cache user locale/zone preferences for future notifications.

Acceptance Criteria
Slack DM: Localized date/time in recipient timezone
Given a meeting scheduled for 2025-10-15 10:00 Europe/London (canonical) And the recipient has timezone America/Sao_Paulo and locale pt-BR with 24-hour preference When the Owner Heads‑Up DM is generated Then the primary date/time displays in America/Sao_Paulo with the correct offset for that date And the time uses 24-hour formatting and includes the weekday label in pt-BR And a secondary hint shows the canonical time and zone (e.g., "Original: 10:00 BST") And both representations resolve to the same instant (epoch milliseconds match)
Email: Locale and 12/24-hour preference respected
Given the recipient has timezone Europe/London and locale en-GB with 24-hour preference When the Owner Heads‑Up email is composed Then the time is rendered using 24-hour format (e.g., 14:30) with weekday label and dd MMM yyyy ordering And a secondary hint shows the canonical time and zone And the email subject and body use the same date/time format And when the recipient’s locale is en-US with 12-hour preference Then the time renders as 2:30 PM with weekday label and MMM dd, yyyy ordering
DST transitions: Correct local offset and labels
Given a meeting at 2025-03-30 09:00 Europe/London (DST start day in UK) And the recipient timezone is America/New_York When the notification is generated Then the recipient’s local time displays as 04:00 with EDT label and the correct weekday/date And when a meeting occurs on the recipient’s DST end day (e.g., 2025-11-02 09:00 America/Los_Angeles canonical) Then the recipient’s local time uses PST (not PDT) and the calendar date/weekday are correct even if day rolls over
Canonical timezone hint across channels
Given a client that supports hover tooltips (e.g., desktop email) When the user hovers the primary time Then a tooltip displays "Original: {time} {zone}" And when hover is not supported (e.g., mobile email or Slack) Then the canonical time appears inline in parentheses immediately after the primary time And in both cases the hint includes the timezone abbreviation and UTC offset for that date (e.g., BST, UTC+1)
Unknown preferences: Fallback, capture, and cache
Given a DM recipient with no stored timezone/locale preferences When generating the DM Then the app fetches timezone and locale from the messaging provider profile and uses them for rendering And the fetched preferences are cached for future notifications And subsequent notifications use the cached values without re-querying the provider And if the provider profile changes, the cache is refreshed within 24 hours of detection And when the recipient has no detectable timezone/locale (email-only first contact) Then the primary time renders in the canonical timezone clearly labeled as such And the notification includes a "Set my timezone" link And upon the recipient setting preferences, the next notification uses the new timezone/locale and stores them
Consistent formatting across DM and email
Given any recipient with known timezone/locale When generating both DM and email Owner Heads‑Up notifications Then both channels use the same ordering and tokens: Weekday, Date, Local Time, TZ Abbreviation And the same 12/24-hour rule is applied in both And snapshots of the formatted strings for DM and email match exactly aside from channel-specific styling
Automated coverage: Locales and timezones matrix
Given a test matrix of locales/timezones: en-US/America/Los_Angeles, en-GB/Europe/London, fr-FR/Europe/Paris, de-DE/Europe/Berlin, pt-BR/America/Sao_Paulo, ja-JP/Asia/Tokyo, hi-IN/Asia/Kolkata, ar-EG/Africa/Cairo When rendering Owner Heads‑Up notifications for the same canonical meeting instant Then the primary date/time strings match each locale’s formatting conventions and the local zone’s correct offset/abbreviation for that date And the canonical timezone hint is present and correct in each case And all renderings include weekday labels and pass snapshot tests
Agenda Preview and Prep Checklist
"As a facilitator, I want an agenda preview and prep checklist included so that I know exactly what to prepare ahead of the meeting."
Description

Include a concise agenda preview and actionable prep checklist sourced from the meeting’s agenda document or template. Support links to relevant docs, owners, and blockers, and allow marking checklist items as done directly from the DM/email where supported. Enforce permissions so only authorized content is shown, truncate long content gracefully, and sync completion state back to the meeting record.

Acceptance Criteria
Agenda Preview Extraction and Truncation
Given a meeting agenda exists in a linked doc or template When generating the Owner Heads-Up DM/email Then extract the first 6 top-level agenda bullets or up to 500 characters, whichever comes first And preserve basic list formatting (bulleted/numbered) in rich clients and provide a readable plain-text fallback And append a 'View full agenda' link to the source And do not break words mid-word; add '...' if truncated And if no agenda is available, display 'No agenda provided yet' with a 'Create agenda' link And total preview height does not exceed 8 lines in DM or 300px in email
Permission-Gated Agenda and Checklist Content
Given the recipient has access only to a subset of agenda content When generating the DM/email Then include only sections the recipient is authorized to view based on a permission check performed at generation time And redact restricted sections with a '[Private]' placeholder without revealing titles or snippets And exclude links to restricted documents or sections And attempting to open any restricted resource returns an access-denied page without leaking metadata And automated tests verify role-based visibility for facilitator, attendee, observer, and external guest roles
Prep Checklist Rendering with Owners and Blockers
Given the agenda includes a prep checklist with items, owners, and optional blockers When generating the DM/email Then render up to 10 checklist items in defined priority order And each item shows: a checkbox, title (max 80 chars), owner display name or @mention, and optional 'Blocked' tag And each item title links to the relevant doc/section when a link is provided And if there are more than 10 items, append a 'View all checklist items' link And if there are zero items, omit the checklist section entirely
One-Tap Checklist Completion from DM
Given a supported DM client (e.g., Slack/Teams) shows interactive checklist items When the recipient taps 'Mark done' on an item Then the item is marked complete in the meeting record within 3 seconds And the DM updates in-place to show a checked state and completion timestamp And the action is idempotent; repeat taps have no additional effect And unauthorized users see 'Action not permitted' and no state change occurs And on backend failure the DM shows a retry option and a descriptive error message And the action is logged with actor ID, item ID, and timestamp
Secure One-Click Checklist Completion from Email
Given the Owner Heads-Up email contains per-item 'Mark done' links When the recipient clicks a 'Mark done' link Then a signed, single-use token validates the request for the intended recipient without requiring login if email matches and token is valid And the token expires at the earlier of 72 hours or 30 minutes before meeting start And upon success the item is completed and a confirmation page is shown And on invalid/expired token the user is prompted to authenticate or shown 'Link expired' And forwarded emails do not permit unauthorized completion And the meeting record reflects the change within 5 seconds
State Synchronization and Concurrency Handling
Given multiple clients attempt to complete the same checklist item concurrently When two or more completion requests are received within 2 seconds Then the system processes them idempotently with optimistic concurrency, resulting in a single 'done' state And an audit log records each attempt with actor ID and timestamps And DM/email and the web view reflect the final state within 5 seconds And offline retries use exponential backoff up to 3 attempts over 90 seconds And no duplicate completion events are persisted
Confirm-By Timer and Smart Reminders
"As a facilitator, I want a clear confirm-by deadline with reminders so that I don’t miss preparation and the team avoids last-minute scrambles."
Description

Display a dynamic confirm-by countdown and deadline in the notification, with automated reminder nudges at configurable intervals. Respect quiet hours and timeboxing rules, allow one-tap snooze, and escalate to a backup owner or team channel if the deadline passes without action. Store per-team SLAs and surface late confirmations in the shared scoreboard for transparency.

Acceptance Criteria
Localized Confirm-By Countdown in DM and Email
Given a heads-up notification is issued to the next facilitator When delivered via DM Then the message displays a live countdown to the confirm-by deadline that updates at least every 60 seconds And it shows the absolute deadline timestamp labeled "Confirm by" in the facilitator’s local timezone When delivered via email Then the email shows the absolute deadline timestamp with timezone and a static countdown snapshot as of send time And both DM and email include one-tap actions: Confirm, Swap, Defer
Configurable Reminder Cadence Pre-Deadline
Given a confirm-by deadline exists and a team-level reminder schedule is configured (e.g., 24h, 4h, 1h before deadline) When the deadline is in the future Then reminders are sent at the configured offsets that still occur before the deadline And reminders scheduled in the past are skipped, not resent And reminders stop immediately after the facilitator selects Confirm, Swap, or Defer And an admin can update the team’s schedule, which applies to new notifications created after the change
Quiet Hours and Timeboxing Respect
Given user-level quiet hours and team timeboxing windows are defined When a reminder would occur inside a quiet hour or outside the timebox Then it is rescheduled to the earliest allowed time that is before the confirm-by deadline And if no allowed time remains before the deadline, the reminder is skipped And all scheduling honors the facilitator’s local timezone And no DM/email is sent during quiet hours
One-Tap Snooze Before Deadline
Given a reminder DM or email is received before the confirm-by deadline When the facilitator taps/clicks Snooze Then they can select from preset durations that do not extend past the confirm-by deadline And the next reminder is scheduled for the selected future time, adjusted to respect quiet hours/timeboxing And the DM/email confirms the new reminder time in the facilitator’s local timezone And if all snooze options would pass the deadline, no snooze is applied and the facilitator is informed
Escalation on Missed Confirm-By Deadline
Given no Confirm, Swap, or Defer has occurred by the confirm-by deadline When the deadline passes Then an escalation is sent within 5 minutes to the configured backup owner via DM including agenda and deadline context And if no backup owner is configured, an escalation is posted to the designated team channel And only one escalation is sent per missed deadline And if the original owner responds after escalation, the escalation thread is updated with the new status
Per-Team SLA Storage and Application
Given a team-level SLA defines the confirm-by offset and reminder cadence When a new heads-up is generated Then the SLA values are applied as defaults to compute the confirm-by deadline and reminders And SLA changes are persisted and auditable with timestamp, actor, and values And SLA updates affect only newly created heads-ups and do not retroactively alter already-sent notifications And per-event overrides can be set and take precedence over the team SLA
Scoreboard Indicator for Late Confirmations
Given a confirmation occurs after the confirm-by deadline When the scoreboard is viewed Then the meeting row displays a Late indicator with the lateness duration (e.g., +12m) visible to the team And the scoreboard updates within 2 minutes of the late confirmation or missed deadline And selecting the indicator reveals the confirm time, deadline, and actor for transparency
Ownership and Calendar Sync on Action
"As a program manager, I want ownership changes to sync to the scoreboard and calendar automatically so that the schedule stays accurate and fair."
Description

Upon Confirm, Swap, or Defer, atomically update the shared equity scoreboard, rotate ownership as per team rules, and adjust the calendar event (title, organizer/facilitator field, attendees) via Google/Microsoft calendar APIs. Trigger follow-up notifications to stakeholders and recalculate timezone-weighted windows when a swap affects scheduling. Provide audit logging and guard against race conditions with optimistic locking.

Acceptance Criteria
Confirm: Atomic Ownership and Calendar Sync
Given a scheduled meeting with a designated next facilitator and an equity scoreboard at version v And the facilitator receives an Owner Heads‑Up with a confirm-by timer not expired When the facilitator taps Confirm Then the system acquires a lock on the meeting and scoreboard at version v using optimistic locking And updates the equity scoreboard to mark the facilitator as owner for this instance and increments their equity credit according to team rules And rotates the next owner per team rotation rules and saves the scoreboard at version v+1 And updates the calendar event via the connected provider to reflect the facilitator: - Google Calendar: transfer event ownership to the facilitator if permitted; otherwise update the title to include "Facilitator: {Name}" and set extended property facilitator_id={id} - Microsoft 365: update the subject to include "Facilitator: {Name}" and set singleValueExtendedProperties facilitator_id={id} And ensures attendees include all required participants and the facilitator, without duplicates And preserves the meeting date/time and conferencing link And sends a success response to the client within 2 seconds of commit
Swap: Recalculate Windows and Reschedule with Ownership Sync
Given a meeting with a designated facilitator, participants across timezones, and valid ergonomic constraints And team rules define rotation and timezone-weighted window selection When the facilitator taps Swap Then the system acquires an optimistic lock on the meeting and scoreboard And recomputes timezone-weighted candidate windows using current availability and constraints And selects the highest-ranked window different from the current start time And updates the calendar event start/end to the selected window via provider APIs and updates facilitator annotations per provider rules And updates the equity scoreboard and rotation per team rules if the swap changes ownership eligibility And sends DM/email notifications to all attendees and watchers within 30 seconds summarizing the change with localized times And records an audit entry with correlation_id and before/after snapshots
Defer: Rotate Ownership to Next Cadence Slot
Given a recurring meeting governed by a cadence (e.g., weekly) and rotation rules When the facilitator taps Defer Then the system acquires an optimistic lock on the meeting and scoreboard And moves the meeting to the next cadence slot that satisfies ergonomic constraints And rotates ownership to the next eligible owner per team rules And updates the calendar event via provider APIs to reflect the new date/time and facilitator annotation And preserves the attendee list and conferencing link And sends DM/email notifications including the new date/time in each recipient's locale and a prep checklist And writes a defer audit record with correlation_id and before/after state
Audit Logging: Complete, Immutable, Searchable
Given any Confirm, Swap, or Defer action When the action is processed Then an audit record is created within 1 second containing correlation_id, actor_id, action type, request payload, pre-commit snapshots (meeting, calendar event, scoreboard), post-commit snapshots, provider request/response IDs, lock version, outcome status, and timestamps And the audit record is write-once and tamper-evident And the audit record is queryable by correlation_id and meeting_id within 2 seconds And personal data fields follow configured retention/redaction policies
Concurrency Control: Optimistic Locking and Idempotency
Given two or more Confirm/Swap/Defer actions are submitted concurrently for the same meeting When the first action commits with scoreboard version v Then subsequent actions expecting version v fail with HTTP 409 Conflict and a "stale action" error, with no changes applied to the scoreboard or calendar event And the client is provided the latest version for retry And duplicate submissions with the same idempotency key result in a single committed transaction and 200 OK for duplicates And no partial updates are observable in the calendar provider or scoreboard
Atomicity: All-or-Nothing Across Scoreboard and Calendar
Given the system is executing a Confirm, Swap, or Defer When any required Google/Microsoft Calendar API call fails permanently after retries Then the transaction is rolled back: the equity scoreboard and ownership rotation revert to their prior state, and no calendar changes persist And the user receives an actionable error message within 2 seconds of rollback And an operational alert is emitted with correlation_id and failure details And transient errors (e.g., 429, 503) are retried with exponential backoff up to 3 attempts
Notifications: Timely, Localized, and De-duplicated
Given any successful Confirm, Swap, or Defer action When the transaction commits Then the facilitator, attendees, and watchers receive DM and email notifications within 30 seconds And each notification includes meeting title, localized date/time for the recipient's timezone, facilitator name, agenda preview, prep checklist, and confirm-by or updated start time as applicable And no recipient receives duplicate notifications for the same action And delivery failures are retried up to 3 times and recorded in logs
Delivery Analytics and Audit Trail
"As an operations lead, I want visibility into heads-up delivery and actions so that I can improve processes and ensure compliance."
Description

Capture delivery, open, click, and action conversion metrics for each channel, with per-team dashboards and CSV export. Maintain a tamper-evident audit log of notifications sent and actions taken for compliance and incident review. Apply data retention policies and privacy controls (redaction of message bodies at rest where required) while exposing aggregated insights to improve reminder timing and channel effectiveness.

Acceptance Criteria
Cross-Channel Delivery and Engagement Event Capture
Given an Owner Heads‑Up notification is sent via email or Slack DM When the provider returns delivery/open/click/bounce events or the recipient performs Confirm/Swap/Defer Then the system records an immutable event with fields: event_id, team_id, meeting_id, recipient_user_id, channel, event_type, template_version, provider_message_id, timestamp_utc, metadata (source_button/link, client) And events are attributed to the correct team and meeting even if the recipient belongs to multiple teams And duplicate provider callbacks are de‑duplicated by provider_message_id + event_type idempotency key And p95 ingestion latency from provider/user to durable storage is ≤ 60 seconds And failed deliveries/bounces are captured with error_code and error_reason And events are queryable via analytics API with filters (team_id, channel, date_range, event_type)
Per‑Team Funnel Dashboard
Given a team admin opens Delivery Analytics for a selected date range When data loads Then the dashboard displays counts and rates per channel: sent, delivered, opened, clicked, actioned (Confirm/Swap/Defer) and conversion funnel percentages And metrics are filterable by channel, owner, meeting type, and template_version And charts show time‑to‑open and time‑to‑action distributions and p50/p95 values And data freshness indicator shows last refresh time (≤ 5 minutes delay for new events) And access is restricted to team admins and analysts; unauthorized users see a 403 And p95 dashboard render time ≤ 2 seconds for 90‑day range on teams ≤ 10k events/day
CSV Export of Metrics and Audit Events
Given a team admin requests a CSV export for a date range and selected filters When the export is generated Then the CSV includes a header and the following columns for events: event_id, team_id, meeting_id, user_id, channel, event_type, timestamp_utc, provider_message_id, template_version, action_source, error_code, error_reason And timestamps are ISO‑8601 UTC; commas are properly quoted; file is UTF‑8 with LF line endings And exports up to 1M rows complete within 2 minutes; larger exports stream in parts with sequence numbers And the download link is single‑use, expires in 24 hours, and requires authenticated access with team scope And an export_requested and export_downloaded event is logged to the audit log including requester and IP And PII masking rules are applied per team settings before file creation
Tamper‑Evident Audit Log
Given any notification send, provider callback, user action, or admin export occurs When an audit entry is written Then the entry is append‑only and includes: audit_id, event_ref, actor (system/user), action, timestamp_utc, payload_hash, prev_log_hash And the service signs each entry’s hash chain with a rotating key; verification endpoint validates chain integrity And any modification to a historical entry causes chain verification to fail and raises an integrity_alert within 60 seconds And the log records sufficient context to reconstruct a timeline from send to action, including channel and delivery status And audit reads are paginated, filterable, and return within p95 ≤ 1 second for 10k‑entry ranges
Data Retention and Privacy Controls
Given team‑level retention settings for raw events and message content When the retention window elapses Then raw event records beyond the window are purged or content‑redacted within 24 hours according to policy And when content redaction is enabled, message bodies at rest are stored as SHA‑256 hash with body removed within 15 minutes of persistence And user erasure requests remove or anonymize all personally identifiable fields within 7 days and are reflected in future exports and dashboards And aggregated metrics remain available but are non‑reidentifiable (no groups with < 10 unique users) And access to unredacted content requires elevated role and is fully audited
Aggregated Insights for Timing and Channel Effectiveness
Given sufficient data (≥ 100 sent heads‑ups and ≥ 30 actions in the past 60 days) When insights are computed nightly Then the system recommends top 3 send windows per team and preferred channel with estimated lift and confidence interval And insights exclude users or teams with privacy opt‑outs and apply minimum cohort sizes to prevent re‑identification And recommendations are versioned with underlying sample sizes and last computed timestamp And changes in recommended window/channel are logged as insight_update events And A/B test outcomes (control vs variant) report absolute and relative conversion differences with p‑value

Handoff Watch

Lightweight checklist that tracks the ownership hand‑off (facilitator role, agenda finalization, links, recording prefs). If any step lags, it gently nudges the current and next owner with specific to‑dos and due times, so meetings don’t start with “who’s driving?” moments.

Requirements

Ownership Resolver & Rotation Sync
"As a recurring meeting participant, I want ownership to rotate automatically and visibly so that it’s clear who is responsible for each meeting’s preparation."
Description

Determine and maintain the “current” and “next” meeting owner for each event by syncing with TimeMeld’s shared equity scoreboard and meeting series rotation rules. Automatically assign facilitator ownership per occurrence, handle skips for PTO/OOO, and support manual delegation with an audit trail. Recompute ownership on event changes (reschedules, attendee changes), and expose resolved owners to Handoff Watch, nudges, and UI. Provide fallbacks when the scoreboard is unavailable (use last known owner or meeting creator) and guard against double-ownership. Expected outcome: accurate, timely assignment of responsibility that powers checklists and reminders without manual coordination.

Acceptance Criteria
Per-Occurrence Owner Resolution from Scoreboard & Rotation
Given a recurring meeting series with defined rotation rules and a shared equity scoreboard When a new occurrence is created or first detected by TimeMeld Then the system computes ownership within 30 seconds of detection And assigns exactly one Current Owner and one Next Owner for that occurrence And both assigned owners are eligible participants per series rules And Next Owner is distinct from Current Owner And the selection honors equity weighting and deterministic tie-breakers And the operation is idempotent under retries, yielding the same result for the same inputs And the assignment is persisted with occurrenceId, computation timestamp, and rule version
Automatic PTO/OOO Skip with Equity Preservation
Given a resolved Current Owner is marked OOO during the occurrence window (via OOO calendar event or org OOO status) When ownership is (re)computed within 24 hours before the meeting or upon OOO status change Then the system skips the OOO user and assigns the next eligible participant And the skipped user does not accrue ownership credit for that occurrence And the replacement is not OOO for the occurrence window And an audit entry records the skip reason, prior owner, new owner, and detector source And notifications are sent to both prior and new owners within 60 seconds And equity ordering for future occurrences is preserved (no long-term penalty to the skipped user) And if all eligible participants are OOO, assign the meeting creator as fallback and flag origin=fallback
Manual Delegation With Audit Trail and RBAC
Given an upcoming occurrence has a Current Owner When the Current Owner or an organization admin delegates ownership to an eligible attendee via UI or API Then the delegate becomes the Current Owner for that occurrence immediately And the delegate accrues equity credit for the occurrence; the original owner does not And a reversible audit trail entry captures occurrenceId, oldOwner, newOwner, actor, timestamp, reason, and source=manual And non-attendees or unauthorized users cannot delegate (returns 403) And exactly one Current Owner exists after delegation (no double-ownership) And delegation can be reverted by an admin or the delegator until the meeting start time, with a new audit entry
Recompute on Event Changes With Concurrency Safety
Given an occurrence has assigned owners When the event is rescheduled, duration changes, or attendee list changes Then the resolver re-evaluates owners within 60 seconds of change ingestion And if the Current Owner is no longer an attendee or becomes ineligible/OOO, reassign to the next eligible participant And if still eligible, retain the Current Owner unless a rotation rule explicitly requires change And recomputation creates an audit entry with before/after owners and change cause And the system enforces at-most-one Current Owner per occurrence via an atomic write (no double-ownership under concurrent updates) And Next Owner is recomputed and remains distinct from Current Owner
Fallback Resolution When Scoreboard Unavailable
Given the equity scoreboard service is unavailable or exceeds a 2-second timeout When an occurrence requires ownership resolution or validation Then the system assigns using fallback priority: lastKnownOwner -> meetingCreator And marks the assignment origin=fallback with a correlationId And schedules reconciliation within 10 minutes of scoreboard recovery And if reconciliation occurs before the meeting start and yields a different owner, update owners and notify impacted users And if the meeting has started or ended, retain the fallback assignment and log unreconciled state And all fallback and reconciliation actions are recorded in the audit trail
Ownership Exposure to Handoff Watch, Nudges, UI, and API
Given owners are resolved or updated for an occurrence When the assignment is committed Then Handoff Watch receives an owner-change event within 15 seconds And product nudges target the correct Current and Next Owners for checklist steps within 30 seconds And the UI displays Current and Next Owners for both series and specific occurrences consistently within 30 seconds And GET /events/{occurrenceId}/owners returns {currentOwner, nextOwner, origin, computedAt, ruleVersion} with p95 latency ≤ 300 ms And updates are eventually consistent across all surfaces within 30 seconds And removal of an owner from attendees immediately reflects in all surfaces after recomputation
Checklist Templates by Meeting Type
"As a team admin, I want reusable handoff checklists for each meeting type so that preparation is consistent without recreating steps every time."
Description

Provide configurable checklist templates per meeting type (e.g., standup, planning, retro) covering facilitator assignment, agenda finalization, links readiness, recording preferences, and optional steps (e.g., pre-reads, note-taker). Allow admins to define defaults, reorder steps, set conditional visibility, and specify due-time rules relative to the meeting start (e.g., agenda T-12h, links T-1h). Support per-series overrides and one-off edits while preserving the base template. Persist checklist instances per occurrence and keep them in sync when events are rescheduled. Expected outcome: standardized, ergonomic handoffs tailored to each team’s rituals.

Acceptance Criteria
Admin Creates Standup Template With Required and Optional Steps
Given I am an org admin And a meeting type "Standup" exists When I create a checklist template named "Standup Default" for meeting type "Standup" And I add steps: Facilitator assignment (required), Agenda finalization (required), Links readiness (required), Recording preferences (required), Pre-reads (optional), Note-taker (optional) And I set default values: Facilitator assignment = Rotating; Recording preferences = Do not record And I save the template Then the template is persisted with a unique ID and version And each step is stored with its required/optional flag and default value And the template is selectable for new "Standup" series and events
Admin Reorders Template Steps
Given an existing "Planning" template with steps in order [Facilitator assignment, Agenda finalization, Links readiness, Recording preferences] When I move "Links readiness" above "Agenda finalization" and save Then the stored step order becomes [Facilitator assignment, Links readiness, Agenda finalization, Recording preferences] And newly created checklist instances from this template reflect the new order And existing instances with 0% completion adopt the new order within the next sync And in-progress instances retain completed steps and reorder only the remaining steps
Conditional Visibility Rules Evaluate Correctly
Given a "Retro" template with a rule: Show "Note-taker" when attendees_count >= 5 When a retro event is created with 6 invitees Then the "Note-taker" step is visible on the checklist instance When the same event's invitees are reduced to 3 before start Then the "Note-taker" step becomes hidden on the instance And the visibility rule is re-evaluated on attendee changes until the meeting starts
Relative Due-Time Rules Computed in Event Timezone
Given a template with due-time rules: Agenda finalization at T-12h, Links readiness at T-1h, Recording preferences at T-2h And an event scheduled for 2025-10-15 10:00 in America/Los_Angeles When the checklist instance is created Then the due times are set to 2025-10-14 22:00, 2025-10-15 09:00, and 2025-10-15 08:00 in America/Los_Angeles respectively And if the event is rescheduled to 2025-10-15 13:00 in America/New_York (same UTC instant), the due times recalculate to 2025-10-14 13:00, 2025-10-15 12:00, and 2025-10-15 11:00 in America/New_York respectively
Per-Series Overrides Preserve Base and Inherit Updates
Given a base "Planning" template with steps [Facilitator assignment, Agenda finalization, Links readiness, Recording preferences] And a series "Platform Planning" configured to use this template When I add a series override step "Tech Risk Review" after "Agenda finalization" and set Recording preferences default = Record Then the base template remains unchanged And new and future checklist instances for "Platform Planning" include "Tech Risk Review" and the overridden default while inheriting all other base steps When the base template is later updated to add a new step "Customer Impact" at the end Then new instances for "Platform Planning" include "Customer Impact" unless explicitly excluded by the series override And precedence for conflicts is: occurrence override > series override > base
One-Off Occurrence Edits Are Isolated
Given a "Weekly Retro" series using a template And the next occurrence has a checklist instance created When I edit only that occurrence to remove "Pre-reads" and set "Links readiness" due-time rule to T-30m Then only that occurrence reflects these changes And the series configuration and base template remain unchanged And subsequent occurrences keep the original series/template configuration
Checklist Instance Persists and Syncs on Reschedule
Given a checklist instance for an event on 2025-11-03 10:00 America/Los_Angeles with steps where some are completed When the event is rescheduled to 2025-11-03 11:30 America/Los_Angeles Then the checklist instance retains the same instance ID and completed-step states And all pending steps' due times recompute relative to 11:30 And any conditionally visible steps are re-evaluated based on updated event metadata And no duplicate checklist instance is created
Smart Nudges with Timezone Guardrails
"As a facilitator on rotation, I want timely, respectful reminders with one-click actions so that I can finish prep without being spammed or interrupted after hours."
Description

Deliver targeted, actionable reminders to the current and next owner for each outstanding checklist item with clear to-dos, owners, and due times localized to the user’s timezone. Channels: in‑app, email, and Slack. Nudge cadence: upcoming (T-24h), soon (T-2h), imminent (T-15m), and overdue with gentle tone. Respect user quiet hours, working windows, and do-not-disturb, with automatic rescheduling to the next permissible window. Include one-click actions (mark done, open agenda doc, set recording pref) and snooze options. Batch multiple items into a single digest to reduce noise and avoid duplicate nudges across channels. Expected outcome: timely, respectful prompts that prevent last-minute scramble without notification fatigue.

Acceptance Criteria
Localized Due Times and One-Click Actions
Given a checklist item with absolute due time D and a recipient with timezone TZ When a nudge is rendered for that recipient in any channel Then the due time is displayed in the recipient's local time (TZ) with timezone abbreviation and local date when different from today Given a checklist item with available actions When a nudge is rendered Then the nudge includes Mark Done and context-appropriate CTAs (Open Agenda if link exists, Set Recording Preference when applicable) Given a nudge containing Mark Done When the recipient clicks Mark Done Then the item is marked complete within 2 seconds and all future nudges for that item are cancelled Given a nudge containing Open Agenda When the recipient clicks Open Agenda Then the agenda document opens to the correct URL in a new browser tab within 2 seconds Given a nudge containing Set Recording Preference When the recipient sets a preference via the nudge Then the preference is saved and visible in Handoff Watch within 2 seconds
Cadence Scheduling at T-24h, T-2h, T-15m, and Overdue
Given a checklist item with due time D and it remains incomplete When scheduling nudges Then sends are queued at D-24h, D-2h, D-15m, and at the first permissible time after D (overdue), subject to guardrails Given a scheduled cadence send When the item is completed before the send time Then that send is skipped and later sends are cancelled Given an item created or updated less than 24h or 2h before D When scheduling nudges Then only future applicable cadence sends are queued Given a checklist item's due time D changes When the change is saved Then remaining cadence sends are recalculated within 1 minute
Quiet Hours, Working Windows, and DND Guardrails with Auto-Reschedule
Given a scheduled nudge time S for a recipient When S falls within the recipient's quiet hours, outside their working window, or during active DND for the intended channel Then the nudge is deferred to the next permissible time within the recipient's working window and outside quiet hours/DND Given a deferred nudge delivered after due time D When it is sent at the next permissible time Then the message indicates the item is overdue Given multiple delivery channels with differing availability When selecting a channel for delivery Then the nudge uses the first available channel in the recipient's configured channel priority order
Cross-Channel Deduplication and Batched Digest
Given multiple outstanding checklist items for a recipient with cadence sends within a 5-minute window When preparing a send Then the items are batched into a single digest message for that cadence event and channel Given a cadence event for a recipient and multiple channels When a nudge is successfully delivered via the highest-priority available channel Then duplicate sends for the same cadence event are suppressed in other channels Given pending duplicate sends for a cadence event When the recipient opens or clicks any nudge for that event Then pending duplicates for that event are cancelled across all channels
Targeted Recipients and Dynamic Handoff Updates
Given an outstanding checklist item with a current owner A and next owner B When sending nudges Then A receives an actionable nudge listing their to-dos and due time, and B receives a heads-up nudge with their upcoming start time and first to-dos Given future scheduled nudges for an item When the item's ownership changes Then all future scheduled nudges are reassigned within 1 minute to the new owners and previous owners stop receiving them Given an owner without outstanding to-dos for an item When scheduling future nudges Then that owner does not receive further nudges for the item
Snooze Options and Suppression Behavior
Given a delivered nudge When the recipient selects Snooze 15m, 1h, or Until Next Working Window Then the next send for that item and recipient is rescheduled accordingly and respects guardrails Given a snoozed nudge for a recipient and item When other cadence events occur before the snooze expires Then additional sends for that recipient-item are suppressed until the snooze expires Given a snooze action taken in any channel When evaluating scheduled sends Then the snooze state is applied across all channels for that recipient and item Given an item is marked done during an active snooze When evaluating future sends Then all scheduled sends for that item are cancelled for all recipients
Auto-Artifact Linking & Validation
"As an attendee, I want meeting links and agenda docs ready and accessible so that we can start on time without hunting for the right materials."
Description

Automatically detect, attach, or create key meeting artifacts required by the checklist: calendar conferencing link (Google Meet/Zoom), agenda document (Notion/Confluence/Google Docs), and recording preferences. Validate presence and access permissions for invitees; suggest fixes when artifacts are missing or restricted. Offer quick-create from templates and set sharing to the attendee list by default. Enforce org policies where applicable (e.g., recording default for company‑wide all-hands). Surface validation errors in the handoff UI and nudge recipients with specific remediation steps. Expected outcome: meetings start with working links and accessible materials, reducing friction at kickoff.

Acceptance Criteria
Auto-Detect and Attach Conferencing Link
Given a calendar event with invitees and no conferencing link When Handoff Watch validates the event or the organizer opens the handoff UI Then TimeMeld proposes the default conferencing provider based on org/user settings and displays an 'Add link' action And when the organizer confirms, a valid conferencing link is created via the provider API and inserted into the event's conferencing field and description within 10 seconds And all invitees receive the updated invite And the 'Conferencing link' step status becomes Pass Given a calendar event with an existing conferencing link When validation runs Then TimeMeld verifies link validity via provider API (e.g., not deleted/cancelled) or HTTP reachability (200/3xx) And if invalid, the step is marked Fail and a 'Regenerate link' action is shown that replaces the link on confirmation Given a recurring event When a link is added or regenerated from Handoff Watch Then the change applies to the single occurrence by default, with an explicit option to apply to the entire series
Agenda Quick-Create From Template With Auto-Sharing
Given no agenda document is detected in the event description or Handoff Watch When the organizer selects 'Create from template' and a provider (Notion, Confluence, or Google Docs) Then TimeMeld creates a document from the org template named 'Agenda - {Event Title} - {YYYY-MM-DD}' in the configured workspace/folder And inserts the agenda link into the event description and Handoff UI within 10 seconds And grants edit access to the facilitator and comment/view access (per org default) to 100% of invitees, including external attendees if policy allows Given an agenda link already exists When validation runs Then TimeMeld confirms the document is reachable and that all invitees meet minimum access (view or comment) And if any attendee lacks access, the step is marked Fail and a 'Fix sharing' action is shown that updates permissions to the attendee list on confirmation Given org policy requires agendas for meetings with more than 3 attendees When such a meeting has no agenda Then the 'Agenda' step is marked Fail and 'Handoff complete' is blocked until an agenda is attached or created
End-to-End Artifact Access Validation For All Invitees
Given a meeting with a finalized attendee list When Handoff Watch runs validation Then a permission matrix is computed for each artifact (conferencing link, agenda doc) And 100% of invitees must have required minimum access (joinable link; document view/comment) And if any invitee is missing access, their names/emails and domains are listed with the specific deficiency And a one-click 'Grant access to attendees' action updates permissions and re-validates within 30 seconds Given external attendees are present and org policy restricts external sharing When validation detects missing access due to policy Then the step shows 'Request exception' and 'Share redacted copy' options per policy And selecting an option records an audit entry and updates status accordingly Given the organizer updates the attendee list When attendees are added or removed Then validation re-runs automatically and sharing updates are offered to keep 100% coverage
Recording Preference Capture And Policy Enforcement
Given the meeting type matches an org policy that requires recording (e.g., company-wide all-hands) When Handoff Watch loads Then 'Recording' is defaulted to On, the control is locked, and a policy tooltip explains the enforcement And the setting syncs to the conferencing provider (Zoom auto-record / Google Meet recording toggle) where supported Given the meeting type has no enforced policy When the organizer sets recording On or Off in Handoff Watch Then the preference is saved and reflected in the event description as 'Recording: On/Off' And if the provider supports pre-configured recording, the meeting is updated accordingly within 30 seconds; otherwise, a start-of-meeting reminder is scheduled for the facilitator Given the organizer attempts to disable recording on a policy-enforced meeting When they toggle Off Then an error is shown and the setting remains On, with an option to 'Request policy exception' that notifies the approver group
Inline Validation Errors With One-Click Remediation In Handoff UI
Given any artifact fails validation (missing, invalid, or restricted) When the handoff page is viewed Then the failing step displays an inline error banner with: concise cause, affected attendee count, timestamp, and a primary remediation button (e.g., 'Add link', 'Fix sharing', 'Regenerate') And the overall 'Handoff readiness' shows Not Ready and prevents marking complete until all critical steps pass Given the organizer clicks a remediation button When the action succeeds Then the step status changes to Pass within 10 seconds without a page refresh And a success toast is shown and the audit log records the action with actor, time, and artifact IDs
Nudge Owners When Artifact Steps Lag Or Are Predicted Late
Given due times for each artifact step (e.g., agenda due 24h prior, conferencing link 2h prior, recording 1h prior) When a step is overdue or predicted to miss its due time based on current progress Then TimeMeld sends a nudge to the current owner via Slack DM and email, including specific to-dos and one-click remediation links And CCs the next owner if the facilitator role will change before the meeting And nudges are throttled to at most once every 4 hours per step and cease when the step status is Pass And timestamps in messages are localized to the recipient's timezone And all nudges are recorded in the audit trail with delivery status
Handoff Panel & Quick-Complete UI
"As a participant about to start a meeting, I want a clear panel to finalize any remaining prep in seconds so that we don’t waste time figuring out who’s driving."
Description

Embed a panel in TimeMeld’s event view (and lightweight modal from calendar integrations) showing owner context, checklist items, due times, and completion state. Support inline completion, comments, reassignment, and attaching artifacts. Provide a quick-start wizard at meeting start if items remain open, allowing rapid fixes (e.g., create agenda, toggle recording) in under 60 seconds. Optimize for desktop and mobile, with accessible keyboard interactions and screen-reader support. Reflect real-time updates from nudges and collaborators, and lock historical state post‑meeting while preserving edits with timestamps. Expected outcome: a fast, intuitive surface to complete handoff tasks without leaving the flow.

Acceptance Criteria
Event View and Calendar Modal Panel Visibility & Parity
1) Given a signed-in user opens a TimeMeld event view, When the page loads, Then the Handoff Panel renders within 1000 ms and shows current owner, next owner, checklist items with completion states, due times in the user’s local timezone, and completion summary. 2) Given the user opens the event via a supported calendar integration modal, When the modal loads, Then the Handoff Panel displays the same fields and states as the TimeMeld event view within 1000 ms and fits the modal layout without horizontal scroll. 3) Given checklist items exist, When the panel loads, Then items are ordered by due time ascending, overdue items are visually flagged, and hovering/focus reveals exact timestamps. 4) Given no checklist is configured, When the panel loads, Then it shows an empty state with a clearly labeled action to initialize the handoff checklist.
Inline Completion, Commenting, Reassignment, and Attachments
1) Given a user with edit permission, When they toggle an item’s completion inline, Then the state updates immediately, persists to the server, shows who updated and when, and is undoable for 5 seconds. 2) Given a user opens the comment input on an item, When they submit a comment, Then it appears in-thread with author, timestamp, and supports @mentions with notifications to mentioned users. 3) Given a user opens the assignee control on an item, When they reassign to a teammate, Then the new assignee is saved, the previous assignee is recorded in history, and a notification is sent to the new assignee. 4) Given a user attaches an artifact (pastes a link or uploads a file), When the attachment is saved, Then it appears with a type icon, filename, and open action; invalid links or failed uploads show inline error with retry and do not create dangling entries. 5) Given a transient network error occurs, When the user performs any inline action, Then the UI shows an optimistic state with spinner and reverts with an error toast if persistence fails, without duplicating actions.
Start-Time Quick-Start Wizard for Open Items
1) Given the current time is within 5 minutes before to 5 minutes after the scheduled start and there are open handoff items, When a participant opens the event, Then a non-blocking quick-start wizard prompt is shown with the count of open items. 2) Given the user launches the wizard, When they choose “Create agenda”, Then the system creates or links an agenda in ≤2 clicks and marks the agenda item complete with a link. 3) Given the user toggles recording preferences in the wizard, When a conferencing integration is connected, Then the recording flag is set on the provider; otherwise, the preference is stored and clear guidance is shown without blocking completion. 4) Given the wizard is used to resolve up to three core items (agenda, facilitator, recording), When tested on p50 target devices, Then 95% of users can complete these within 60 seconds end-to-end. 5) Given the user dismisses the wizard, When open items remain and it is still within the start window, Then the wizard can be re-opened from the panel.
Responsive Layout and Accessibility (Keyboard & Screen Reader)
1) Given desktop (≥1024px) and mobile (≤768px) viewports, When the panel renders, Then it adapts without horizontal scroll, maintains touch targets ≥44px, and uses text size ≥14px equivalent. 2) Given a keyboard-only user focuses the panel, When navigating, Then all actionable elements are reachable via Tab/Shift+Tab in logical order with visible focus indicators; Enter/Space activates primary actions and Esc closes popovers/modals. 3) Given a screen reader is active, When the panel loads and updates, Then controls expose correct roles, names, and states; dynamic updates announce via aria-live polite without interrupting user context. 4) Given color contrast checks, When evaluated, Then all text and interactive elements meet WCAG 2.2 AA contrast ratios. 5) Given due times are rendered, When read by assistive tech, Then both absolute time with timezone and relative status (e.g., “due in 2 hours” or “overdue by 10 minutes”) are announced.
Real-Time Sync and Collaboration
1) Given two collaborators view the same event, When one updates any checklist field (state, assignee, comment, attachment), Then the other sees the change within 2 seconds and a transient activity indicator identifies the actor. 2) Given simultaneous edits to the same field, When both are saved, Then last-writer-wins is applied and a non-destructive activity log entry records both edits; the overwritten client receives a toast explaining the resolution. 3) Given a nudge notification includes a deep link, When the recipient completes an item from that link, Then all open clients reflect the new state within 2 seconds. 4) Given the user is offline, When they perform actions, Then actions queue locally with badges indicating pending state and automatically sync in order on reconnect; conflicts resolve per rule 2 with user-visible notices.
Post-Meeting Lock and Audit Trail
1) Given the event reaches its scheduled end time plus a 10-minute grace period, When the panel next refreshes or receives a time tick, Then all checklist items become read-only and a “Meeting locked” banner appears. 2) Given an authorized admin/editor needs to correct records, When they invoke post-lock edit, Then they must supply a reason; the system saves an amendment without altering the original record and displays both in history. 3) Given a user opens the history view, When loaded, Then a chronological audit timeline shows who changed what and when, including before/after values for state, assignee, due time, and attachments, with CSV export available. 4) Given comments are posted after lock, When submitted, Then they persist and appear in history but cannot change completion states.
Permissions, Errors, and Safeguards
1) Given a viewer without edit rights, When they open the panel, Then all fields are readable but edit controls are disabled with explanatory tooltips and no state changes can be made. 2) Given an attachment upload fails or a link is invalid, When the user attempts to save, Then an inline error is shown with retry; partial uploads are cleaned up and no broken attachment entries remain. 3) Given an integration permission is missing (e.g., recording control), When the user attempts the action, Then the UI presents a connect flow or non-blocking fallback guidance and logs the attempt without erroring the whole panel. 4) Given a server or network error during inline actions, When the error occurs, Then optimistic UI updates roll back, the action is not duplicated, and the user can retry. 5) Given backend unavailability, When the panel cannot reach services, Then a cached read-only view renders if available with a clear status message and automatic retry/backoff.
Audit Trail, Metrics & Escalations
"As an ops lead, I want visibility and escalation on stalled handoffs so that critical meetings aren’t jeopardized by missed preparation."
Description

Record who completed each checklist item, when, and via which channel, along with ownership changes and delegations. Provide series‑level metrics (completion rate, average lead time, overdue rate, nudge effectiveness) and export/reporting per team. Define SLAs per step (e.g., agenda by T-12h) and escalate overdue critical items to a backup owner or team lead with context. Support retention controls and privacy scopes (restrict visibility to invitees/admins). Expected outcome: visibility into preparation health, actionable improvements, and reliable backups when handoffs stall.

Acceptance Criteria
Checklist Item Audit Logging
Given a checklist item is completed via UI, Slack, or email, When completion is submitted, Then the audit log records item_id, series_id, completer_user_id, role, channel, UTC timestamp, and previous_status. Given a completed item is edited, When changes are saved, Then a new immutable audit entry is appended capturing field_deltas, editor_user_id, UTC timestamp, and optional reason without overwriting prior entries. Given multiple completion events occur within 1 second, When events are processed, Then ordering is preserved and duplicates are prevented using idempotency keys. Given an authorized viewer opens item history, When the last 50 entries are requested, Then they load in under 500 ms and additional entries are accessible via pagination.
Ownership Change & Delegation Capture
Given facilitator ownership is changed or delegated, When the change is confirmed, Then the audit trail records from_user_id, to_user_id, initiator_user_id, reason, effective_time, and scope (single vs series) and preserves previous owner mapping. Given a delegation with an expiry time exists, When the expiry is reached, Then ownership reverts to the prior owner automatically and an audit entry is created. Given an unauthorized user attempts to change ownership, When the request is made, Then a 403 is returned and no ownership-change audit entry is created (security log only).
Series-Level Preparation Metrics
Given a meeting series with 5 or more past instances in the selected range, When metrics are requested, Then the API returns per-step: completion_rate_before_start (%), average_lead_time_hours, overdue_rate (% past SLA), and nudge_effectiveness (% resolved within 4h of first nudge and median_resolution_time_after_nudge). Given fewer than 3 instances exist in range, When metrics are requested, Then the response flags insufficient_data for affected metrics and omits misleading aggregates. Given daylight saving transitions occur, When lead times are computed, Then values are normalized to the scheduled start in the series timezone with UTC storage for consistency.
Team Export & Reporting
Given a team admin requests an export for a date range and series selection, When the export is generated, Then CSV and JSON files are available containing step-level metrics, audit entries (with fields redacted per privacy scope), and summary stats, plus metadata including row_count and checksum. Given the export size exceeds 50,000 rows, When the export is requested, Then it runs asynchronously, notifies the requester on completion, and completes within 2 minutes at the 95th percentile. Given a non-admin requests a team-wide export, When access is evaluated, Then the request is denied unless restricted to series where the requester is an invitee.
SLA Definition & Enforcement per Step
Given SLAs are configurable per checklist step as relative offsets (e.g., T-12h), When a series is created or edited, Then default SLAs are applied and may be overridden by the series owner within a validated range (T-72h to T-15m). Given an SLA exists for a step, When current time passes the SLA and the step remains incomplete, Then the step status becomes overdue and the breach timestamp is recorded. Given a step is completed, When completion is logged, Then SLA outcome is marked met or breached and stored for reporting.
Escalation of Overdue Critical Items
Given a critical step is overdue, When the first escalation triggers, Then a nudge is sent to the current owner via their preferred channel and an escalation notice is sent to the backup owner or team lead including: step, SLA due time, current owner, last activity, links to complete, and next meeting start time. Given no backup owner is configured, When escalation triggers, Then the escalation targets the series team lead. Given the item remains overdue after the configured interval (default 4h), When subsequent escalations are considered, Then the next-level escalation is sent and duplicates are suppressed within a 2h window. Given the item is completed, When completion is recorded, Then all pending escalations and reminders for that item are canceled.
Retention Controls & Privacy Scopes
Given retention is set to N days, When an audit entry exceeds N days, Then it is deleted or anonymized per policy and excluded from exports and metric recalculations. Given privacy scope is restricted to invitees and admins, When a non-invitee attempts to view audit details, Then access is denied and sensitive fields are redacted in aggregated exports and reports. Given a user requests erasure of personal data, When the request is processed, Then identifying fields in audit entries are pseudonymized while preserving aggregate metrics integrity.

QuickSwap

Instant swap from DM/email with auto‑suggested eligible alternates based on availability, timezone burden, and rotation fairness. One tap updates the invite’s role badges, equity scoreboard, and reminders—resolving conflicts without back‑and‑forth or bias.

Requirements

Inline QuickSwap from DM/Email
"As a remote team member, I want to trigger a QuickSwap directly from Slack or email so that I can hand off my meeting role instantly without switching apps."
Description

Provide actionable QuickSwap in Slack/Teams and email. Implement message actions and signed deep links that open a minimal web view preloaded with meeting context and the role to swap. Ensure frictionless SSO with Slack/Microsoft/Google and a responsive layout. Validate initiator permissions and meeting edit rights before rendering options. Complete the trigger-to-confirmation flow in under 10 seconds median with graceful degradation to a fallback web flow if chat actions are unavailable.

Acceptance Criteria
Slack/Teams Message Action QuickSwap Launch
Given a Slack or Microsoft Teams message generated by TimeMeld contains a QuickSwap action, When the user selects the QuickSwap action, Then a minimal QuickSwap web view opens within 2 seconds preloaded with meeting ID, participant list, and the role to swap. And if the chat client supports in-app browsers, Then the view opens in-app; otherwise it opens in the system browser with the same preloaded context. And the action request returns HTTP 200 within 1 second to the chat platform callback to avoid timeouts.
Email QuickSwap Deep Link Security
Given a TimeMeld email includes a QuickSwap link for a meeting, When the recipient clicks the link, Then a minimal QuickSwap web view opens preloaded with meeting ID, participant list, and the role to swap. And the link is a signed, single-use URL that expires after 15 minutes; attempts after expiry return 410 with an "Link expired — request a new link" prompt. And any tampering with parameters or signature returns 403 with no meeting context disclosed. And only intended, eligible recipients can proceed; others receive 403 with guidance to request access.
Frictionless SSO and Responsive Web View
Given the user has an active Slack, Microsoft, or Google session in the same browser, When the QuickSwap web view opens, Then the user is authenticated via that provider without additional credential prompts within 2 seconds. And if no session exists, When the user chooses a provider, Then OAuth completes and returns to the QuickSwap view preserving meeting context without data loss. And the web view is responsive: no horizontal scroll at widths 320–1440px; primary actions are visible without scrolling on a 667px height viewport; all actionable controls have visible focus states.
Permission Validation Before Rendering Options
Given a user initiates QuickSwap from chat or email, When the server validates identity and meeting edit rights, Then if the user lacks required permissions, no swap options are rendered and the user sees "You don't have permission to swap roles for this meeting" with a link to request access. And if the user has required permissions, Then eligible swap options are rendered; the authorization decision is logged with user ID, meeting ID, and timestamp. And authorization is enforced server-side for both chat actions and deep links.
Eligible Alternate Suggestions and Ranking
Given a meeting with defined participants and constraints, When QuickSwap options are displayed, Then only eligible alternates are shown (available, not OOO, no hard conflicts, within configured work hours). And suggestions are ranked by a composite score that weighs availability, timezone burden, and rotation fairness; the highest score appears first. And each suggestion includes a brief reason (e.g., "lowest burden, maintains fairness") and a burden delta indicator. And at least 3 suggestions are shown when 3 or more eligible alternates exist; otherwise a "No more eligible alternates" message is displayed.
One-Tap Apply Updates Across Calendar and Scoreboard
Given a user selects a suggested alternate, When they tap Confirm Swap, Then the connected calendar event (Google/Microsoft) is updated with the new role within 5 seconds of confirmation. And role badges in the invite are updated, the equity scoreboard is adjusted, and reminders retarget the new role holder. And all affected attendees receive updated invites/notifications; no duplicate events are created. And the operation is atomic: on partial failure, changes are rolled back and an actionable error with retry is shown.
Performance SLA and Fallback Flow
Given a QuickSwap is initiated via chat action or email link, When the user completes the flow, Then the median (p50) time from trigger to confirmation is ≤ 10 seconds measured server-side. And if chat actions are unavailable due to platform outage, permissions, or app disablement, Then the user is presented with a fallback web flow link that completes the same validation and update steps successfully. And the fallback mode is indicated in the UI and yields the same outcome quality as the standard flow.
Role-Aware Alternate Suggestion Engine
"As a product manager, I want the system to suggest fair, available alternates for my role so that the swap is unbiased and doesn’t overburden teammates."
Description

Compute and rank eligible alternates for the vacated role using live calendar availability, timezone ergonomics scoring (local-hours burden and streak avoidance), and rotation fairness (equity credits/debits and recent ownership). Filter out conflicts (PTO, focus blocks, DND hours, organizer constraints), respect team eligibility lists, and enforce max-frequency caps to avoid repeated inconvenient assignments. Return a short list with per-candidate justifications and deterministic tie-breakers for auditability. Expose a stateless API consumable by Slack/Email QuickSwap UI and in-app flows.

Acceptance Criteria
Filter by Live Availability and Conflicts
Given a vacated role, a meeting start time and duration, and a policy snapshot defining conflict sources (PTO/OOO, focus blocks, DND hours, organizer constraints) When the engine evaluates team members’ calendars and profiles Then it shall include only candidates with continuous free time covering the full duration and marked available across connected calendars And it shall exclude any candidate with overlapping PTO/OOO events, focus blocks (per policy), DND hours from profile, organizer exclude constraints, or double-bookings And each inclusion/exclusion decision shall be captured with a reason code and details in the candidate’s justification
Timezone Ergonomics Scoring and Streak Avoidance
Given policy settings ergonomic_workday_local=[08:00,18:00], early_penalty=10/30m, late_penalty=10/30m, overnight_penalty=40/30m, streak_window=5 meetings, max_inconvenient_streak=1 When scoring each eligible candidate for a meeting in their local timezone Then compute ergonomics_score in [0,100] with deductions per policy penalties And demote any candidate exceeding max_inconvenient_streak within the streak_window to the bottom of the shortlist And include ergonomics_score and streak history in each candidate’s justification
Rotation Fairness via Equity Credits/Debits
Given an equity scoreboard snapshot with per-candidate credits/debits and last_ownership_at timestamps, and policy weights fairness_weight=0.6, ergonomics_weight=0.4, recency_half_life=14d When ranking eligible candidates Then compute total_score = 100*(fairness_normalized*0.6 + ergonomics_normalized*0.4) - recency_penalty And rank candidates so that those with higher equity debt (owe coverage) sort ahead of those with credits, subject to ergonomics and recency penalties And include score breakdown, equity position, and recency factors in the justification
Max-Frequency Caps and Bias Prevention
Given policy caps max_frequency_per_role=2 within rolling_window=14d and per_person_global_cap=3 within 14d When generating alternates Then exclude any candidate whose recent assignments exceed either cap at evaluation time And include rejection reason max_frequency_cap with current counts and window in audit data
Honor Eligibility Lists and Organizer Constraints
Given a role eligibility list and any organizer constraints (e.g., excluded regions, required skills) When generating alternates Then consider only candidates present in the role’s eligibility list and not violating organizer constraints And exclude candidates flagged not_eligible with reason codes (e.g., not_in_role_list, violates_constraint) in justification
Deterministic Ranked Shortlist with Justifications
Given deterministic tie-breakers priority=[equity_debt_desc, ergonomics_score_desc, recent_ownership_asc, timezone_offset_penalty_asc, candidate_id_asc] and max_results=N When producing the shortlist Then return up to N candidates ordered by the tie-breaker priority And for exact ties across all sort keys, order by candidate_id ascending And include for each candidate a justification containing reasons[], score_breakdown, eligibility_flags, and tie_breaker_path And identical inputs (including policy snapshot) yield identical outputs within a 60s clock skew
Stateless API Contract for QuickSwap Surfaces
Given POST /v1/alternates/suggest with body {request_id, role_id, meeting_start, duration_minutes, participants[], policy_snapshot_id, max_results} and Bearer auth When invoked with identical payload and policy_snapshot within 5 minutes Then the response is identical (idempotent) and the service remains stateless with decisions derived solely from inputs and referenced snapshots And P95 latency <= 500ms and P99 <= 900ms for teams <= 50 members And return 400 on invalid input (with error codes), 401 on auth failure, 404 on missing snapshot, 503 on upstream timeout with Retry-After And response includes {candidates[], justification_version, computation_id, generated_at} and no PII beyond candidate_id and display_name
One-Tap Calendar and Reminder Update
"As an organizer, I want the invite and reminders to update with one tap so that all participants have the correct roles and notifications with minimal churn."
Description

Upon alternate selection, atomically update the existing calendar event via Google/Graph APIs without changing the event ID, swap role badges in title/description, adjust attendee list, and transfer host/presenter privileges if required. Regenerate reminder schedules for the new assignee and notify impacted participants while suppressing duplicates. Ensure idempotency, retries with exponential backoff, and rollback if any downstream step fails.

Acceptance Criteria
Atomic Update Preserves Event Identity Across Providers
Given an existing calendar event with ID E and iCal UID U on Google Calendar or Microsoft 365, and a selected alternate assignee When the user confirms One-Tap update via QuickSwap Then the provider event ID E and iCal UID U remain unchanged after the update And the update is applied atomically so that any read between start and completion observes either the old state or the fully updated state, never a partial state And the provider version (ETag/sequence/changeKey) changes exactly once And the operation returns success (2xx) from the provider API
Role Badge Swap in Event Title and Description
Given an event whose title and description contain role badges for Host and Presenter When the alternate is selected to replace a specific role Then the event title and description reflect the new role assignment using the standard badge format And exactly one instance of the replaced role badge is updated; no duplicate or stale badges remain And no unrelated text in the title or description is modified And structured metadata for roles (if present) is updated consistently with the displayed badges
Attendee List Adjustment and Privilege Transfer
Given the swap requires removing attendee A and assigning attendee B to a role that grants meeting privileges When One-Tap update executes Then attendee A is removed or demoted from the role and attendee B is added with no duplicate attendees in the list And attendee B’s RSVP status is set to needsAction or preserved if previously accepted per provider rules And meeting host/presenter privileges are transferred to attendee B in the provider’s meeting settings And the organizer field remains unchanged unless explicit host transfer is supported and requested And the changes propagate to the provider within 60 seconds
Reminder Regeneration and Duplicate Suppression
Given the previous assignee had provider-native reminders and TimeMeld reminders scheduled When the role is reassigned via One-Tap update Then all reminders for the previous assignee related to the event are canceled And a new reminder schedule is generated for the new assignee according to policy and timezone settings And no participant receives duplicate reminders for the same trigger time And reminder deduplication is keyed by event ID, recipient, and trigger time
Participant Notification Without Redundancy
Given participants are impacted by the reassignment When the update completes Then impacted participants receive a single consolidated notification via their preferred channel within 60 seconds And duplicate provider update emails or invites are suppressed where possible And participants not impacted by the reassignment receive no notification
Idempotent Re-Submission with Exponential Backoff
Given the same One-Tap update request may be retried due to client or network issues When the server receives multiple requests with the same idempotency key within 24 hours Then only the first request mutates state and subsequent requests return a no-op result with the final state And on transient errors (HTTP 5xx or 429) the system retries with exponential backoff (base delay >= 500 ms, factor ~2, jitter) up to a maximum of 5 attempts And retries are logged with attempt count and outcome
Transactional Rollback on Downstream Failure
Given any downstream step (privilege transfer, reminders, or notifications) fails after the calendar provider update When failure is detected Then the system rolls back the event to its pre-swap state within 60 seconds And no participant retains privileges or reminders inconsistent with the rolled-back state And the initiator is informed of the failure with a correlation ID And an audit record contains before and after snapshots and the rollback reason
Equity Scoreboard Sync and Rotation
"As a team lead, I want the equity scoreboard to update when a swap happens so that rotation fairness remains accurate and transparent."
Description

Recalculate equity scores and rotation standings immediately after a swap, applying weights for burden, time-of-day, and role criticality. Update the shared scoreboard in TimeMeld, reflect changes in the meeting’s sidebar widget, and persist a delta entry with before/after values. If ownership rotation is due, update the next rotation queue accordingly. Provide read-only APIs and webhooks to propagate changes to dashboards.

Acceptance Criteria
Immediate Scoreboard Recalculation After QuickSwap Confirmation
Given a swap is confirmed via QuickSwap for a scheduled meeting When the swap confirmation event is saved Then equity scores for all participants impacted by the meeting are recalculated using the active weighting configuration (burden, time-of-day, role criticality) And the recalculation is atomic and idempotent per swap_id And the updated equity scores are persisted within 5 seconds And the TimeMeld shared equity scoreboard reflects the new scores within 5 seconds of persistence And no participant’s score changes if they are not impacted by the swap
Weighting Configuration Application and Deterministic Output
Given an organization has default weighting values and optional org-level overrides When recalculating scores after a swap Then burden, time-of-day, and role criticality weights are each applied exactly once per affected participant And org-level overrides supersede defaults; missing values fall back to defaults And the same inputs and configuration always produce the same outputs (deterministic) And scores are rounded to two decimal places using half-up rounding And the computation run records the versioned config_id used for traceability
Meeting Sidebar Widget Reflects Score and Role Changes
Given a user is viewing the meeting’s sidebar widget in TimeMeld When a swap is confirmed for that meeting Then the widget updates in-place without page reload within 5 seconds And role badges reflect the new roles/ownership And equity deltas (before → after) are displayed for each affected participant And the displayed values match the persisted delta entries for the same swap_id
Delta Audit Entry Persistence and Retrieval
Given a swap is confirmed When the recalculation completes Then a delta entry is created per affected participant capturing before_score, after_score, before_rotation_position, after_rotation_position, meeting_id, swap_id, actor_id, and occurred_at And the delta entry is immutable once created And it is persisted within 5 seconds and retrievable via read-only APIs by swap_id and by meeting_id And the delta entry correlates one-to-one with the sidebar widget’s displayed deltas
Ownership Rotation Queue Update When Due
Given a rotation policy is enabled for the meeting’s ownership role And the updated scoring/rotation logic determines rotation is due at this swap When the swap is confirmed Then the next rotation queue is updated atomically with the score changes And the new owner is reflected in role badges and in the rotation queue order And no rotation occurs when not due And a rotation.updated delta is included in the audit entries when rotation changes
Read-Only APIs and Webhooks Propagate Changes
Given an authenticated client with read-only scope When a swap-driven update occurs Then GET /scoreboard?meeting_id={id} and GET /deltas?swap_id={id} return updated data within 5 seconds of persistence And responses include ETag and Last-Modified headers for cache validation And unauthorized or insufficient scope requests return 401/403 as appropriate And webhook events equity.score.updated and rotation.queue.updated are delivered to subscribed endpoints within 10 seconds, signed with the configured secret, retried with exponential backoff on 5xx, and contain a unique event_id for idempotency
Concurrent Swaps Consistency and Conflict Handling
Given two swap requests for the same meeting occur within a short interval When they are processed by the system Then operations are serialized per meeting_id so only one recalculation/rotation commit succeeds at a time And losing transactions are retried against the latest state or rejected with 409 Conflict without partial updates And the scoreboard, sidebar widget, delta entries, and rotation queue remain consistent and reflect only the committed transaction
Approval Rules and Guardrails
"As an operations lead, I want approval rules to apply to sensitive swaps so that policy and compliance are enforced without blocking routine changes."
Description

Define policies for when a QuickSwap is auto-approved versus requiring organizer or lead approval (e.g., last-minute swaps, burden thresholds exceeded, critical roles). Block swaps that violate compliance constraints or repeat the same participant burden within a cooldown window. Present lightweight approval prompts in Slack/Email with expiration timers, and auto-approve if SLA is unmet and policy permits. Log every decision with rationale.

Acceptance Criteria
Auto-Approval Within Policy Limits
Given a QuickSwap request where all candidates meet eligibility and compliance And the timezone-burden delta is <= the configured auto-approve threshold And the request does not occur within the configured last-minute window And no critical-role approval rule is triggered When the request is submitted Then the system auto-approves the swap within the configured processing-time SLA And updates the calendar invite, role badges, reminders, and equity scoreboard atomically And sends confirmation notifications to the organizer and impacted participants And records an audit entry with decision=auto-approved, policyVersion, evaluated metrics, and timestamp
Approval Needed for Last-Minute or Critical Role
Given a QuickSwap request triggers any approval rule (last-minute window, critical role, burden delta above auto-approve threshold but within manual-approval range) When the request is submitted Then Slack and Email approval prompts are sent to the designated approver(s) with Approve and Decline actions and an expiration timer And prompts include swap summary, burden deltas, cooldown indicators, and policy references And only authorized approvers can act; all others see read-only And no calendar or scoreboard changes occur before approval When an approver Approves within the SLA Then the swap is applied and notifications are sent When an approver Declines within the SLA Then the swap is not applied and decline notifications are sent When the SLA expires Then if policy permits, the system auto-approves; otherwise it auto-declines And the audit log reflects the path taken and approver identity when applicable
Compliance Violation Blocking
Given a QuickSwap request violates any configured compliance constraint When the request is submitted Then the request is blocked And the user receives a non-approvable error showing the violated constraint identifiers And no approval prompts are sent And no changes are made to the calendar, role badges, reminders, or equity scoreboard And an audit entry is recorded with decision=blocked, violatedConstraints, and timestamp
Cooldown Window Prevents Repeated Burden
Given participant P incurred an inconvenient time slot within the configured cooldown window And the proposed swap would assign P another inconvenient slot within that window When the request is submitted Then the system enforces the configured cooldown action And if the action is block, the request is rejected and alternative eligible candidates are suggested And if the action is require-override, the request enters approval with an override-required reason and cannot be auto-approved And all outcomes are logged with cooldown metrics and policy references
Post-Approval Updates Are Atomic and Consistent
Given a QuickSwap request is approved (auto or manual) When the swap is applied Then the calendar invite, role badges, reminders, and equity scoreboard are updated in a single transaction And fairness metrics and rotation history are recalculated and persisted And outbound notifications include the updated fairness delta Given a QuickSwap request is declined or blocked Then no updates are applied and existing artifacts remain unchanged
SLA Expiration Behavior
Given an approval prompt with an SLA of N minutes is outstanding When the SLA timer expires Then if the policy rule is auto-approve-on-expiry and no compliance violations exist, the swap is auto-approved And if the policy rule is auto-decline-on-expiry, the swap is auto-declined And approver(s) and requester receive an outcome notification with the elapsed SLA and rule applied And the audit log captures SLA start/end timestamps, elapsed duration, and outcome
Audit Log Completeness and Traceability
Given any QuickSwap decision is made Then the system stores an immutable audit record containing: requestId, meetingId, policyVersionId, rule evaluations and results, burden scores, critical-role flags, cooldown context, compliance check outputs, decision, actor (auto or user), approver identity and comment (if applicable), timestamps for request/decision/notifications, source channel, and traceId And audit records are queryable by time range, policy version, user, and meetingId And exported logs redact fields marked as sensitive per configuration
Swap Audit Trail, Notifications, and Undo
"As an engineer, I want a clear audit trail and a brief undo option so that mistakes can be corrected and changes can be reviewed later."
Description

Create an immutable audit trail recording initiator, timestamp, decision path, candidate list, selected alternate, and calendar changes. Send a confirmation in the originating DM/email thread and update the meeting thread in Slack/Teams. Provide a time-boxed undo (e.g., 10 minutes) that restores prior state across calendar, role badges, reminders, and equity scoreboard. Offer CSV export and admin search.

Acceptance Criteria
Immutable Audit Trail Captures Swap Metadata
Given a QuickSwap is confirmed When the swap is finalized Then the system writes an append-only audit record within 2 seconds containing: swap_id (UUID), meeting_id, initiator_user_id, initiator_channel (Slack|Teams|Email), original_attendee_id, selected_alternate_user_id, candidate_list [user_id, rank, availability_window, timezone_burden_score, rotation_fairness_score], decision_path [step, reason, timestamp], calendar_changes [adds, removals, role_badge_deltas, reminders_deltas], equity_scoreboard_delta, request_timestamp_utc, confirmation_timestamp_utc, result (confirmed) And the record includes a content_hash and previous_hash, forming a tamper-evident chain And any attempt to update or delete the record via APIs returns HTTP 403 with no mutation And reading the record by swap_id returns exactly the stored values and hash verifies integrity
DM/Email Confirmation In-Thread After Swap
Given a swap is confirmed from a DM or email thread When confirmation is processed Then a confirmation message is posted to the originating thread within 5 seconds containing: meeting title, start time in originator’s local time and UTC, original→alternate mapping, updated role badges, equity scoreboard delta summary, Undo link with remaining time, audit link, and swap_id correlation code And if posting fails, a retry with exponential backoff occurs up to 3 times and failure is logged in the audit with result=notify_failed And the Undo link is unique, single-use per action, and expires exactly at T+10 minutes
Slack/Teams Meeting Thread Update After Swap
Given the meeting has a Slack/Teams thread When a swap is confirmed Then the meeting thread receives an update message within 5 seconds tagging the affected users, showing new role badges, updated participant list, and a timestamped “Swap applied” marker with swap_id And the meeting’s associated metadata (topic header or pinned block) is updated to reflect the new attendee list within 10 seconds And if no thread exists, no message is posted and the audit records thread_absent=true
Time-Boxed Undo Restores Prior State
Given a swap was confirmed less than 10 minutes ago When the Undo action is invoked Then the system atomically restores: calendar invites (remove alternate, re-invite original), role badges, reminders, and equity scoreboard to the exact pre-swap state within 15 seconds And a reversal audit record is appended linking to the original swap_id with result=undone and includes restoration deltas And notifications are posted to the origin DM/email thread and the meeting thread indicating “Swap undone” with updated details And subsequent Undo attempts for the same swap return 409 Conflict idempotently without side effects And if the Undo is invoked after 10 minutes, the request is rejected with 410 Gone and a deep link to initiate a new swap And if the meeting was canceled after the swap, Undo returns 409 Conflict with reason=meeting_canceled and no state change
Admin Audit Search and Access Control
Given an authenticated org admin is on the Audit page When they query by any combination of: date range, initiator_user_id, meeting_id, participant_id, channel, result status, decision_path.reason, or swap_id Then results return within 1000 ms for ≤10k records and are correctly filtered, sorted by confirmation_timestamp_utc desc, and paginated (default 50/page) And non-admin users receive HTTP 403 and no data And selecting a result opens the full audit details view matching the stored record and passing hash verification
CSV Export of Swap Audits
Given an authenticated org admin requests a CSV export for a date range When the export is generated Then the CSV contains headers and fields: swap_id, meeting_id, initiator_user_id, initiator_channel, original_attendee_id, selected_alternate_user_id, confirmation_timestamp_utc, request_timestamp_utc, result, decision_path_json, candidate_list_json, calendar_changes_json, equity_scoreboard_delta_json, content_hash, previous_hash And timestamps are ISO 8601 UTC, fields are UTF-8, values with commas are quoted, and line endings are LF And the export file is available via a pre-signed URL valid for 24 hours and includes a detached SHA-256 checksum file And exports over 100k rows stream without timeouts; progress updates are emitted; final row count matches query count

Auto‑Rotate Failover

If the upcoming owner hasn’t confirmed by the deadline, TimeMeld auto‑assigns the next fair facilitator, notifies stakeholders, and logs the equity adjustment. It respects PTO/travel and quiet hours, ensuring continuity without heroics.

Requirements

Owner Confirmation Deadline & Auto-Trigger
"As a remote team member, I want the facilitator to auto-rotate at a clear, configurable deadline if the current owner hasn’t confirmed so that meetings stay on track without last-minute scrambling."
Description

Provide a configurable confirmation deadline for each meeting or series (e.g., X hours/days before start, owner’s local timezone). Send escalating reminders to the assigned owner ahead of the deadline. If not confirmed by cutoff, automatically trigger failover without manual intervention. The trigger must be idempotent to avoid duplicate rotations, respect business days and regional holidays, and support per-series overrides. The system should expose deadline state in the UI and via webhook for observability and integrate with TimeMeld’s scheduler so the failover executes before invite updates and notifications. Expected outcome: meetings never stall on unconfirmed ownership and transitions happen predictably and on time.

Acceptance Criteria
Configurable Confirmation Deadline (Per Meeting/Series, Owner’s Local Time, Business‑Day Aware)
Given a series default deadline rule "24 hours before start" in owner’s local timezone, When an occurrence is created, Then deadline_at = occurrence_start_at (owner_tz) − 24 hours. Given owner timezone America/New_York and meeting start 2025-10-10 11:00 ET (15:00 UTC), When the deadline rule is "24 hours before", Then deadline_at = 2025-10-09 11:00 ET. Given the computed deadline falls on a weekend or regional holiday for the owner’s locale, When business‑day adjustment is enabled, Then deadline_at shifts to the previous business day at the same local time. Given a per‑series override exists, When computing deadline, Then the override supersedes workspace default for that series. Given API/UI retrieval, When the deadline is exposed, Then it includes an ISO‑8601 timestamp with timezone and a source attribute of default or override.
Escalating Reminders to Owner Prior to Deadline
Given an assigned owner has not confirmed, When T‑48h, T‑24h, T‑4h, and T‑1h milestones occur before deadline, Then reminders are sent at each milestone unless the owner has already confirmed. Given the next reminder time falls within the owner’s quiet hours, When scheduling, Then send at the nearest earlier allowed window before the milestone; no reminders are sent during quiet hours. Given the owner confirms via UI, email, or Slack, When confirmation is recorded, Then all pending reminders are canceled within 60 seconds and no further reminders are sent. Given duplicate reminder jobs are enqueued, When they execute, Then only one message is sent per milestone using an idempotency key meeting_occurrence_id+milestone. Given a reminder delivery fails with a transient error, When retried, Then up to 3 retries occur with exponential backoff; on final failure a reminder_failed event is emitted.
Idempotent Auto‑Trigger Failover at Cutoff
Given the deadline passes with the owner unconfirmed, When the cutoff is reached, Then the system triggers failover exactly once for the occurrence. Given parallel trigger attempts within a 5‑minute window, When processed, Then only the first acquires the lock and subsequent attempts are no‑ops (no duplicate rotation, no duplicate logs). Given failover runs, When selecting a new facilitator, Then choose the next fair eligible user excluding those on PTO/travel or blocked by quiet hours at meeting time. Given failover completes, When auditing, Then exactly one equity adjustment log entry exists reflecting the reassignment delta. Given failover begins, When monitoring, Then state transitions to failover_in_progress and then owner_assigned within 60 seconds or a failover_failed event is emitted.
Deadline State Observability (UI + Webhook)
Given any upcoming occurrence, When viewed in the UI, Then it shows a state badge (Unconfirmed, Confirmed, Deadline Passed, Failover In Progress, Owner Reassigned) and a countdown to deadline in the owner’s local timezone. Given a state change (owner_confirmed, deadline_updated, deadline_passed, failover_triggered, owner_reassigned), When it occurs, Then a webhook is emitted within 10 seconds with payload including event_type, meeting_id, series_id, previous_owner_id, new_owner_id (when applicable), deadline_at, occurred_at, idempotency_key. Given webhooks are delivered, When duplicates occur, Then the same idempotency_key allows consumers to de‑duplicate; the system retries 3 times with exponential backoff on 5xx. Given the UI is open, When state changes, Then it reflects the new state within 10 seconds without a full page refresh.
Respect PTO, Travel, Quiet Hours, and Regional Holidays
Given a candidate facilitator is marked PTO or travel during the meeting time, When failover selects a new owner, Then that candidate is skipped and the next fair eligible candidate is considered. Given quiet hours are defined for a candidate, When evaluating eligibility for assignment, Then do not assign ownership if the meeting start falls inside their quiet hours window. Given a regional holiday in the owner’s locale, When computing the deadline and reminders, Then they are adjusted to the previous business day at the same local time and no reminders are sent during the holiday. Given no eligible candidates due to PTO/quiet hours, When failover runs, Then a no_eligible_facilitator event is emitted and the system retries selection until the first eligible candidate becomes available according to rules.
Per‑Series Overrides and Edit Behavior
Given a series‑level override is set to "48 hours before", When creating future occurrences, Then they inherit the override while past and locked occurrences remain unchanged. Given an occurrence‑level exception override is set, When computing its deadline, Then it takes precedence over the series override and workspace default. Given the series override is removed, When creating future occurrences, Then the workspace default applies. Given any override change, When audited, Then the audit log records actor, timestamp, previous value, and new value.
Sequenced Integration with Scheduler, Invites, Notifications, and Equity Log
Given a failover is triggered, When processing, Then the system performs in order: (1) atomically reassign new owner and write equity log, (2) update scheduler state, (3) update calendar invites, (4) dispatch stakeholder notifications, with each step succeeding before the next begins. Given the previous owner confirms within 10 seconds of the cutoff while failover is starting, When both actions race, Then a compare‑and‑set guard ensures only one state transition commits and a canceled_due_to_race webhook is emitted for the losing action. Given calendar invites are updated, When attendees view the invite, Then the facilitator/organizer reflects the new owner and no duplicate or spurious cancellations occur. Given stakeholder notifications are sent, When delivered, Then recipients receive a single consolidated message including new owner and reason "auto‑rotate due to missed confirmation" within 2 minutes of failover start. Given any step fails irrecoverably, When retries exhaust, Then a failover_failed event with diagnostic code is emitted and no partial double‑assignment exists.
Fair Rotation Selection & Equity Adjustment
"As a frequent meeting participant, I want the next facilitator to be chosen fairly based on our equity rules so that ownership rotates transparently and no one is overburdened."
Description

Automatically select the next facilitator using the equity scoreboard, ensuring fair distribution of ownership over time. The algorithm must consider cumulative equity balance, recent inconveniences (e.g., early/late slots), and tie-breakers (e.g., least recent ownership, role weighting). Upon selection, adjust the equity ledger atomically with the rotation and persist rationale (inputs, scores, tie-breaker) for transparency. Integrate with the shared scoreboard UI so participants can see the updated balance immediately. Expected outcome: objectively fair assignments that maintain trust and reduce contention.

Acceptance Criteria
Failover on Missed Confirmation Triggers Fair Auto-Rotation
Given meeting M has upcoming owner U who has not confirmed by deadline T And an eligible candidate pool exists When time >= T Then the system performs auto-rotation And selects facilitator F using the equity scoring algorithm And reassigns ownership of meeting M to F And persists the equity ledger adjustment and selection rationale atomically And notifies participants, U, and F within 60 seconds And the operation is idempotent for the same missed-confirmation event id
Composite Equity Scoring With Inconvenience and Role Weighting
Given candidates A, B, C with attributes: - cumulativeEquityBalance: A=-3, B=-1, C=0 (more negative = owes more) - recentInconvenientSlots(30d): A=3, B=0, C=1 - roleWeight: A=1.0, B=1.0, C=0.8 - lastOwnedDaysAgo: A=12, B=40, C=9 When the equity scoring algorithm runs Then it computes a composite score per candidate that increases selection priority with owing equity, decreases with recent inconvenient slots, and applies roleWeight And the selected facilitator is B And per-candidate scores and inputs are persisted with the rationale
Tie-Breaker: Least Recent Ownership for Equal Composite Scores
Given candidates D and E produce equal composite scores And D.lastOwnedDaysAgo = 28 and E.lastOwnedDaysAgo = 53 When the tie-breaker is applied Then E is selected due to least recent ownership And the applied tie-breaker and comparison values are recorded in the rationale
Atomic Ownership Change and Equity Ledger Update
Given facilitator F is selected for meeting M When committing ownership reassignment and equity ledger adjustment Then the updates are atomic: either both persist or neither And an audit log entry is written with timestamp, requestId, inputs, per-candidate scores, winner, and tie-breakers And concurrent rotation attempts result in exactly one committed update; others abort without side effects And retries do not create duplicate ledger entries
PTO/Travel and Quiet Hours Eligibility Filtering
Given candidate G has active PTO or travel overlapping the meeting window or configured quiet hours that intersect the proposed time When building the eligible candidate pool Then G is excluded from selection And if all candidates are ineligible Then the system escalates by moving the rotation to the next ergonomic window and notifies stakeholders within 60 seconds
Scoreboard UI Real-Time Update on Rotation
Given the rotation for meeting M is committed at timestamp t0 When users view the shared scoreboard UI Then the new facilitator and updated equity balances are displayed within 5 seconds of t0 And connected clients receive the update without manual refresh And the displayed equity delta equals the persisted ledger change
Selection Rationale Persistence and Access
Given a rotation event id R When a participant opens rotation details via UI or API Then they can view the rationale including candidate list, inputs (balances, inconveniences, role weights, eligibility), computed scores, selected winner, and tie-breakers And the record is immutable and retained for at least 180 days And the rationale values exactly match the computation used for selection
Constraint-Aware Availability Check (PTO/Travel/Quiet Hours)
"As a facilitator candidate, I want the system to skip assigning me when I’m on PTO, traveling, or in quiet hours so that I’m not scheduled into impractical or disruptive slots."
Description

Before assigning a new facilitator, validate candidate availability against declared PTO, travel windows, quiet hours, and live calendar free/busy. Pull constraints from connected calendars and TimeMeld profiles; if a candidate violates any constraint or is otherwise unavailable, skip to the next eligible person. Support per-user exceptions (e.g., opt-in to override quiet hours) and surface skip reasons in the UI and audit log. Expected outcome: failovers that respect human constraints and reduce churn from impractical assignments.

Acceptance Criteria
Eligibility Evaluation Across All Constraints
Given auto-rotate failover is triggered for a meeting with scheduled start and end times When evaluating a candidate facilitator Then the system aggregates constraints from the candidate’s connected calendars (PTO/OOO events, travel), TimeMeld profile (quiet hours, overrides), and live calendar free/busy And normalizes all constraint times to the candidate’s timezone And marks the candidate eligible only if the meeting interval is fully outside PTO, does not overlap blocked free/busy, and is outside quiet hours unless an override applies
Quiet Hours With Per-User Override
Given a candidate has quiet hours defined in their profile And the meeting time falls within those quiet hours When evaluating eligibility Then the candidate is ineligible by default And if the candidate’s profile has "override quiet hours" enabled, the candidate is eligible And if an override is applied, the assignment is tagged as "quiet-hours override" for UI and audit log
Travel Windows Respect and Availability
Given a candidate has an active travel window sourced from a connected calendar or their TimeMeld profile When the meeting time overlaps the travel window Then the candidate is ineligible unless their profile indicates "available while traveling" And if "available while traveling" is true, the candidate remains subject to quiet hours and live free/busy checks And the allow/skip decision records the travel source and time range
Live Free/Busy Re-Check Before Finalizing Assignment
Given a candidate passed initial constraint checks When TimeMeld is about to assign the facilitator Then it re-queries the candidate’s live free/busy within 5 seconds prior to sending notifications And if the slot is no longer free, the candidate is skipped and the system proceeds to the next eligible candidate without sending an invite to the skipped candidate And the skip reason "busy-on-recheck" is recorded with a timestamp
Skip Reasons Surfaced in UI and Audit Log
Given a candidate is skipped due to any constraint When displaying the failover decision Then the UI shows for each skipped candidate: candidate name, primary constraint type (PTO | Travel | Quiet Hours | Busy), time interval, and data source (calendar | profile) And an audit log entry is created with the same fields plus meeting ID and timestamp
No Eligible Candidate Outcome Handling
Given all candidates in the rotation are ineligible after evaluation When auto-rotate failover runs Then no facilitator is assigned And stakeholders are notified with a "no eligible facilitator" message including per-candidate skip reasons And an audit log entry is created capturing the evaluation summary and zero-assignment decision
Sequential Evaluation and Assignment Order
Given a ranked list of candidate facilitators and a meeting time When auto-rotate failover evaluates candidates Then candidates are evaluated in listed order and any ineligible candidates are skipped per constraints And the first eligible candidate is assigned And the audit log records the evaluation order and selected candidate
Stakeholder Notifications & Messaging
"As an attendee, I want a clear notification when ownership rotates so that I understand who’s leading and whether anything changed for the meeting."
Description

Notify the newly assigned facilitator, the previous owner, and attendees when failover occurs. Deliver timely, actionable messages via configured channels (email, Slack/Teams) with clear context: reason for failover, new owner, meeting details, and any equity changes. Provide localized, templated copy with tokens for series name, time, and links to view details or undo (if permitted). Respect recipients’ notification preferences and quiet hours where feasible without compromising time-critical delivery. Expected outcome: stakeholders are informed immediately with minimal confusion and no manual coordination.

Acceptance Criteria
Immediate Multi-Stakeholder Notification on Failover
Given an upcoming meeting in a rotating series and the current owner has not confirmed by the configured deadline And Auto‑Rotate Failover has selected a new facilitator When the failover event is committed Then notifications are sent to the new facilitator, the previous owner, and all invited attendees within 60 seconds And each notification includes the reason for failover, the new facilitator’s name, the meeting series name, the meeting occurrence date/time in the recipient’s local timezone, and links to view details and manage/undo if permitted And no manual action is required to trigger these messages
Channel Preference and Fallback Delivery
Given each recipient has notification channel preferences with a primary and optional fallback and valid contact details When a failover notification is sent Then the message is delivered via the recipient’s primary channel (Slack/Teams or email) And if the primary channel errors or times out after up to 3 retries within 30 seconds, a fallback channel is attempted within the same 60-second SLA And the recipient receives at most one successful notification per failover event (deduplicated across channels) And delivery outcome is recorded per channel attempt
Quiet Hours Respect with Time‑Critical Override
Given recipient quiet hours are active and the organization has a configured time‑critical window (default 12 hours before meeting start) When a failover notification is generated Then if the meeting start time is outside the time‑critical window, the notification is queued and delivered immediately after quiet hours end And if the meeting start time is within the time‑critical window, the notification is delivered immediately and flagged as urgent, using channel mechanisms to bypass Do Not Disturb where available And queued notifications display a scheduled delivery time in the audit log
Localized, Tokenized Templates Render Correctly
Given localized templates exist per supported locale and channel with tokens {series_name}, {occurrence_time_local}, {new_owner_name}, {reason}, {equity_change}, {details_link}, {undo_link} And a recipient has a locale preference or an organization default locale When a notification is rendered Then the correct locale and channel-specific template is used And all tokens are resolved with non-empty values appropriate to the recipient And no raw token placeholders remain in the delivered message And date/time is formatted in the recipient’s locale and timezone And links resolve to the correct meeting instance for the recipient
Equity Adjustment Disclosure
Given the failover recalculates equity/ownership points When notifications are sent to stakeholders Then the message includes the equity delta for the previous owner and the newly assigned facilitator when policy permits disclosure to that recipient And a link to the equity scoreboard is included And the displayed equity deltas match the ledger entries recorded for the failover event And recipients without permission to view equity receive a redacted message with no token leakage
Undo Capability Messaging and Enforcement
Given the organization permits undo within a configured window (default 15 minutes) for specified roles And a failover notification includes an undo link When an eligible recipient clicks the undo link within the allowed window Then the failover is reversed, prior ownership restored, and updated notifications are sent to all stakeholders within 60 seconds And if the window has expired or the user lacks permission, the action is blocked with an explanatory message and no changes are applied And the original notification is marked as superseded in event history
Notification Event Logging and Traceability
Given observability and audit logging are enabled When a failover notification workflow executes Then an audit record is written per recipient with fields: event_id, meeting_id, recipient_id, locale, channels_attempted, channel_outcome, timestamps (queued/sent/delivered/failure), quiet_hours_handling, and template_version And logs are queryable within 5 minutes and exportable in CSV or JSON And personally identifiable information is stored per policy and redacted in non-production environments
Calendar Ownership Reassignment & Invite Update
"As a product manager, I want the event to update seamlessly to the new owner so that links, attendees, and context remain intact without manual cleanup."
Description

Execute the ownership transfer on connected calendars (Google Workspace, Microsoft 365) for single occurrences and series. Where organizer transfer is supported, update in place while preserving event ID, conferencing links, agenda, attachments, and attendee list. Where not supported, create a replacement event that mirrors metadata, cancels the original, and minimizes attendee churn (no duplicate notifications). Ensure idempotency, retry with backoff on API failures, and guard against race conditions from concurrent updates. Expected outcome: calendars reflect the new owner accurately without broken links or duplicated invites.

Acceptance Criteria
In-Place Organizer Transfer — Google Workspace Single Event
Given a Google Workspace calendar event owned by User A with conferencing link, agenda/description, attachments, and attendees And TimeMeld selects User B as the new owner When TimeMeld executes an in-place organizer transfer Then the event ID and iCal UID remain unchanged And the organizer becomes User B And the conferencing link, agenda/description, attachments, and attendee list remain unchanged And each attendee receives at most one update notification (no duplicates) And the event appears on User B’s calendar as organizer and on attendees’ calendars with unchanged RSVP statuses And the updated organizer is observable via the Calendar API within 60 seconds of operation completion
Exception Instance Transfer — Google Workspace Recurring Series (Single Occurrence)
Given a recurring series in Google Workspace with an upcoming single occurrence selected for transfer And the series contains agenda/description, attachments, attendees, and a conferencing link When TimeMeld transfers ownership for only that occurrence Then only the targeted occurrence reflects User B as organizer; the series master and all other instances remain owned by User A And the occurrence’s event ID remains unchanged (no new duplicate instance is created) And the conferencing link, agenda/description, attachments, and attendee list for that occurrence remain unchanged And attendees receive notifications only for that occurrence (no notifications for untouched instances) And the change is observable via the Calendar API within 60 seconds
Replacement Event Creation — Microsoft 365 Single Event (Organizer Transfer Not Supported)
Given a Microsoft 365 calendar event where organizer transfer is not supported And TimeMeld selects User B as the new owner When TimeMeld performs the transfer Then the original event is cancelled for all attendees And a replacement event is created on User B’s calendar within 30 seconds with identical start/end time, title, location, agenda/description, attachments, and the same join link preserved as a clickable URL And each attendee receives at most one cancellation and one invitation email (no duplicate sends) And each attendee’s calendar shows exactly one meeting at the scheduled time owned by User B (no orphaned duplicates) And provider sync completes with the above state within 5 minutes
Replacement Event Creation — Microsoft 365 Recurring Series (Single Occurrence Only)
Given a recurring series in Microsoft 365 and a single upcoming occurrence selected for transfer When TimeMeld executes the transfer Then the original occurrence is cancelled and a replacement occurrence owned by User B is created at the same time with mirrored metadata (title, location, agenda/description, attachments, and preserved join link as URL) And the series master and all other instances remain unchanged And each attendee receives at most one cancellation and one invitation email for that occurrence only And attendees’ calendars show exactly one occurrence at that time owned by User B, with no duplicate instances after provider sync (<=5 minutes)
Idempotency and Retry with Exponential Backoff
Given multiple identical transfer requests identified by the same operationId within 24 hours When these requests are executed concurrently or sequentially Then exactly one ownership change is performed; subsequent requests return a successful, no-op result with the same final state And transient provider errors (HTTP 429/5xx) are retried with exponential backoff and jitter up to 5 attempts over 10 minutes And retries do not generate duplicate notifications or multiple replacement events (deduplicated by operationId) And if the provider returns a permanent error, the operation is marked failed and any partial artifacts (e.g., replacement without cancel) are reconciled so attendees are left with a single correct event owned by the original owner
Concurrency Safety — Conflicting Updates and Race Conditions
Given two competing ownership changes for the same event (e.g., auto-rotate trigger and a near-simultaneous manual update) When both operations attempt to update the event Then a deterministic, optimistic concurrency check ensures only one operation commits (based on a version/etag match), and the losing operation aborts without sending notifications or altering calendars And attendees receive only one set of notifications reflecting the committed owner And the final event state shows a single owner and no duplicate or flip-flopped events across provider and attendee calendars And the committed change is observable via the provider API within 60 seconds
Audit Trail & Equity Change Log
"As an ops lead, I want a detailed audit of each auto-rotation so that I can explain decisions, verify fairness, and satisfy compliance needs."
Description

Record an immutable audit entry for each failover capturing timestamps, triggering condition, candidates evaluated, selection rationale, constraint checks, notifications sent, and delta to the equity scoreboard. Provide a searchable view and export (CSV/JSON) for compliance and retros, with role-based access controls. Minimize sensitive data exposure by default and redact attendee details where unnecessary. Expected outcome: complete traceability of automated decisions that supports trust, troubleshooting, and governance.

Acceptance Criteria
Record Immutable Failover Audit Entry
Given a scheduled meeting whose assigned facilitator has not confirmed by the deadline And Auto‑Rotate Failover triggers an automatic reassignment When the failover completes Then the system writes a single immutable audit entry with a unique event_id and UTC timestamps for detection_time, assignment_time, and write_time And the entry includes trigger_condition, prior_owner, evaluated_candidates with eligibility and scores, selected_facilitator, selection_rationale, applied_constraints and their pass/fail And the entry includes notifications_sent with recipient_role, channel, and delivery_status, and equity_delta with before, after, and delta And write_time occurs within 2 seconds of assignment_time And the audit API and UI do not allow update or delete operations on this entry And the entry has an integrity_hash verifiable against its payload
Search and Filter Audit Log
Given an authorized auditor views the audit log UI or API When they apply filters for date_range, meeting_id, trigger_condition, facilitator_id, and outcome Then the results contain only records matching all filters And results include only fields permitted by their role, with PII redacted by default And results are sorted by detection_time desc by default and sortable by any visible column when specified And pagination supports page_size up to 100 and stable next/prev page tokens And queries returning up to 10,000 records complete within 2 seconds at p95
Export Audit Log (CSV/JSON)
Given a user with export permission has applied audit log filters When they request an export in CSV or JSON Then the exported file contains exactly the filtered records under current redaction rules And CSV follows RFC4180 with a header row and UTF‑8 encoding; JSON is newline‑delimited objects And all timestamps are ISO 8601 UTC with Z suffix And each record includes schema_version and event_id And exports up to 100,000 records complete within 10 seconds at p95 and stream for larger sets And the download link expires within 15 minutes and requires equivalent or stronger authorization
Role‑Based Access and Redaction Defaults
Given system roles Admin, Compliance Auditor, Facilitator, and Viewer When a user accesses audit entries Then Admin and Compliance Auditor may view full details including unredacted attendee identifiers And Facilitator may view entries where they are prior_owner or selected_facilitator with technical details but attendee identifiers masked except their own And Viewer may view aggregate metadata (counts, timestamps, rationale summary) with all PII redacted And by default, attendee emails and phone numbers are masked (e.g., a***@domain.tld, last4 only); external guests appear as "Guest N" And any unredaction requires an explicit Reveal action, is permitted only for Admin/Compliance, and creates its own audit entry
Logged Constraint Checks and Selection Rationale
Given a failover considers PTO, travel, quiet hours, and fairness weighting policies When the next facilitator is selected Then the audit entry lists all candidates with constraint evaluations (pass/fail) and reasons per constraint And includes fairness score inputs and outputs per candidate And the selected_facilitator either has the highest eligible score or includes a rationale with a policy_code explaining the exception And the constraints reflect the org configuration effective at detection_time with a config_version And disqualified candidates include disqualification_reason codes
Notification Logging and Equity Delta Consistency
Given a failover completes and stakeholder notifications are sent When the audit entry is viewed alongside the equity scoreboard Then notifications_sent includes recipients by role, channel (email, Slack, SMS), send_time, delivery_status, and retry_count And equity_delta includes before, after, and delta for affected participants And the equity scoreboard reflects the after values within 5 seconds at p95 And retries or replays do not create duplicate equity adjustments, ensured by idempotency on event_id
Policy Controls & Quiet Hours Configuration
"As a workspace admin, I want to configure deadlines, quiet hours, and rotation rules so that auto-rotate behavior aligns with our team’s practices."
Description

Offer admin and series-level controls to configure confirmation deadlines, rotation rules, weighting factors, quiet hours, blackout dates, and eligible facilitator pools. Allow per-team templates and per-user overrides with validation to prevent conflicting policies. Expose a preview/simulation mode to show who would be assigned under current policies. Expected outcome: organizations can tailor failover behavior to their norms while keeping outcomes predictable and explainable.

Acceptance Criteria
Team Template with Series-Level Overrides
Given I am an Org Admin with policy:manage permission And a Team "Eng" exists When I create a Template "Eng Daily" with confirmationDeadline=12h, rotationRule=round_robin, weightingFactors={timeZonePenalty:0.6,recentLoad:0.4}, quietHours=22:00–07:00 local, blackoutDates=[2025-11-27], eligiblePool="Eng Facilitators" And I assign the template to Team "Eng" And I apply the template to Meeting Series "Standup - PST" and override confirmationDeadline=3h and eligiblePool="Oncall Rotation A" Then the series inherits all non-overridden fields from the template And overridden fields display as series-specific values and persist after reload And an audit log entry records template assignment and overrides with actor, timestamp, and diff
Quiet Hours and Blackout Enforcement Across Time Zones
Given Team "Eng" template quietHours is 22:00–07:00 local for each user and blackoutDates include 2025-12-24..2025-12-26 And User A (America/Los_Angeles, UTC−08:00) has a per-user quietHours override 21:00–08:00 And User B (Europe/Berlin, UTC+01:00) uses template defaults When I open the "Standup - PST" series policy preview for the week of 2025-12-23 Then proposed meeting windows exclude 2025-12-24..2025-12-26 for all users And windows exclude 21:00–08:00 for User A (local) and 22:00–07:00 for User B (local) And no proposed window violates any participant’s quiet hours when converted to their local timezone
Eligible Facilitator Pool with PTO/Travel Exclusions
Given the series eligiblePool is "Oncall Rotation A" with users [A,B,C,D] And User C has PTO 2025-09-15..2025-09-20 and Travel (UTC+10) 2025-09-21..2025-09-23 And series quietHours are enforced per user When I run facilitator simulation for meeting 2025-09-21T16:00Z Then User C is excluded due to Travel/availability conflict with an explicit reason And only users not on PTO/Travel and within quiet hours are considered eligible And the resulting candidate list is ordered by rotation and weighting factors
Rotation Rules and Weighting Factors Application
Given rotationRule=fairness_weighted with weightingFactors {timeZonePenalty:0.7, recentLoad:0.3} And equity history shows A:4, B:2, D:1 facilitations this quarter And timeZonePenalty applies to local windows before 07:30 or after 20:30 When I run simulation for 2025-09-22T17:00Z with participants [A,B,D] Then the facilitator with the lowest combined fairness score (normalized 0–1) is selected And changing timeZonePenalty to 0.2 and re-running updates scores and may change the selection And the output includes each candidate’s score breakdown and final rank
Confirmation Deadline Configuration and Validation
Given the series confirmationDeadline is set to 6 hours before meeting start When the meeting is scheduled for 2025-09-23T15:00Z Then the confirmation deadline displays as 2025-09-23T09:00Z (UTC) and converts correctly per viewer’s timezone When I attempt to set confirmationDeadline to −1h or 200h Then the system rejects the change with HTTP 422 and inline message "Confirmation deadline must be between 0 and 168 hours before start" And the last valid value remains unchanged
Preview/Simulation Mode Explainability and Determinism
Given policies for "Standup - PST" are configured via template "Eng Daily" with series overrides When I click "Preview assignment" for 2025-09-24T16:00Z Then the simulation returns a predicted facilitator, a ranked candidate list, and excluded users with explicit reasons And the result includes a reproducible input hash (policyVersion, participants, calendarBlocks, PTO/Travel, clock) and an Export JSON link And re-running the same simulation without changes returns the same hash and result
Conflict Detection Preventing Unschedulable Policies
Given Team "Eng" template quietHours is 00:00–24:00 on Mon–Fri and series blackoutDates cover the next 30 days When I attempt to save the series policy Then the system blocks saving with HTTP 422 and messages: "No schedulable window remains" and "Eligible pool is empty" (if applicable) And the UI highlights conflicting fields and offers a Resolve action to reset defaults or remove conflicts And the API response includes error codes [NO_SCHEDULABLE_WINDOW, ELIGIBLE_POOL_EMPTY]

Equity Pulse

Live micro‑updates to the equity scoreboard with a post‑meeting fairness receipt that shows who carried early/late and who’s up next. Subtle alerts trigger when someone nears an over‑burden threshold, helping teams spot and correct bias early.

Requirements

Live Equity Scoreboard Micro-Updates
"As a remote team member, I want the equity scoreboard to update live during scheduling and after meetings so that I can see fairness changes as they happen and trust the system."
Description

Stream real-time changes to the equity scoreboard across web and mobile clients within seconds of scheduling actions, time proposals, or meeting end events. Compute incremental fairness deltas and patch the scoreboard without full reloads, with conflict resolution for concurrent edits. Use event-driven updates (WebSocket/SSE) backed by a cache to minimize latency and server load, and fall back to periodic polling when offline. Integrate with TimeMeld’s scheduling engine to consume meeting proposals, acceptances, reschedules, and cancellations. Instrument reliability (delivery, lag) and guardrails (rate limits, back-pressure) to ensure smooth UX for distributed teams.

Acceptance Criteria
P95 <2s Real-Time Scoreboard Updates Across Clients
- Given web and mobile clients subscribed to a team’s scoreboard and server load ≤ 60 events/min/team with ≤ 500 concurrent clients, When a scheduling action/proposal/acceptance/reschedule/cancellation or meeting end event is produced, Then 95th percentile end-to-end latency from event time to render is ≤ 2s, P99 ≤ 4s, and max ≤ 6s, and all connected clients display identical updated values. - Given a client subscribes mid-session, When the subscription is established, Then an initial snapshot from cache renders within ≤ 1s followed by live updates without requiring a full page/app reload. - Given intermittent network loss ≤ 2s, When the connection auto-recovers, Then missed updates are replayed and the scoreboard state matches the server canonical state within ≤ 3s.
Incremental Delta Patching Without Full Reload
- Given an existing scoreboard view, When a fairness delta arrives, Then only changed rows/fields are patched without a full reload, preserving scroll position and input focus, with no visible flicker. - Given a single update, When transported, Then the delta payload size is ≤ 25 KB and does not include the full scoreboard snapshot. - Given bursts of multiple deltas for the same scoreboard within 200 ms, When updates are applied, Then they are coalesced into a single render pass (≤ 1 reflow) while maintaining correctness.
Concurrent Edit Conflict Resolution
- Given two or more concurrent updates affecting the same meeting/participant weights from different sources, When processed, Then last-writer-wins by server-assigned monotonic version applies (tie-breaker: lexicographic source ID), and all clients converge to the same state within ≤ 2s. - Given out-of-order delivery, When deltas are received, Then the client reorders by version and discards stale versions, preventing visual oscillation. - Given conflicting reschedule and cancellation events for the same meeting, When resolved, Then the terminal state is consistent with the event of higher version, and a single fairness delta is reflected.
Offline Fallback to Polling and Re-sync
- Given a client loses real-time connectivity for > 5s, When degradation is detected, Then the client falls back to ETag-based polling every 15s until real-time resumes. - Given connectivity is restored, When the client reconnects, Then it requests and applies catch-up deltas since the last acknowledged version without duplicating visible changes, resulting state equals server canonical snapshot. - Given the app is backgrounded, When platform policies throttle sockets, Then the client uses reduced-frequency polling (≥ 30s) and resumes real-time on foreground within ≤ 2s.
Event-Driven Integration With Scheduling Engine
- Given a meeting proposal is created, accepted, rescheduled, cancelled, or a meeting ends, When the scheduling engine emits the event, Then a corresponding fairness delta is computed within ≤ 500 ms and broadcast to subscribed clients. - Given a meeting ends, When the fairness receipt is generated, Then the scoreboard updates include early/late carry attribution and the “who’s up next” indicator within ≤ 2s on all clients. - Given duplicate events or retries, When processed, Then idempotency via event_id/version ensures no duplicate scoreboard changes are rendered.
Reliability, Rate Limiting, and Back-Pressure Telemetry
- Given normal operation, When metrics are collected, Then delivery_success_rate ≥ 99.9% and end_to_end_lag_p95 ≤ 2s over a rolling 15-minute window are reported to the monitoring dashboard at 1-minute granularity. - Given traffic bursts > 20 events/sec/client, When back-pressure engages, Then server rate-limits to ≤ 5 messages/sec/client and coalesces deltas, and the client UI remains responsive (no main-thread blocks > 100 ms during 95th percentile frames). - Given sustained lag where end_to_end_lag_p95 > 3s for 5 consecutive minutes, When detected, Then an alert is fired to the on-call channel with affected team IDs and region.
Post-Meeting Fairness Receipt
"As a meeting participant, I want a post-meeting fairness receipt so that I can understand who bore the burden and ensure future meetings rotate fairly."
Description

Generate an immutable, shareable receipt immediately after each meeting that summarizes early/late burden minutes by participant, timezone spread, on/off-core-hours impact, and a clear callout of who carried the burden and who’s up next. Surface receipts in-app, and deliver via Slack/Email with deep links back to the meeting. Support per-team templates, localization, and accessibility. Store receipts with retention controls, allow comments/acknowledgements, and enable private vs team-visible modes aligned with org policies.

Acceptance Criteria
Immediate Immutable Receipt Generation
Given a scheduled meeting ends (actual end or host clicks End Meeting) When the end event is recorded Then a post-meeting fairness receipt is generated within 60 seconds. Given a receipt is generated When any user attempts to edit receipt content Then the operation is blocked with a permission error and an audit entry is recorded. Given a meeting is canceled before start When no actual meeting occurs Then no receipt is generated. Given a meeting is reopened or extended When the final end event is recorded Then exactly one receipt exists per meeting instance and reflects the final duration.
Receipt Content Accuracy and Fairness Callouts
Given participants with time zones and team-defined core hours When the receipt is generated Then it lists each participant’s early/late burden minutes calculated against core hours, and totals equal the meeting’s off-core minutes. Given participants in different time zones When the receipt is generated Then it displays the timezone spread in hours as the difference between the earliest and latest local start times. Given the burden minutes are computed When the receipt is generated Then the callout highlights the participant(s) with the highest off-core burden; ties list all top carriers. Given the team’s equity rotation When the receipt is generated Then the “Up Next” field shows the next owner in rotation after the burden carrier (first carrier wins tie).
Delivery, In-App Surfacing, and Deep Links
Given a receipt is generated When delivery is triggered Then it appears in the meeting detail view and Equity Pulse feed within 60 seconds. Given Slack is connected and a participant is opted in When delivery is triggered Then the participant receives a Slack DM with a localized summary and a deep link within 120 seconds. Given Slack delivery fails or Slack is disconnected When delivery is triggered Then email delivery is used as fallback and recorded with status. Given participants have email addresses When delivery is triggered Then they receive a localized HTML email with a plain-text alternative and a deep link. Given a recipient clicks the deep link When they are authenticated and authorized Then the receipt opens; otherwise they are prompted to sign in and unauthorized users see an access denied state.
Per-Team Templates and Localization
Given a team admin edits the receipt template When they save changes Then validation prevents unknown tokens and a preview is available; changes apply only to new receipts. Given users with different locales (en, es, fr, de, ja) When they view a receipt Then static text, dates, times, numbers, and units are localized per user locale; missing translations fall back to English without raw tokens. Given a receipt is rendered from a template When variables are resolved Then all required fields (burden minutes, timezone spread, core-hours impact, callouts) are populated or the render fails with a clear error logged and the default template is used.
Accessibility Compliance (WCAG 2.1 AA)
Given a user navigates the in-app receipt When using only a keyboard Then all interactive elements are reachable in a logical order with visible focus indicators. Given a screen reader is active When the receipt is opened (app, email, Slack preview) Then landmarks, headings, labels, and callouts are announced in a meaningful order with text alternatives for non-text content. Given the receipt UI and emails render When colors and contrast are evaluated Then contrast ratios meet or exceed WCAG 2.1 AA and no information relies on color alone.
Retention Controls, Immutability, and Audit
Given a team retention policy is set between 30 and 730 days (default 365) When receipts reach the configured age Then they are auto-deleted or archived per policy and deep links return 410 Gone; actions are logged in the audit trail. Given a receipt exists When a legal hold is applied by an admin Then deletion is suspended until the hold is removed and the hold state is visible on the receipt. Given any receipt lifecycle event occurs (generation, delivery, view, visibility change, comment, acknowledgement) When it is processed Then an immutable, time-stamped audit entry is recorded and is exportable by admins.
Comments, Acknowledgements, and Visibility Modes
Given a participant or admin opens a receipt When they post a comment Then the comment is saved with author, timestamp, and mentions; authors can edit or delete their comment within 15 minutes; all edits are versioned. Given a participant views a receipt When they acknowledge it Then their acknowledgement is recorded once with a timestamp and is visible to authorized viewers. Given org policy enforces a default visibility (Private or Team-Visible) When a receipt is created Then the visibility defaults to the policy and only admins can change it; all changes are audited; unauthorized users cannot increase visibility. Given an unauthorized user accesses a private receipt via deep link or search When they attempt to open it Then access is denied and the receipt does not appear in listings or search results for them.
Over-Burden Threshold Alerts
"As a team lead, I want subtle alerts when someone nears an over-burden threshold so that I can adjust schedules before bias accumulates."
Description

Continuously evaluate rolling windows (e.g., last 4–8 weeks or N meetings) to detect individuals approaching or exceeding configurable over-burden thresholds. Trigger subtle, non-intrusive alerts in-app and via Slack, with snooze/dismiss, rate limiting, and escalation to meeting owners when patterns persist. Expose admin- and team-level controls for thresholds, core-hour definitions, and alert routing. Feed alert signals back into scheduling proposals to proactively bias away from inconvenient slots for over-burdened users.

Acceptance Criteria
Rolling Window Threshold Evaluation Accuracy
Given team-level threshold config: windowType=time, windowValue=6 weeks, burdenThreshold=5 points; When a meeting with participants completes; Then each participant’s rolling burden count includes only meetings in the last 6 weeks and updates within 2 minutes of meeting end. Given windowType=count, windowValue=10 meetings; When an additional meeting completes; Then the rolling burden count re-computes using only the last 10 meetings per participant and the oldest meeting outside that set is removed. Given burdenThreshold=5; When a participant’s rolling burden reaches 4 points (>=80% of threshold); Then the participant state is set to "approaching"; And when it reaches >=5 points; Then the state is set to "exceeded". Given historical meeting data is imported; When the import completes; Then rolling counts reflect imported data and thresholds re-evaluate within 10 minutes.
Core Hours and Inconvenience Scoring
Given a user’s core hours are set to 09:00–17:00 local time Mon–Fri; When a meeting starts at 07:30 local; Then it is scored "early" and increments the user’s burden by 1 point. Given a meeting starts at 19:15 local; Then it is scored "late" and increments the user’s burden by 1 point. Given a meeting occurs fully inside core hours; Then no burden points are added. Given participants are in different time zones; When scoring the same meeting; Then each participant’s score is computed using their local time at meeting start, correctly handling daylight saving transitions. Given burden weights are configured (early=1, late=1, weekend=2); When a weekend meeting occurs; Then 2 points are added for each affected participant.
Alert Delivery, Routing, and Rate Limiting
Given alert routing is configured to In‑App and Slack DM; When a participant enters "approaching" or "exceeded"; Then an alert is delivered in-app and via Slack DM within 60 seconds of state change containing: participant, state, window definition, current burden/threshold, and suggested actions. Given a team alert channel is configured; When a participant remains in "exceeded" for >48 hours; Then a summary alert is posted to the channel once per 24 hours. Given the global rate limit is 1 alert per user per channel per 24 hours per condition; When multiple triggers occur; Then alerts are deduplicated and a single consolidated message is sent. Given both In‑App and Slack are enabled; When the same condition triggers twice within 1 hour; Then no duplicate alerts are sent across either channel within the 1-hour suppression window. Given Slack routing is disabled at team level; When a trigger occurs; Then no Slack messages are sent while in-app alerts still appear if enabled.
Snooze and Dismiss Behavior
Given an in‑app alert is shown; When the recipient clicks Snooze for 7 days; Then no alerts for the same condition are shown or sent via any channel for that recipient for 7 days unless the condition escalates from "approaching" to "exceeded". Given a recipient clicks Dismiss; Then the current alert instance is cleared and will reappear only upon a new state change (e.g., burden increases or window roll causes exit and re-entry). Given a user has active snoozes; When viewing alert settings; Then they can view and cancel snoozes; And cancelling immediately re-enables alerts for that condition. Given a meeting owner receives an escalation alert about another participant; When the owner dismisses the alert; Then only their view is dismissed and the participant’s alerts remain unaffected.
Admin and Team-Level Configuration Controls
Given an org admin; When they open Equity Pulse settings; Then they can set defaults for windowType (time/count), windowValue, burden weights (early/late/weekend), burdenThresholds (approaching %, exceeded absolute), core-hour templates, and alert routing policies. Given a team lead; When they override settings; Then team-level overrides supersede org defaults and are recorded with timestamp, actor, and change summary in an audit log. Given a non-admin user; When they access settings; Then they can view team rules and adjust personal core hours within allowed bounds (if enabled) but cannot change team/org thresholds. Given configuration changes are saved; When saved; Then new calculations and alerts use the new settings within 5 minutes; historical metrics remain unchanged.
Escalation to Meeting Owners on Persistent Patterns
Given escalation is enabled with rule: escalate after 3 exceeded-state days within 14 days; When a participant meets the rule; Then the owners of that participant’s next 3 upcoming meetings within 14 days receive an escalation alert with suggested fair-time alternatives. Given no upcoming meetings exist; Then a single escalation is posted to the team alert channel tagging the participant’s manager (if mapped) and team lead. Given the participant returns below "approaching" for 7 consecutive days; Then escalation is automatically cleared and future meeting owners are not alerted. Given the privacy setting "anonymize outside team" is enabled; When posting escalations to a broader channel; Then the participant is anonymized to initials and time zone.
Scheduling Proposal Biasing Away From Over‑Burdened Users
Given the proposals engine runs; When a participant is in "approaching" or "exceeded"; Then candidate slots outside that participant’s core hours receive a penalty weight that excludes them from the top 3 suggestions when at least 3 core-hour alternatives exist. Given no core-hour alternatives exist for all required participants; Then the engine includes the least-burdening slot and displays a fairness note indicating the affected participant(s). Given a participant is in "exceeded"; When generating proposals over the next 2 weeks; Then no more than 1 proposed slot outside their core hours is suggested unless the meeting is marked "critical" by the owner. Given equity biasing is active; When comparing proposals generated before and after an alert; Then the share of suggested inconvenient slots for the over-burdened participant decreases by at least 80% when viable alternatives exist.
Timezone Ergonomic Weighting Model
"As a participant, I want fairness scores to consider my local hours and preferences so that equity reflects my actual burden."
Description

Define and implement a transparent scoring model that weights meeting burden by participant timezone, declared core hours, personal preferences, DST shifts, holidays, and recurring cadence. Provide deterministic, versioned calculations with unit tests and explainability strings used in receipts and tooltips. Expose a service/API that the scheduler and scoreboard can query for per-meeting and cumulative equity scores. Include safeguards for edge cases (overnight spans, split core hours) and ensure model updates are backward compatible through version pinning.

Acceptance Criteria
Deterministic Scoring With Explainability
Given identical participants, time proposal, constraints, and pinned model_version "1.0.0" When the score is requested twice Then per-participant scores, total score, and ordering are identical within 1e-6 precision Given a request with any seed or non-deterministic parameter When model_version is pinned Then no randomness influences outputs and results are repeatable Given a computed score When explainability is returned Then for each participant it includes: local_time, core_hours_overlap_pct, preference_offset, DST_adjustment, holiday_flag, cadence_weight, term coefficients, and subtotal contributions Given an explainability string When independently recomputed Then the reconstructed value matches the numeric score within 1e-6 Given a scoring response When inspected Then it includes model_version, inputs_hash, and calculation_timestamp in ISO 8601 with timezone
Core Hours, Preferences, and Overnight Handling
Given a participant with core hours 10:00–16:00 local and a meeting at 06:30 local When scoring Then the burden penalty is strictly greater than at 11:00 local by at least configured off_core_penalty_delta Given split core hours 09:00–12:00 and 19:00–21:00 When evaluating 20:30 local Then it is treated as within core and no off-core penalty is applied Given a meeting spanning 23:30–00:15 local When scoring Then minutes before and after midnight are accounted for without double-counting and duration equals 45 minutes Given a declared preference "no meetings before 08:00" When evaluating 07:45 local Then a preference penalty is added and is visible in explainability as preference_offset > 0 Given two equal-duration candidates where one overlaps a Do Not Disturb block When scoring Then the overlapping candidate has a strictly worse score
DST Shift and Holiday Adjustments
Given a meeting at 09:00 local the day before DST starts and 09:00 local the day after When scoring Then both map to correct UTC offsets and burdens reflect true local time without ±1 hour error Given a meeting on a participant's public holiday When scoring Then a holiday penalty multiplier is applied as configured and shown in explainability Given participants across regions with and without DST When scoring across the DST boundary Then only affected participants receive DST adjustments; unaffected participants do not Given a recurring series that crosses a DST change When computing cumulative equity Then per-occurrence burdens reflect the shift and sum correctly to the series totals
Cumulative Equity Score for Recurring Series
Given a 6-occurrence weekly series with varied times When computing cumulative equity Then per-participant totals equal the sum of their occurrence burdens and are returned by the API Given computed cumulative equity totals When generating a fairness receipt Then it lists early/late counts per participant, the top burden carrier, and the next owner rotation per policy Given an over-burden threshold of 1.5x team median When any participant reaches ≥90% of the threshold Then near_threshold=true is flagged in the API response and Equity Pulse alerting payload Given two candidates for the next meeting When participant A is currently most burdened Then the recommended window reduces A's marginal burden relative to alternatives, all else equal Given backfilled historical meetings When recomputing cumulative equity under the same model_version Then results are deterministic and idempotent
Scoring Service API Contract and Version Pinning
Given a POST /score request with schema v1.0 and model_version=1.0.0 When processed Then the response status is 200 and body includes per_meeting_scores[], cumulative_scores, explainability[], model_version, and inputs_hash Given a /score request without model_version When processed Then the service responds 400 with an error stating version is required and listing supported versions Given a request pinned to 1.0.0 after deploying 1.1.0 When processed Then outputs for identical inputs match prior 1.0.0 outputs byte-for-byte Given a request specifying an unsupported model_version When processed Then the service responds 409 with guidance to migrate and a link to docs Given a GET /versions request When processed Then it returns supported model versions with deprecation dates and stability labels
Edge Cases: No Overlap and Cross-Timezone Teams
Given participants with no overlapping core hours When scoring candidate windows Then the least-bad window is identified and response includes unavoidable_burden=true with per-participant attribution Given a team spanning UTC−10 to UTC+12 with 20 participants and 50 candidates When scoring Then results are returned within 200 ms p95 on reference hardware and numeric stability is maintained (no NaNs/inf) Given missing preference data for a participant When scoring Then defaults are applied, the assumption is documented in explainability, and the request does not fail Given an attendee marked optional When scoring Then their burden is weighted by optional_attendee_weight and shown as such in explainability Given an all-day holiday for one participant and a partial-day holiday for another When scoring Then penalties reflect full vs partial accurately and differ by at least the configured partial_holiday_multiplier
Unit Tests, Golden Vectors, and Invariants
Given the unit test suite When executed in CI Then branch coverage for the weighting model module is ≥90% and line coverage is ≥95% Given golden vectors for inputs and outputs under model_version 1.0.0 When run on Linux, macOS, and Windows in supported runtimes Then outputs match golden files exactly (byte-for-byte) and checksums are identical Given property-based tests for monotonicity When an input time moves further outside a participant's core hours holding other factors constant Then the computed burden does not decrease Given explainability strings for golden vectors When parsed and recomputed Then reconstructed scores match numeric scores within 1e-6 Given API request/response serialization round-trips When performed Then no loss of precision occurs beyond 1e-6 and timestamps remain in ISO 8601 with timezone
“Who’s Up Next” Rotation Logic
"As a scheduler, I want a clear “who’s up next” indicator so that I can assign ownership and times that keep the burden balanced."
Description

Compute and display the next meeting owner/time-carrier based on cumulative equity scores, recent burdens, skipped turns (PTO, holidays), and meeting criticality. Integrate with the scheduling assistant to propose windows that align with the predicted rotation while avoiding repeated inconvenience. Present the next-up indicator in the scoreboard, in receipts, and during proposal flows, with justifications and override options for owners. Maintain an audit trail of overrides and adjustments.

Acceptance Criteria
Deterministic Next Owner/Time-Carrier Calculation
Given a team with at least 3 members, historical equity scores, and the next scheduled meeting context And a rotation policy with weighted factors configured and published When the system computes the next owner and time-carrier Then it returns a single candidate per role with a normalized score between 0 and 1 and a factor-by-factor breakdown And the result is deterministic for the same inputs across repeated calls And ties are resolved by documented tie-breakers (least recent ownership, lowest recent burden, alphabetical as last resort) And the computation completes within 300 ms for teams up to 50 members
Skip Logic for PTO/Holidays and Skipped Turns
Given the predicted next-up user is marked unavailable due to PTO, holiday, or an approved skip window that overlaps the meeting time When rotation is calculated Then the user is skipped for this turn and a "skipped-turn" entry is recorded with reason and time window And the next eligible user is selected without penalizing the skipped user’s equity score And the skipped turn is queued to be fairly reinserted within the next 2 eligible meetings And the UI shows a skip badge with hover details on the scoreboard
Meeting Criticality Weighting
Given a meeting has a criticality level of Normal, Important, or Critical When rotation is calculated Then the weighting configuration applied corresponds to the meeting’s criticality level And the justification panel displays the criticality and the factors it influenced And if the result changes when criticality is toggled, the UI updates within 1 second to reflect the new next-up candidate
Proposal Windows Align with Predicted Rotation and Avoid Repeated Inconvenience
Given a predicted time-carrier for the meeting and each attendee’s ergonomic hours and recent early/late burdens When the assistant generates proposed time windows Then it proposes at least 3 windows ranked by match to the predicted rotation And the top-ranked window falls within the next-up time-carrier’s ergonomic range And no proposed window repeats a marked inconvenient slot for the same person within the last 14 days unless no feasible alternative exists And any unavoidable conflict is labeled with a reason chip (e.g., "no overlap", "hard conflict") in the proposal flow
Consistent Next-Up Indicator and Justifications Across Surfaces
Given a computed next-up owner/time-carrier When the user views the scoreboard, a proposal flow, or a post-meeting receipt Then the same next-up user and role are displayed consistently across all three surfaces And a "Why" affordance reveals factor weights, recent burdens, skips, and criticality influences And the next-up badge includes an accessible label and is keyboard-focusable
Owner Override with Mandatory Reason and Audit Trail
Given the current meeting owner has permission to override rotation When they select "Override" and choose a different owner or time-carrier Then a mandatory reason category and optional note are required before saving And the override is logged with actor, timestamp, prior and new assignees, factors, and meeting ID in an immutable audit record And the equity scoreboard updates according to the override rules within 5 seconds And the receipt shows an override flag and links to the audit entry
Post-Meeting Fairness Receipt Reflects Burden and Next-Up
Given a meeting has concluded and attendance plus actual start time are known When the receipt is generated Then it shows who carried early/late, the quantified burden delta applied, and who is next-up with justification And equity scores update within 60 seconds and are visible in the scoreboard And if the meeting was canceled or rescheduled beyond 24 hours, no burden delta is applied and the receipt indicates the exception
Privacy, Consent, and Access Controls
"As an employee, I want control over who sees my burden metrics so that fairness doesn’t compromise my privacy."
Description

Provide role-based access to equity metrics with employee opt-in/opt-out for individual visibility, team-level aggregation controls, and anonymization for cross-team views. Support data minimization (store only necessary metrics), configurable retention, and export controls. Log access and changes for auditability. Ensure compliance alignment (e.g., GDPR/CCPA) and deliver an admin console for policy configuration and consent management. Clearly communicate what is shared in receipts and alerts and allow users to adjust visibility defaults.

Acceptance Criteria
Role-Based Access Enforcement
Given an authenticated user with role Org Admin, when they access Equity Pulse policy settings or consent records, then access is granted; when they attempt to view any individual’s metrics who has opted out, then access is denied with 403 and the event is audited. Given an authenticated user with role Team Admin, when they view their team dashboard, then only aggregated metrics are visible; when they attempt to drill down to an individual who has not explicitly opted in, then access is denied with 403 and the event is audited. Given an authenticated user with role Member, when they view Equity Pulse, then they can see only their own metrics (if they have opted in) and team aggregates (subject to k-anonymity rules); when they attempt to view other individuals’ metrics, then access is denied with 403 and the event is audited. Given an authenticated user with role Viewer, when they access Equity Pulse, then only cross-team anonymized aggregates are visible; attempts to access individual or team-identifiable data return 403 and are audited. Given a role change in the admin console, when permissions are updated, then effective access rights reflect the change within 60 seconds across UI and API.
Employee Consent and Visibility Controls
Given org-level default visibility is configured in the admin console, when a user first accesses Equity Pulse, then they are presented with a clear consent screen summarizing what data appears in receipts and alerts and must explicitly opt in before any individual visibility is enabled. Given a user opts out of individual visibility, when receipts and alerts are generated, then the user’s identity and individual metrics are excluded or replaced with an anonymized placeholder; changes take effect within 60 seconds. Given a user updates consent, when the change is saved, then a consent record is stored with user ID (pseudonymous), timestamp, prior state, new state, legal basis/justification, and locale; the action is audited. Given a material change to visibility policy, when users next use Equity Pulse, then re-consent is required before any sharing of individual data resumes. Given a user views their settings, when they select “Preview what others see,” then the system shows an accurate preview reflecting current consent and role-based permissions.
Team Aggregation and Cross‑Team Anonymization
Given a team dashboard is requested, when the number of eligible members with valid consent is fewer than 5, then individual and aggregate metrics are suppressed with a message indicating insufficient group size. Given team or cross-team views, when aggregates are displayed, then no user identifiers, email addresses, or exact timestamps are shown; drill‑down to individual records is disabled unless explicit opt‑in exists for each individual and the viewer has appropriate role. Given cross‑team views are generated, when over‑burden alerts are shown, then alerts reference only anonymized counts (e.g., “2 members near threshold”) and never identify individuals from other teams or opted‑out users. Given exports or screenshots are not in use, when data is presented in UI, then copy/inspectable elements exclude hidden identifiers (no data attributes leaking PII).
Data Minimization and Field‑Level Controls
Given Equity Pulse processes meeting burden, when storing data, then only the following fields are persisted: pseudonymous user ID, team ID, role, timezone offset, burden metrics (early/late counts and rolling weights), consent state, alert thresholds, and timestamps; no meeting titles, descriptions, invitee lists, free‑form notes, or email content are stored. Given an admin reviews data policy, when optional fields are disabled in the admin console, then collection and storage of those fields stop within the next processing cycle and historical records for disabled fields are purged per retention policy. Given new fields are introduced, when the schema migrates, then deployment is blocked unless the field is tagged as “necessary” with documented purpose in the data dictionary visible in the admin console. Given data at rest, when inspected, then all user identifiers are pseudonymized and reversible mapping is stored separately with restricted access; direct PII is not present in metric tables.
Retention Policy Configuration and Automated Purge
Given an Org Admin opens the admin console, when they configure retention for data classes (individual metrics, aggregates, audit logs, consent records), then the system accepts values within allowed ranges and displays the effective purge dates. Given data reaches its retention limit, when the daily purge job runs, then expired records are hard‑deleted from primary storage within 24 hours and removed from backups within 35 days; a purge report is added to the audit log. Given a user submits a delete request (DSAR), when it is approved, then their personal data in Equity Pulse is deleted within 30 days, with a confirmation record and exceptions documented (e.g., legal retention of audit logs) in the audit log. Given retention settings change to a shorter period, when saved, then recalculated purge schedules apply immediately to existing data and are executed in the next purge cycle.
Secure Export Controls
Given an Org Admin initiates an export, when selecting scope, then they can choose aggregated (anonymized) or individual-level exports; individual-level exports include only users with explicit opt‑in or documented legal basis attached to the request. Given an export is created, when the file is prepared, then it is available in CSV and JSON inside an encrypted ZIP; the download link requires re‑authentication with 2FA and expires in 24 hours or after one download, whichever comes first. Given any user without Org Admin role attempts an export, when the request is made, then the system returns 403 and logs the attempt. Given a user requests “Download my data,” when the export completes, then only that user’s data is included and delivered via the same secure mechanism; the event is audited with export hash and scope.
End‑to‑End Audit Logging and Tamper Evidence
Given any access to equity metrics, policy settings, exports, or consent changes, when the action occurs, then an audit event is recorded with timestamp (UTC), actor ID, role, action, target, scope, client IP, and outcome (success/denied). Given audit logs are stored, when reviewed, then they are write‑once (WORM) for the configured retention period and cannot be modified or deleted by standard users; tamper attempts generate a high‑severity alert to Org Admins. Given an Org Admin searches audit logs, when filtering by actor, action type, and date range, then results return within 5 seconds for 95th percentile of queries up to 100k events and can be exported securely with the same controls as data exports. Given system clocks, when events are recorded, then timestamps are synchronized via NTP and include monotonic sequence IDs to support forensic ordering across services.

Nudge Ladder

Adaptive escalation that starts with a quiet‑hours‑aware DM, then a friendly thread ping, and finally a discreet manager heads‑up if needed. Escalations stop as soon as ownership is confirmed, maintaining momentum without nagging.

Requirements

Quiet-Hours-Aware DM Nudge
"As a distributed team member, I want to receive ownership nudges only when I’m available so that I’m not interrupted during quiet hours yet can quickly take action when I’m online."
Description

Implements the first step of the Nudge Ladder by delivering direct messages to candidate meeting owners only within their local, non-quiet windows. Pulls timezone and quiet-hours signals from Slack/Teams presence, user preferences, and calendar working hours; respects regional holidays and user-configured exceptions. Messages include context about the pending scheduling decision, the proposed timezone-weighted windows from TimeMeld, and clear CTA actions (Confirm owner, Assign to teammate, Snooze). Applies rate limiting, retries with exponential backoff, and idempotency keys to prevent duplicates. Observes workspace permissions and channel access scopes, and logs attempts and outcomes to the Nudge state machine for downstream steps and analytics.

Acceptance Criteria
Quiet-Hours-Aware DM Delivery Window
Given the user's time zone is resolved from profile, calendar, or presence signals When current time falls within the user's configured working hours and outside quiet hours Then send the DM within the configured send SLA and record delivery Given current time is outside the user's working hours or within quiet hours When evaluating delivery Then do not send the DM and schedule the next attempt at the start of the next eligible window Given conflicting signals across sources When computing working and quiet windows Then resolve using precedence: user preferences override calendar, which override Slack/Teams presence, which override org defaults Given no usable time zone or working hours are available When evaluating delivery Then default to workspace working hours in workspace time zone and mark the attempt decision as skipped_missing_signal
Holiday and Exception Respect
Given the recipient's locale-specific holiday calendar indicates a regional holiday for the day When evaluating delivery Then do not send the DM and schedule for the next working day window Given the user has configured an exception to allow nudges on holidays When evaluating delivery on a regional holiday Then send the DM if within working and non-quiet hours Given the user has configured a one-off do-not-nudge date When evaluating delivery on that date Then do not send the DM and record the skip reason as user_exception Given the user's region cannot be resolved When evaluating holiday constraints Then fall back to the workspace default region and record the fallback
DM Content and CTAs
Given a pending scheduling decision exists When composing the DM Then include meeting context (title or identifier), participants count, and decision deadline Given computed timezone-weighted windows exist When composing the DM Then include the top N windows in the recipient's local time with a link to view all in TimeMeld Given supported chat platform is Slack or Teams When rendering the DM Then display actionable buttons: Confirm owner, Assign to teammate, Snooze, and a View details link Given message exceeds platform limits When composing the DM Then truncate non-critical text and preserve CTAs and key context
Rate Limiting, Retries, and Idempotency
Given per-user and per-request rate limit policies are configured When attempting delivery Then enforce at most the configured number of DMs within the configured window per recipient and per scheduling request Given a transient platform error occurs (e.g., rate_limited, network_error) When attempting delivery Then retry using the configured exponential backoff until max retries or until the next eligible window boundary is reached, whichever comes first Given multiple workers process the same request or a retry occurs When sending the DM Then use a deterministic idempotency key derived from workspace_id, request_id, recipient_user_id, and step_type to prevent duplicate messages Given a duplicate send is attempted with the same idempotency key When posting to the chat API Then no additional DM is created and the attempt is recorded as duplicate_suppressed
Action Handling and State Transitions
Given the recipient taps Confirm owner When processing the action Then mark the recipient as owner for the scheduling request, persist the decision, cancel any pending retries, and halt further escalation steps for this request Given the recipient taps Assign to teammate and selects a valid coworker When processing the action Then set the selected user as owner (with audit of assigner), notify the assignee via DM, and halt further escalation for the original recipient Given the recipient taps Snooze and chooses an option When processing the action Then schedule the next nudge for the selected snooze duration aligned to the next eligible delivery window and record the snooze reason Given an action arrives after the message has expired or after ownership is already confirmed When processing the action Then reject the action, show an ephemeral notice, and make no state changes
Permissions and Channel Access Scopes
Given the app lacks required workspace scopes or cannot DM the user due to tenant policy When attempting delivery Then do not send the DM, do not retry until permissions change, and record the outcome as blocked_permission with details Given the app has required scopes and the user allows app DMs When attempting delivery within an eligible window Then send the DM successfully and record the platform message_id for traceability Given the channel or DM thread becomes inaccessible after send When processing follow-up actions Then gracefully handle with a user-visible error and log as transient_error without data leakage
Nudge State Machine Logging and Analytics
Given any delivery attempt is evaluated When completing the decision Then emit a state machine log with correlation_id, workspace_id, scheduling_request_id, recipient_user_id, attempt_number, decision (sent, skipped_quiet_hours, skipped_holiday, skipped_outside_hours, blocked_permission, duplicate_suppressed, failed), idempotency_key, and next_attempt_at (if any) Given a DM is sent successfully When completing the send Then record platform message identifiers and timestamps and link them to the scheduling request Given the recipient takes any action via CTA When processing the action Then emit an outcome event with action_type (confirm_owner, assign_owner, snooze), actor_user_id, timestamp, and resulting state, and update analytics counters Given logs are queried by correlation_id When fetching analytics Then return consistent records within the configured ingestion SLA and with PII redacted according to policy settings
Thread Ping Escalation
"As a project collaborator, I want a polite thread reminder if no one has taken ownership so that the team can keep momentum without excessive DMs."
Description

Executes the second step of the Nudge Ladder by posting a friendly ping into the active scheduling thread or channel when the DM SLA expires without confirmed ownership. Finds or creates the relevant thread, references the meeting request context, and mentions the most likely owners without spamming the entire channel. Uses configurable copy and tone, deduplicates across parallel pings, respects quiet hours for tagged users, and links directly to the TimeMeld proposal and ownership actions. Updates the Nudge state machine with outcomes and transitions, and gracefully falls back if the original thread no longer exists.

Acceptance Criteria
Trigger Ping on DM SLA Expiry
Given a meeting request has an active Nudge instance and a DM was sent at T0 with SLA X minutes, and no ownership has been confirmed by any recognized signal When current time >= T0 + X minutes Then post a thread ping to the associated scheduling thread within 30 seconds And transition Nudge state from "DM_Sent" to "Thread_Ping_Sent" And record the ping timestamp and message_id in the audit log And do not post if the meeting request is canceled or ownership was confirmed before send time
Find or Create Scheduling Thread
Given the meeting request stores a thread identifier When posting the thread ping Then reply in that thread if it exists and is accessible And include meeting title, proposed time window(s) localized per primary participants, the TimeMeld proposal deep link, and a "Take Ownership" deep link Given the stored thread cannot be found or is inaccessible When posting the thread ping Then create a new thread in the original scheduling channel (or configured fallback channel) And include a concise context summary referencing the original request And persist the new thread_id to the meeting request And transition state to "Thread_Recreated"
Targeted Mentions Without Channel Spam
Given a ranked list of likely owners is available for the meeting request When composing the thread ping Then mention up to 3 top candidates who are not in quiet hours, not OOO, and have not been mentioned for this meeting in the last 60 minutes And never use @channel or @here And ensure total mentions <= 3 And exclude any user who already confirmed ownership
Configurable Copy, Tone, and Deep Links
Given the workspace has a configured thread-ping template and locale When rendering the ping Then populate variables {meeting_title}, {time_window_localized}, {proposal_link}, {take_ownership_link}, {requestor} And use the workspace locale and friendly tone settings And if the template is missing or invalid, fall back to the default friendly copy And ensure the message body length <= 500 characters (excluding link URLs) And include two distinct, working deep links: one to view the proposal and one to take ownership
Cross-Process Deduplication
Given multiple triggers occur for the same meeting request within a 5-minute window When attempting to post a thread ping Then compute an idempotency key {workspace_id}:{meeting_id}:thread_ping And ensure only one ping is posted per key And mark subsequent attempts as "deduplicated" without posting And record deduplication events in the audit log with correlation_id
Quiet Hours Compliance for Mentions
Given a candidate owner is within configured quiet hours at send time When composing mentions Then do not mention that user And schedule a deferred mention for the first minute after their quiet hours end if ownership remains unconfirmed And record a "mention_deferred" event with user_id and next_attempt_at Given all candidate owners are in quiet hours When posting the ping Then post without mentions And schedule a consolidated deferred mention batch for the earliest quiet-hours end among candidates
State Machine Updates and Escalation Stop
Given a user confirms ownership via the TimeMeld "Take Ownership" action or recognized thread command When the confirmation event is received Then transition state to "Ownership_Confirmed" And cancel any scheduled future Nudge Ladder escalations for the meeting And edit the thread ping to reflect "Owned by @user" within 15 seconds And ensure no further pings are sent for this meeting request
Ownership Confirmation Detection
"As a potential meeting owner, I want my confirmation to immediately stop further reminders so that the process feels responsive and non-nagging."
Description

Stops escalations the moment ownership is confirmed via any recognized signal: clicking a Confirm Owner button, replying with a supported intent (e.g., “I’ll take it”), or adding a configured reaction emoji. Validates user permissions to own the meeting, records the assignment, and syncs with the shared equity scoreboard to rotate ownership fairly. Emits events to trigger invite automation, suppresses further Nudge steps, and provides idempotent handling to avoid double assignment. Includes telemetry for confirmation path, time-to-ownership, and failure reasons.

Acceptance Criteria
Confirm Owner button assigns owner and halts Nudge Ladder
Given an open meeting ownership request with pending Nudge Ladder steps and the user is eligible to own When the user clicks the Confirm Owner button in the DM or thread Then the system records the user as the meeting owner within 3 seconds And sets ownershipConfirmed = true with a timestamp And cancels all scheduled Nudge Ladder escalations for this meeting (including manager heads-up) And emits a MeetingOwnershipConfirmed event with idempotencyKey = "<meetingId>:<userId>" And triggers the invite automation workflow And posts a confirmation message in the thread mentioning the new owner
Intent reply confirms ownership
Given an open meeting ownership request bound to a thread/DM and the user is eligible to own When the user replies with a supported intent phrase (e.g., "I'll take it", "I can own", "mine") Then the system records the user as the meeting owner within 5 seconds And sets confirmationPath = "intent" And cancels all scheduled Nudge Ladder escalations for this meeting And emits a MeetingOwnershipConfirmed event And triggers the invite automation workflow And posts a confirmation message acknowledging the intent
Reaction emoji confirmation assigns owner
Given an open meeting ownership request and a configured confirmation reaction emoji (e.g., :white_check_mark:) When an eligible participant adds the configured reaction to the bot’s ownership request message Then the system records the user as the meeting owner within 3 seconds And sets confirmationPath = "emoji" And cancels all scheduled Nudge Ladder escalations for this meeting And emits a MeetingOwnershipConfirmed event And triggers the invite automation workflow And posts a confirmation message indicating ownership claimed via reaction
Permission validation prevents unauthorized ownership
Given an open meeting ownership request When a user without required permissions (e.g., not an invitee or lacks calendar write access) sends any confirmation signal (button, intent, or emoji) Then the system does not assign ownership And posts a clear, private message explaining why ownership cannot be assigned and how to resolve And continues the Nudge Ladder schedule unchanged And does not emit MeetingOwnershipConfirmed nor trigger invite automation And emits telemetry with failureReason = "PERMISSION_DENIED" and the attempted confirmationPath
Idempotent handling of duplicate or concurrent confirmation signals
Given an open meeting ownership request When multiple confirmation signals for the same user/meeting arrive concurrently or within a 5-minute window (any mix of button, intent, emoji) Then exactly one ownership assignment record is created And exactly one MeetingOwnershipConfirmed event is emitted with a stable idempotencyKey And Nudge Ladder cancellation executes once without error on repeated attempts And the shared equity scoreboard is updated once And subsequent signals receive an "already owned" acknowledgement without changing state
Equity scoreboard sync and rotation update on assignment
Given a meeting ownership confirmation has been recorded When the assignment is persisted Then the shared equity scoreboard increments the owner’s ownedCount and updates rotation to the next eligible participant per configuration And persists the updated scoreboard state atomically with the assignment And emits a ScoreboardUpdated event referencing meetingId and ownerUserId And the scoreboard UI/API reflects the update within 10 seconds
Telemetry captured for confirmation path, time-to-ownership, and failures
Given a meeting ownership request created at time T0 When a confirmation attempt occurs (success or failure) Then a telemetry record is stored with meetingId, orgId, actorUserId, confirmationPath in {button,intent,emoji}, outcome in {success,failure}, failureReason when outcome=failure, and timeToOwnershipMs when outcome=success And telemetry is emitted within 5 seconds of processing the attempt And 100% of processed attempts have a corresponding telemetry record retrievable via analytics API
Discreet Manager Heads-Up Routing
"As a manager, I want a discreet heads-up only when necessary so that I can unblock scheduling without causing public pressure on my team."
Description

Implements the final escalation by notifying the appropriate manager privately if prior steps fail within the configured SLA. Resolves manager mapping via Slack/Teams profile fields, HRIS integrations, or admin-defined directory, with overrides and safeguards for sensitive org structures. Crafts a concise, non-shaming message including context, attempted steps, and a one-click option to assign or re-route. Honors quiet hours, regional data residency, and privacy preferences; excludes unnecessary meeting details by default. Throttles to prevent over-notifying, records outcomes for auditing, and ensures no public mention is made in team channels.

Acceptance Criteria
Trigger After SLA and Prior Steps Fail
Given a meeting with unconfirmed ownership and Nudge Ladder steps 1 (DM) and 2 (thread ping) have been sent within their configured intervals And the configured SLA window for escalation has elapsed without ownership confirmation When the escalation job runs Then the system sends a private heads-up to the resolved manager And if ownership is confirmed before send time, no heads-up is sent And the event is marked as escalated-final with a correlation ID
Manager Resolution Fallback and Overrides
Given manager mapping data are available from Admin Overrides, HRIS, and Slack/Teams profile fields When multiple sources provide conflicting managers Then the resolution priority is Admin Override > HRIS > Workspace Profile And if no manager is resolved, route to the configured fallback role and record fallback_used=true And sensitive-org overrides are applied to skip prohibited routes
Quiet Hours and Timezone-Aware Delivery
Given the recipient manager’s quiet hours and timezone are configured When a heads-up is scheduled during the manager’s quiet hours Then delivery is deferred to the first minute outside quiet hours in the manager’s local timezone And if the timezone is unknown, the organization default timezone is used And no heads-up is delivered during quiet hours
Privacy, Non-Public Delivery, and Minimal Content
Given privacy preferences and sensitive-org routing rules are configured When sending the manager heads-up Then the message is delivered only as a direct message (no posts or mentions in any team channels) And the message includes only: meeting identifier, concise context summary, prior attempts with timestamps, and one-click Assign/Re-route actions And by default excludes: full attendee list, agenda contents, attachments, and links to recordings And if a user or org unit has do_not_escalate_to_manager enabled, the escalation is skipped and routed to the configured privacy contact
Throttling and Digesting
Given multiple escalation triggers occur for the same meeting or manager When evaluating notifications within the throttle window Then send at most one manager heads-up per meeting within a 24-hour (configurable) window And cap total heads-ups per manager per calendar day at N (configurable) And if more than M meetings require escalation to the same manager within the digest window, send a single digest message instead of individual messages
One-Click Assign/Re-route Actions
Given the manager receives the heads-up message When the manager clicks Assign to self, Assign to <user>, Re-route, or Mark resolved Then the action completes within 2 seconds and updates meeting ownership/state accordingly And actions require authenticated identity; if not authenticated, the user is prompted for SSO and the action proceeds after success And successful actions immediately stop further escalations for that meeting and log the outcome
Audit Logging and Data Residency
Given any heads-up is sent or action is taken When recording the event Then an audit log entry is created with meeting ID, recipient ID, timestamp, manager source, template version, and outcome And storage and processing occur only within the configured regional data residency boundary And audit logs are permission-controlled, access is logged, and exports/retention follow configured policies
Escalation Policy Configuration
"As a workspace admin, I want to tailor escalation steps and timings to our team norms so that nudges are effective without being intrusive."
Description

Provides an admin UI and API to configure the Nudge Ladder per workspace, team, or project: step order (DM → thread → manager), SLA durations, quiet-hour rules, opt-out lists, channel selection, and per-role overrides. Includes copy templates with variables, preview and test-send modes, versioning with rollback, and validation to prevent conflicting settings. Supports inheritance of org-wide defaults with local overrides, as well as feature flags for gradual rollout. Changes take effect without downtime and are tracked for auditability.

Acceptance Criteria
Org Defaults with Team-Level Overrides Applied
Given an org-wide Nudge Ladder policy is active with default step order DM → thread → manager, defined SLAs, quiet-hour rules, and channel selections And a Team A override is created that changes only the DM SLA and quiet-hour window When the admin saves the Team A override Then the effective policy preview for Team A shows the overridden DM SLA and quiet-hour window And all other fields (step order, thread/manager SLAs, channels, templates) display as inherited from org defaults And a GET request to the configuration API for Team A's effective policy returns the same values And no validation errors are shown
Conflicting Settings Validation Blocks Save
Given an admin edits a policy with the following invalid settings: a non-sequential step order, overlapping quiet-hour windows, a zero or negative SLA, a channel that does not exist or is unauthorized, and an opt-out list that removes the only required recipient for a configured step without an override When the admin clicks Save Then saving is blocked and inline errors are shown next to each offending field And the errors specify the rule violated (e.g., "Step order must be DM → thread → manager", "Quiet-hour windows may not overlap", "SLA must be > 0 minutes", "Channel must exist and be selectable", "Required recipient cannot be fully opted out without an alternate override") And the configuration API returns HTTP 422 with a structured list of field errors And no changes are persisted
Template Preview and Test Send
Given message templates exist for each step and include variables {assignee_name}, {issue_key}, {next_sla_at}, {manager_name}, and {ownership_link} And the admin provides a sample context for preview When the admin clicks Preview for the thread step Then the preview renders all known variables and highlights any unknown or missing variables with a clear indicator And the rendered message length is shown and fits platform limits When the admin clicks Test Send and selects a sandbox destination Then a test message is delivered only to the chosen sandbox destination, is labeled as [Test], and does not notify real recipients or advance any real escalations And the test send event is recorded in the audit log with actor, scope, template version, and timestamp
Versioning and Rollback Without Downtime
Given policy version v1 is active and has in-flight escalations using v1 When the admin saves changes, creating version v2 Then new escalations initiated after the save use v2 immediately without service downtime And in-flight escalations continue using v1 until completion When the admin performs a rollback from v2 to v1 Then a new version v3 is created whose configuration equals v1, and it becomes the active version And the audit log records v2 creation and rollback to v3 with diffs, actor, scope, and timestamps
Feature Flag Gradual Rollout
Given the feature flag "Nudge Ladder Configuration" is Off for the workspace When the admin enables the flag for 25% of teams Then only teams within the targeted cohort can view and edit the configuration UI and have their local overrides applied And non-cohort teams continue using org defaults without change When the admin increases rollout to 100% Then all teams gain access and have configurations applied When the admin disables the flag Then the UI is hidden, local overrides stop applying, and data remains intact for future re-enable
Quiet Hours and SLA Deferral Calculation Preview
Given quiet-hour rules are set to 20:00–08:00 local time for recipients And the DM step SLA is 2 hours When an escalation would be scheduled at 21:30 recipient local time Then the effective send time is deferred to 08:00 with the remaining SLA applied, showing 30 minutes carried over And the preview timeline displays the computed timestamps per step across time zones And the API returns the same computed schedule in the preview endpoint
Per-Role Overrides and Opt-Out Resolution
Given per-role overrides specify that the manager step notifies Engineering Managers for Engineer assignees and Product Leads for PM assignees And the opt-out list contains a specific Engineer who should not receive DMs When previewing escalation recipients for an Engineer assignee who is on the opt-out list Then the DM step excludes the opted-out Engineer, the thread step still posts to the team thread, and the manager step targets the appropriate Engineering Manager And when previewing for a PM assignee, the manager step targets the Product Lead per override And if a required step would have no recipients after opt-out and no override, validation blocks Save with a clear error
Nudge Audit Logging & Reporting
"As an operations lead, I want visibility into nudge activity and effectiveness so that I can improve policies and prove compliance."
Description

Captures an end-to-end ledger of all nudge events, state transitions, messages sent, user interactions, and outcomes with timestamps and correlation IDs. Exposes search, filters (team, project, user, step, outcome), and exports for compliance and postmortems. Provides dashboards for time-to-ownership, step effectiveness, opt-out rates, and quiet-hour adherence. Implements role-based access controls, data minimization and redaction for sensitive content, retention policies, and webhook/BI connectors. Aligns with SOC 2 controls and supports incident traceability.

Acceptance Criteria
End-to-End Nudge Event Ledger with Correlation IDs and Timestamps
- Given a nudge ladder is initiated, When any step executes (quiet-hours-aware DM, thread ping, manager heads-up), Then an audit entry is written with {event_type, step, actor_id, recipient_id, channel, message_id, state_before, state_after, outcome, correlation_id, occurred_at_utc, tenant_id}. - Given multiple events are part of the same nudge flow, When logged, Then they share the same correlation_id and include a strictly increasing sequence number to preserve order. - Given a user interacts (acknowledge, claim ownership, opt-out), When the interaction is captured, Then the audit log records {interaction_type, user_id, channel, message_id, correlation_id, occurred_at_utc} and the resulting state transition. - Given message content may contain sensitive text, When persisted, Then only metadata is stored and the message body is redacted per policy with {redaction_applied=true, redaction_reason, redaction_policy_version}. - Given quiet hours defer delivery, When a DM is scheduled, Then the audit log includes {quiet_hours_window, scheduled_for_utc, adherence=true}.
Search, Filter, and Pagination on Audit Log
- Given a permitted user accesses the audit search API/UI, When filters {team, project, user, step, outcome, date_range, correlation_id} are applied, Then results contain only matching rows and default sort is occurred_at_utc desc. - Given up to 10,000 matching rows, When queried, Then 95th percentile response time is ≤ 2s and 99th percentile is ≤ 5s. - Given free-text search, When a query matches correlation_id, message_id, or user handle, Then matching entries are returned. - Given pagination parameters {page, page_size ≤ 200}, When requested, Then total_count is returned and navigation works with stable ordering. - Given no records match, When queried, Then an empty result set is returned with total_count=0 and HTTP 200.
Secure Export with Redaction and Data Minimization
- Given any set of applied filters, When a permitted user requests export, Then CSV and JSON exports contain exactly the filtered rows with a fixed schema and schema_version. - Given PII fields {email, phone, message_body}, When exported, Then values are redacted or masked per policy, and include pii_policy_version and redaction_applied flags per row. - Given exports exceeding 100k rows, When requested, Then an asynchronous job is created, progress status is trackable, and the download link is available within 10 minutes for up to 1M rows. - Given a completed export, When accessed, Then it is delivered via a signed URL valid ≤ 24h, limited to the requesting tenant, with SHA-256 checksum and row count metadata. - Given access control, When a user without Export permission requests an export, Then a 403 is returned and the attempt is itself audited with {actor_id, time, resource, decision=denied}.
Dashboards for Time-to-Ownership and Step Effectiveness
- Given production data, When dashboards load, Then metrics display: time_to_ownership median and p90, step_effectiveness (conversion by step), opt_out_rate, and quiet_hours_adherence for selected team/project and date range. - Given data freshness SLO, When new nudge events occur, Then dashboards reflect them within 15 minutes (lag p95 ≤ 15m) or show a freshness warning. - Given a metric is clicked, When drilling down, Then a list of underlying correlation_ids and events is shown with links to the audit log. - Given permissions, When a Viewer accesses dashboards, Then only aggregated metrics are visible; no raw message content is shown. - Given filter changes, When applied, Then all widgets update consistently and the applied filters are included in share/export URLs.
Role-Based Access Control for Audit and Reporting
- Given roles {Admin, Manager, Analyst, Viewer}, When assigned to a user, Then permissions are enforced: Audit View (Manager+, Analyst+), Export (Admin, Analyst), Retention Configure (Admin), Connectors Configure (Admin), Dashboard View (all). - Given team scoping, When a Manager is limited to certain teams/projects, Then searches and dashboards only return data within that scope. - Given an unauthorized attempt to access redacted content or configure policies, When performed, Then a 403 is returned and the action is captured in the admin audit trail with {actor_id, action, resource, decision=denied}. - Given SSO groups are mapped, When group changes occur, Then access changes take effect within 15 minutes and are recorded. - Given multi-tenant isolation, When a user is authenticated, Then data for other tenants is never accessible, verified by tenant_id checks on every query.
Retention Policies, Legal Hold, and Purging
- Given tenant-configured retention policies, When set for data classes {message_content, metadata, exports, webhook_deliveries}, Then allowed ranges are 7–365 days and the active policy version is stored. - Given retention has elapsed, When daily purge runs, Then eligible records are irreversibly deleted or truncated, with a purge log capturing counts per class and policy_version. - Given a legal hold is applied with reason and scope, When active, Then records matching the hold are exempt from purge until hold expiry or manual release, and the hold is auditable. - Given a policy is tightened, When applied, Then a backfill purge is executed within 24 hours to meet the new policy. - Given exports, When their retention expires or the signed URL TTL elapses, Then links become unusable and artifacts are deleted from storage.
Webhooks and BI Connectors for Incident Traceability
- Given webhook delivery is enabled, When audit events are produced, Then events are POSTed to the tenant endpoint with HMAC-SHA256 signature, idempotency key, schema_version, and delivered in order per correlation_id. - Given transient failures, When delivery fails, Then retries follow exponential backoff for up to 24 hours, after which events move to a dead-letter queue with tenant-visible status and replay capability by correlation_id or time range. - Given BI connectors are configured (Snowflake, BigQuery, S3), When sync runs, Then incremental loads append within 15 minutes of event arrival, and full loads can be scheduled nightly, with row counts reconcilable to the audit store within 0.5% tolerance. - Given security controls, When secrets are rotated, Then connectors continue operating without data loss and the rotation is logged; network egress uses TLS 1.2+ and IP allowlists where configured. - Given performance SLO, When the system is under normal load, Then audit logging p95 write latency ≤ 200 ms and webhook enqueue does not increase it by more than 50 ms.

Backup Buddy

Let owners designate a backup facilitator. When risk signals appear (travel, non‑response), the backup is auto‑prepped with agenda and links and can be promoted in one tap. Keeps sessions on track even when plans change.

Requirements

Backup Designation & Permissions
"As a meeting owner, I want to designate a backup facilitator with the right permissions so that my meeting can proceed smoothly if I’m unavailable."
Description

Enables meeting owners to assign one or more backup facilitators per recurring series or single event, with explicit permission scopes (view agenda, edit agenda, start call, manage recording). Captures acceptance from backups, surfaces conflicts and availability, and stores backup preferences at team and workspace levels. Integrates with Google/Microsoft calendars to write backup as alternate organizer where supported and persists a TimeMeld-level backup linkage when not. Expected outcome: every session has a designated, consented backup with the required access to take over without friction.

Acceptance Criteria
Assign Backups to Events and Series
Given I am the owner of a single event or recurring series When I add one or more backups and select per-backup permission scopes (view agenda, edit agenda, start call, manage recording) Then the system persists the backups and scopes to the event or series And the event/series details display the backups and their scopes to the owner And each backup receives a consent request summarizing their scopes And for a series, future occurrences inherit the current backups and scopes And past occurrences are not modified by series-level changes
Enforce Permission Scopes
Given a designated backup has specific permission scopes When the backup accesses the event in TimeMeld Then actions within scope are permitted and actions outside scope are blocked with an explanatory message And if the backup has only "view agenda" they can view but cannot edit And if the backup has "edit agenda" they can create, update, and reorder agenda items And if the backup has "start call" they can initiate the meeting and admit attendees And if the backup has "manage recording" they can start/stop recordings and access recording controls
Backup Acceptance Workflow
Given a user is designated as a backup for an event or series When the user accepts the request Then the system records consent with timestamp and actor, sets backup status to Active, and notifies the owner When the user declines the request Then the system sets backup status to Declined and notifies the owner When the user has not responded Then the system shows backup status as Pending and allows the owner to resend or replace the backup
Conflict and Availability Surfacing
Given the owner is selecting backups When provider calendars (Google/Microsoft) are connected Then the system displays each candidate's availability for the meeting window as Available, Conflicted, or Unknown And if a candidate is Conflicted, a warning is shown before saving the designation And the owner can proceed despite conflicts When provider calendars are not connected Then availability is shown as Unknown and no conflict warnings are displayed
Calendar Provider Integration
Given Google or Microsoft calendar is connected and supports alternate organizer When an Active backup is saved for an event or series Then the backup is written as an alternate organizer on the provider event And on backup removal or scope change, the provider event is updated to reflect the change When the provider does not support alternate organizer or integration is disconnected Then TimeMeld stores the backup linkage internally and ensures the backup receives the invite, join links, and in-app controls matching their scopes
Team and Workspace Backup Preferences
Given team or workspace-level backup preferences exist (preferred backups and default scope templates) When a new event or recurring series is created Then the default backups and scopes pre-populate the form And the owner can override the suggested backups and scopes before saving And saving the event/series does not alter the stored team/workspace defaults When team/workspace preferences are updated later Then existing events/series are not modified automatically
Session Backup Readiness Gate
Given a session is scheduled When the session is being finalized or is approaching start time Then the system verifies at least one backup has Active consent and includes the minimum required scopes (including "start call") And if no qualifying backup exists, the owner is alerted with options to assign a backup, request consent, or adjust scopes before the session starts
Risk Signal Detection Engine
"As a team lead, I want the system to detect when I’m unlikely to make a meeting so that a backup can be readied before the start time."
Description

Continuously monitors risk signals that threaten facilitator availability and meeting start reliability. Signals include owner travel (OOO events, timezone deltas), non-response to RSVP or agenda acknowledgement by a configured deadline, repeated late arrivals, and device/calendar connectivity errors. Provides tunable thresholds, quiet hours, and override controls to minimize false positives. Integrates with calendar, Slack/Email, and TimeMeld presence to gather signals. Emits a risk score per meeting and triggers auto-prep when risk surpasses threshold. Expected outcome: proactive detection of facilitator risk with clear, explainable reasons and low false alarms.

Acceptance Criteria
Travel/OOO Risk Detection
Given the meeting owner has a calendar event overlapping the meeting window with status OOO or title containing travel keywords, When the detection engine evaluates signals within 24 hours of the meeting or upon event change, Then a travel_ooo risk signal is recorded with its event reference and a configurable weight is applied to the meeting risk score. Given the meeting owner’s current timezone differs from their home timezone by more than the configured delta (default 3 hours) within 24 hours of the meeting, When the engine evaluates signals, Then a timezone_delta risk signal is recorded with the measured offset and contributes its configured weight to the risk score. Given travel or OOO events are removed or end before the meeting, When the next detection cycle runs, Then all associated travel-related risk signals are cleared within 5 minutes and the risk score is recomputed. Given the owner marks “Travel but available” for this meeting, When detection runs, Then travel-related signals are suppressed for this meeting and do not contribute to the risk score.
RSVP/Agenda Non-Response Deadline
Given a response deadline is configured for the meeting owner (e.g., 12 hours before start) and RSVP or agenda acknowledgement is required, When the deadline passes without owner response, Then a non_response risk signal is recorded with timestamp and source and adds its configured weight to the risk score. Given the owner responds after the deadline, When detection runs, Then the non_response signal is cleared within 2 minutes and the risk score is reduced accordingly. Given the owner responded before the deadline, When detection runs at or after the deadline, Then no non_response risk signal is created.
Repeated Late Arrival Pattern Detection
Given a recurring meeting series with at least 3 prior occurrences, When the owner has arrived more than 5 minutes late to at least 2 of the last 3 occurrences, Then a late_pattern risk signal is recorded for the upcoming occurrence and contributes its configured weight to the risk score. Given the owner is on time for the next two occurrences after a late_pattern signal, When detection runs for the subsequent occurrence, Then the late_pattern signal is cleared and no longer contributes to the risk score. Given the lateness threshold is adjusted (e.g., from 5 to 7 minutes) in configuration, When detection runs, Then the late_pattern evaluation uses the updated threshold within 5 minutes of the change.
Connectivity and Sync Error Risk
Given the owner’s calendar sync reports 3 or more consecutive failures within the last 2 hours, When detection runs, Then a connectivity risk signal is recorded with error codes and contributes its configured weight to the risk score. Given TimeMeld presence for the owner is offline or stale for more than 30 consecutive minutes within the 2 hours leading to the meeting, When detection runs, Then a presence_stale risk signal is recorded and contributes its configured weight to the risk score. Given connectivity recovers (successful sync resumes and presence updates for at least 10 minutes), When detection runs, Then related connectivity/presence signals are cleared and the risk score is recomputed. Given a source API is rate-limiting, When detection runs, Then the engine applies exponential backoff and does not duplicate identical connectivity signals within the backoff window.
Risk Score, Explainability, and Auto-Prep Trigger
Given multiple risk signals may apply, When detection runs, Then the engine emits a numeric meeting risk score between 0 and 100 and a reasons array where each reason includes type, weight, timestamp, and source evidence. Given the meeting risk score meets or exceeds the configured threshold (default 70), When detection runs, Then an auto_prep_initiated event is emitted for the meeting and includes the score, reasons, and the target backup facilitator ID. Given the risk score falls below the threshold after auto_prep was initiated and the meeting start is more than 15 minutes away, When detection runs, Then the engine emits an auto_prep_canceled event and updates the reasons accordingly. Given the threshold configuration is changed, When detection runs after up to 5 minutes, Then comparisons to threshold use the updated value.
Quiet Hours Behavior
Given workspace quiet hours are configured for the owner’s local time, When a new threshold breach occurs during quiet hours and the meeting start is more than 60 minutes away, Then the engine continues scoring and storing reasons but suppresses outbound risk-triggered actions (including auto_prep_initiated) until quiet hours end. Given a threshold breach occurs during quiet hours and the meeting start is within 60 minutes, When detection runs, Then the engine bypasses quiet hour suppression and proceeds with risk-triggered actions. Given quiet hours end, When pending suppressed actions exist for still-active threshold breaches, Then the engine releases those actions immediately and includes a reason noting quiet hours deferral.
Overrides and Threshold/Signal Configuration
Given the owner applies an Override: I’m available to a specific meeting, When detection runs, Then the meeting’s risk score is capped at 20 and no auto_prep events are emitted for that meeting; an audit entry records actor, time, and scope. Given an admin disables a specific signal type (e.g., timezone_delta) for the workspace or adjusts its weight, When detection runs after up to 5 minutes, Then the disabled signal no longer contributes (or contributes with the new weight) and the change is recorded in configuration audit logs. Given an admin updates the non_response deadline policy, When detection runs, Then the engine evaluates deadlines using the updated policy and includes the effective policy in the reasons payload.
Auto-Prep Facilitator Kit
"As a backup facilitator, I want a complete, ready-to-run meeting kit so that I can step in without scrambling for context or links."
Description

When a meeting’s risk score crosses the threshold, assembles and delivers a complete facilitator package to the designated backup: finalized agenda, participant roster with local times, conferencing links, access to docs/board, prior notes, and timeboxed checklist. Precreates draft announcements to attendees and pre-authorizes required services (conferencing host, recording, whiteboard). Surfaces a single 'Step in' control in Slack, Email, and the TimeMeld app. Expected outcome: backups can step in confidently without searching for context or links.

Acceptance Criteria
Risk Threshold Triggers Auto‑Prep
Given a scheduled meeting with a designated backup facilitator and a configured risk threshold T And continuous risk monitoring is enabled for the meeting When the meeting’s risk score crosses or equals T within the monitoring window Then TimeMeld assembles the facilitator kit within 2 minutes of the crossing And logs a single kit_prepared event with meeting_id, backup_id, risk_score, and timestamp And sends one notification to the backup in Slack, Email, and the TimeMeld app with a deep link to the kit And subsequent crossings within 60 minutes do not create duplicate kits or notifications (idempotent)
Facilitator Package Completeness
Given a meeting with an agenda, participant list, conferencing details, prior notes, and access-controlled documents/boards When the facilitator kit is assembled Then the kit includes: the latest finalized agenda version, a participant roster with each attendee’s local time for the meeting start (DST-aware), conferencing/join links, access links to docs/board, prior notes, and a timeboxed facilitator checklist And each link opens successfully for the backup without additional permission prompts And 100% of expected artifacts are present or each missing artifact is clearly flagged with a remediation action (e.g., Request Access) without blocking delivery of the rest
Service Pre‑Authorization and Permissions
Given conferencing, recording, and whiteboard services integrated with TimeMeld and the backup set as a permitted alternate host When the facilitator kit is assembled Then the backup is pre-authorized with host/control rights for conferencing, recording, and whiteboard And pre-authorization is valid from 15 minutes before scheduled start until 30 minutes after scheduled end (or actual end if captured), then automatically revokes And a preflight check confirms the backup can start/join as host without prompts And all grants are audit-logged with scope, start_time, and expiry; if policy blocks a grant, the kit flags it as Requires Admin and provides a resolution link
Multi‑Channel “Step in” Control Availability
Given a prepared facilitator kit for a meeting with a designated backup When delivery notifications are sent Then a single actionable Step in control is visible to the backup in Slack (DM), in the TimeMeld app, and in the backup’s email notification And the control is hidden from non-backup users And activating the control deep-links to a confirmation screen bound to the correct meeting_id and backup_id And the control remains available until the meeting ends or the backup has been promoted, whichever occurs first
Draft Announcements Prepared for Attendees
Given a prepared facilitator kit When the kit is delivered Then TimeMeld prepares drafts for attendee announcements in the team’s primary channels (Slack and Email) addressed to the correct attendee list And drafts include updated facilitator name, meeting time with attendees’ local times, agenda link, conferencing link(s), and relevant docs/board links And drafts are grammatically complete, with all placeholders resolved, and ready-to-send with one click And drafts are updated automatically if the backup is promoted, reflecting the new facilitator in the message content
Backup Promotion and Ownership Transfer
Given a prepared facilitator kit and a visible Step in control for the backup When the backup confirms promotion Then the backup is set as active facilitator within 5 seconds and receives host privileges in conferencing/whiteboard tools And the calendar event is updated to reflect the facilitator change (description/metadata) without re-inviting attendees And the TimeMeld equity scoreboard and meeting ownership records are updated accordingly And Step in controls are disabled to prevent duplicate promotions, with a success confirmation shown to the backup
Error Handling, Idempotency, and Retries
Given transient failures from external services during kit assembly or promotion When an operation fails Then TimeMeld retries up to 3 times with exponential backoff and logs error details And delivers a partial kit with clear warnings for any unrecoverable components, providing remediation actions And only one active kit exists per meeting per backup (idempotency), with a Rebuild Kit action available when source artifacts (e.g., agenda version) change And all state changes are audit-logged and are reversible where applicable via a single Rollback action
One-Tap Promotion Workflow
"As a backup facilitator, I want to take over hosting in one tap so that the meeting starts on time with minimal disruption."
Description

Provides a single-action workflow to promote the backup to facilitator/host. Updates calendar event ownership where supported, switches conferencing host/alternative host, transfers recording privileges, and updates meeting metadata and ownership in TimeMeld. Notifies all attendees of the change, updates the meeting room titlecard, and logs the action for audit. Supports automatic reversion if the original owner returns before a configurable cutoff. Expected outcome: seamless, low-latency takeover that keeps the session on schedule.

Acceptance Criteria
One-Tap Backup Promotion from Alert
Given a scheduled meeting within 30 minutes of start with a designated backup and an active risk signal And a preflight check confirms required calendar and conferencing permissions for the backup When the backup taps "Promote to Facilitator" in TimeMeld Then the promotion workflow starts immediately and displays a success confirmation within 3 seconds at the 95th percentile And TimeMeld updates meeting ownership to the backup and reflects the change in the meeting details instantly And the action is idempotent; repeated taps within 60 seconds do not create duplicate promotions or notifications And on preflight failure, no changes are applied and a single actionable error is shown with retry guidance
Calendar Organizer Handoff (Google/Microsoft 365)
Given the meeting is on Google Calendar or Microsoft 365 and organizer change is supported via API When promotion completes Then the calendar event organizer is set to the backup within 5 seconds at the 95th percentile And invitees, recurrence, conferencing link, and reminders remain unchanged And if organizer change is not supported, the backup is granted edit/co-organizer rights and the event metadata indicates the backup as facilitator in title/description And TimeMeld records whether direct organizer change or fallback path was applied
Conferencing Host and Recording Transfer
Given the meeting has Zoom, Google Meet, or Microsoft Teams conferencing attached When promotion completes Then the backup becomes host/alternative host (per provider capability) within 5 seconds at the 95th percentile And recording privileges and waiting room/lobby controls transfer to the backup And if full host transfer is unavailable, the backup is assigned the highest available role (e.g., alternative host/co-host) and a "limited host transfer" notice is displayed in TimeMeld And any ongoing recording continues uninterrupted or the backup can start a new recording without additional permissions
Attendee Notifications and Titlecard Refresh
Given promotion completes successfully When the workflow finishes Then all attendees receive a single consolidated facilitator-change notification via calendar update and in-app/push/email within 10 seconds at the 95th percentile And the TimeMeld meeting room titlecard updates within 2 seconds at the 95th percentile to show the backup as facilitator with avatar and role And agenda/docs/links are re-shared to the backup and pinned in the room And the equity scoreboard updates to credit meeting ownership to the backup
Automatic Reversion Before Cutoff
Given a configurable cutoff T (1–60 minutes; default 5 minutes after scheduled start) is set for the meeting And the original owner becomes active in TimeMeld or taps "Resume facilitation" before T When reversion is triggered Then calendar organizer/permissions and conferencing roles revert to the original owner within 5 seconds at the 95th percentile And attendees receive a single consolidated reversion notification And after T elapses, no automatic reversion occurs; reversion requires explicit facilitator/admin action
End-to-End Audit Logging and Traceability
Given any promotion or reversion attempt When the workflow runs Then an immutable audit record is written containing: initiator, target, meeting ID, calendar event ID, conferencing meeting ID, timestamps (start/end), reason code, per-system outcomes, and per-step latencies And the record is retrievable in the admin console, filterable by date/meeting/user, and exportable as CSV and JSON And audit data is retained for at least 12 months and access-controlled per least privilege
Partial Failure Handling and Consistency Guarantees
Given a multi-system update across TimeMeld, calendar, and conferencing providers When any step fails Then compensating actions execute to restore a consistent pre-promotion state or complete to a consistent post-promotion state; no mixed ownership is left across systems And the user sees a single error with a retry option; automatic retries use exponential backoff up to 3 attempts per failing system And attendee notifications are sent only after all critical steps succeed; on failure, no attendee notification is sent And telemetry captures the failing step and correlation ID linking to the audit record
Attendee Notifications & Failover Safeguards
"As an attendee, I want clear notifications about facilitator changes so that I know who’s leading and where to join without confusion."
Description

Automates timely, respectful communications and guardrails around takeover. Sends pre-alerts to owner when risk is rising, seeks quick confirmation, and notifies backup when auto-prep begins. Upon promotion, informs attendees via their preferred channels and updates the invite description. Includes rate limiting, do-not-disturb windows, and approvals for high-visibility meetings. Provides rollback flow to restore original facilitator and reconcile notes/recordings. Expected outcome: clear expectations and minimal disruption for all participants.

Acceptance Criteria
Owner Pre‑Alert on Rising Risk
Given a scheduled meeting within the next 48 hours with a designated owner and backup And risk signals (e.g., travel, no response, OOO) raise the meeting’s risk score above the pre‑alert threshold When the risk score crosses the threshold Then send a pre‑alert to the owner via their preferred channels within 60 seconds And the pre‑alert includes: meeting title, start time with timezone, detected signals, current risk level, and two actions ("I’m available", "Prep backup") And the system records an audit event with timestamp and correlation ID And if the owner selects "I’m available", the risk is acknowledged and backup prep is not started And if no response is received within 5 minutes, send exactly one follow‑up reminder And if still no response after the reminder, automatically initiate backup auto‑prep And no more than 2 total pre‑alert messages are sent for this threshold crossing
Backup Auto‑Prep Packet Delivery
Given a backup facilitator is configured for the meeting And auto‑prep has been initiated When auto‑prep begins Then deliver a preparation packet to the backup within 60 seconds via their preferred channel And the packet contains: agenda, meeting link, attendee list with local times, latest shared notes (last 7 days), facilitation checklist, and ownership rotation info And the backup is prompted to acknowledge readiness with one tap And if no acknowledgment is received within 10 minutes, escalate to the owner and secondary backup (if configured) And if delivery fails on the primary channel, retry once and fall back to email And the system logs delivery status and acknowledgment outcome
Promotion and Attendee Notifications
Given a meeting with a designated owner and backup within the next 24 hours And promotion to backup has been authorized per policy (approval or rules) When the backup is promoted to facilitator Then update the calendar event’s facilitator field or description within 30 seconds to reflect the new facilitator And send a notification to all attendees via their preferred channels within 60 seconds indicating the facilitator change, unchanged start time, and any updated links And publish a calendar update (ICS/Google/Graph) so attendee calendars reflect the change without creating duplicate events And if a channel delivery fails, fall back to email within an additional 60 seconds And exactly one attendee notification is sent per attendee per promotion event And an audit trail is recorded with approver, timestamp, and delivery results
Notification Rate Limiting and Deduplication
Given multiple risk or state changes occur for the same meeting within a 24‑hour period When generating notifications to the owner, backup, or attendees Then send no more than 3 notifications per recipient per meeting per 24 hours And enforce a minimum spacing of 10 minutes between notifications to the same recipient for the same meeting And coalesce changes occurring within a 5‑minute window into a single message summarizing the latest state And suppress duplicate sends using an idempotency key of meeting+recipient+eventType And expose metrics for suppressed, coalesced, and sent counts to monitoring
Do‑Not‑Disturb Windows Respect
Given a recipient has configured do‑not‑disturb (DND) windows and preferred channels And a non‑urgent notification is scheduled during that window When evaluating delivery Then defer delivery until the DND window ends and include a summary of deferred items And do not send SMS or push during DND unless the recipient has opted in to urgent overrides And if the meeting starts in <= 30 minutes, send an urgent notice via a non‑intrusive channel (email) and mark it as urgent And all times are evaluated in the recipient’s local timezone And record deferral and final delivery timestamps in the audit log
Approval Workflow for High‑Visibility Meetings
Given a meeting is labeled High‑Visibility and has a designated owner and backup When a promotion to backup is proposed Then require explicit approval from the owner or designated approver before promotion executes And present the approver with meeting details, rationale, and Approve/Deny options And if no decision is received within 5 minutes and the meeting starts in <= 15 minutes, escalate the approval request to the fallback approver And block promotion if approval is denied or no fallback approval is obtained And record approver identity, decision, timestamp, and justification in the audit trail
Rollback and Reconciliation After Owner Returns
Given the backup has been promoted and is facilitating an ongoing meeting And the original owner becomes available When the owner requests rollback during the meeting Then transfer facilitation back within 30 seconds without changing the meeting link or creating a new calendar event And notify all attendees of the change via their preferred channels And merge the backup’s notes, action items, and recording markers into the meeting record without data loss And preserve a single continuous recording with updated ownership And enforce permission checks so only the owner or an admin can trigger rollback And if the request occurs after the meeting ends, reconcile artifacts (notes, recording ownership) within 5 minutes and leave attendee calendars unchanged And log rollback and reconciliation outcomes with timestamps
Equity Scoreboard Attribution
"As a product manager, I want takeover events to update the equity scoreboard so that facilitation credit and rotation remain fair."
Description

Integrates Backup Buddy events with TimeMeld’s equity scoreboard so that promoted backups receive appropriate credit and recurring ownership rotation adjusts accordingly. Distinguishes between voluntary and automatic takeovers, prevents double-crediting, and ensures inconvenient-time penalties or credits are applied to the correct person and timezone. Displays history of takeovers in the scoreboard detail view and exports to CSV. Expected outcome: fair attribution that reinforces balanced facilitation and prevents repeated inconvenient slots.

Acceptance Criteria
Automatic Backup Promotion Attribution
Given a meeting occurrence with a designated backup and an automatic risk signal triggers before the scheduled start When Backup Buddy promotes the backup to facilitator Then the backup is credited as facilitator in the equity scoreboard for that occurrence and the primary receives no facilitator credit And the takeover_type is recorded as "automatic" And the scoreboard reflects the credit change within 60 seconds of promotion and no later than 5 minutes after the meeting end time And the occurrence contributes exactly one facilitator credit globally (no duplicates)
Voluntary Takeover Attribution
Given a meeting occurrence with a designated backup When the primary manually promotes the backup before the meeting end time Then the backup is credited as facilitator and the primary is not credited And the takeover_type is recorded as "voluntary" And the attribution is reversible only by an explicit "Reassign Facilitator" admin action with a corresponding audit trail entry And attendee responses or calendar invite states do not affect the credit assignment outcome
Inconvenient-Time Penalties Applied to Correct Timezone
Given a facilitated meeting occurrence with either the original owner or backup credited When computing inconvenient-time penalties or credits Then the calculation uses the organization’s configured inconvenient-time policy parameters And the facilitator’s active timezone as of the scheduled start (respecting DST) is used; if a temporary travel timezone was active then that timezone is used, otherwise the default working timezone is used And the penalty/credit is applied once and only to the credited facilitator’s equity score for that occurrence And test cases at DST boundaries produce results consistent with IANA timezone rules
Double-Credit Prevention and Idempotency
Given repeated promotion events or webhook retries for the same meeting occurrence When processing attribution Then the system uses a deterministic occurrence_id and enforces idempotency so that only one facilitator credit exists per occurrence And if a backup is prepped but never promoted, no attribution change occurs And if promotion is reverted and reassigned within the same occurrence, only the final state at meeting end is counted And the data model prevents two credited users for the same occurrence via a unique constraint that is verified in tests
Recurring Rotation Adjustment After Takeover
Given a recurring series that uses equity score rotation to assign future facilitators When a backup is credited as facilitator for an occurrence Then equity scores are updated immediately and the next occurrence’s facilitator is selected using the updated scores And no participant is skipped or double-selected due to the takeover; ordering remains deterministic for ties using the system’s tie-break rule And a dry-run of the next two occurrences reflects the changed assignment consistent with the added credit to the backup and removal from the primary And any existing manual overrides remain in effect and are respected by the rotation
Scoreboard Detail View Shows Takeover History
Given the scoreboard detail view for a series When any takeover has occurred in past occurrences Then the view lists one entry per occurrence including: occurrence_start, credited_facilitator, original_owner, takeover_type (automatic|voluntary), promotion_timestamp, timezone_used, penalty_applied And entries are sorted by occurrence_start descending and can be filtered by takeover_type And selecting an entry reveals audit metadata (actor, source signal) without exposing PII And displayed values match persisted records exactly (field-for-field)
CSV Export Includes Correct Attribution and Takeover Fields
Given a request to export scoreboard details as CSV for a date range When takeovers exist in the range Then the CSV contains one row per occurrence with columns: occurrence_id, series_id, scheduled_start_utc, credited_facilitator_id, original_owner_id, takeover_type, timezone_used, penalty_or_credit_value, rotation_delta, double_credit And numeric values are rounded to 2 decimals and timestamps are ISO 8601 in UTC And exporting the same range twice without data changes yields identical files (byte-for-byte) And rows without takeovers still include credited_facilitator_id and penalty_or_credit_value with takeover_type empty and double_credit=false

Product Ideas

Innovative concepts that could enhance this product's value proposition.

Zero-Friction Guest Links

Send magic-link invites that verify email at join time—no accounts needed. External guests RSVP in one click and auto-see localized time and conferencing details.

Idea

Focus Block Guardian

Ingest personal focus blocks and team maker hours, then hard-guards them in proposals. Suggests nearest humane alternative with explicit tradeoff scores.

Idea

Attendance Drift Radar

Visualize attendance by region and hour; auto-recommends time shifts when a timezone’s show-rate falls 10% below baseline. One click updates series with rebalanced windows.

Idea

Slipstream Rescheduler

One-click reschedule that preserves equity rules, avoids repeat late/early burdens, and rebooks the nearest fair window. Keeps agenda, attendees, and conferencing intact.

Idea

Invite Hygiene Engine

Auto-lint invites: concise title, localized time, agenda bullets, Zoom/Meet link, ICS for externals, and fallback dial-in. Reduces “what’s this meeting?” churn.

Idea

Holiday Mesh Merge

Merge public holidays and quiet weeks across attendee locales into the weighting model. Flags blackout days and nudges to skip or stagger.

Idea

Ownership Nudge Loop

Automate facilitator rotation with gentle nudges: upcoming owner DM, miss-hand-off alert, and equity scoreboard update. Provides quick-swap buttons when conflicts arise.

Idea

Press Coverage

Imagined press coverage for this groundbreaking product concept.

P

TimeMeld Unveils Slipstream Rescheduler to Rebook Complex Meetings in One Click Without Breaking Fairness

Imagined Press Article

San Francisco, CA — TimeMeld today announced Slipstream Rescheduler, a breakthrough capability that rebooks complex, multi‑time‑zone meetings in one click while preserving fairness, continuity, and attendance. Built for product managers, engineers, and operations leaders at remote‑first startups, Slipstream eliminates the rescheduling ping‑pong that exhausts teams and erodes maker hours. Reschedules are inevitable—travel shifts, urgent incidents, investor calendars, and regional holidays all change. What’s been missing is a humane, data‑driven way to move a meeting once and move it right. Slipstream combines equity‑aware automation with pragmatic guardrails so organizers can adapt fast without accidentally penalizing the same people or breaking invites that already work for guests. Slipstream is a coordinated suite that includes: - RippleGuard Rebook: Finds the nearest fair time that triggers the fewest downstream conflicts across all required attendees. It simulates candidate slots, avoids maker‑hour guards, and chooses the option with minimal ripples—so you reschedule once, not three times. - Equity Ledger Lock: Enforces rotation and burden limits at reschedule time with a clear preview of who gets earlier/later and how the change affects the equity scoreboard. If a tradeoff is unavoidable, it proposes auto‑compensation before you confirm. - Quorum Soft‑Hold: Places temporary holds on top candidate times and gathers one‑tap approvals from required roles via Slack/email. The first slot to reach quorum auto‑confirms; if key people decline, Slipstream falls back to the next fair option. - Asset Carry‑Through: Moves the meeting without breaking anything. Agenda, attachments, conferencing links, and invite rules persist, with delta‑only updates and ICS continuity—so externals keep working links. - Smart Decline Swap: When a required attendee can’t make the new time, Slipstream offers humane alternates within equity rules and lets the organizer swap into the earliest mutually fair window in one tap. - Travel‑Aware Shift: Detects upcoming timezone changes and PTO for key attendees and proactively suggests a fair, minimal‑disruption slip to keep show‑rates high. Together these capabilities cut rescheduling time from hours to seconds, reduce no‑shows, and protect deep work. Slipstream is fully integrated with TimeMeld’s core engine, including Auto Block Sync, Guarded Proposals, Humane Finder, and Focus Buffers, so any proposed change respects maker hours and localized constraints by default. “Rescheduling shouldn’t mean throwing fairness out the window,” said Arjun Rao, co‑founder and CEO of TimeMeld. “Slipstream takes the friction and bias out of a moment that historically punishes the same time zones and derails calendars. We designed a system that moves fast and stays humane—so leaders can adapt without burning trust.” Early users report dramatic gains. “As an incident manager, I have to regroup the right people fast without punishing APAC every time,” said Max Reyes, a global reliability lead at a cloud security company. “RippleGuard Rebook and Equity Ledger Lock let me pick the best tradeoff in seconds, and we don’t miss a beat. Attendance recovered, and my team’s focus blocks remain intact.” TimeMeld’s weighted model considers equity rotation, region‑specific attendance baselines, quiet hours, and observances. When Slipstream proposes a shift, organizers see transparent tradeoff scores and an equity preview. If urgency requires an exception, Graceful Overrides suggests compensation—like swapping next ownership, extending future buffers, or granting make‑up focus time—and logs the adjustment to the Equity Pulse. For external meetings, Slipstream pairs with LinkLock, Calendar Deeplink, and Auto‑Localize to keep guest entry secure and effortless. Recipient‑bound magic links verify the invited email with a lightweight OTP, dates render in the guest’s locale with DST handled automatically, and confirmed updates sync to Google, Outlook, and Apple with ICS fallback. Teams can monitor the impact of reschedules with Drift Radar and Drift Heatmap. If attendance dips below Adaptive Baselines after a time change, Recovery Nudges propose pre‑vetted alternates and automate a return to healthier windows. The Impact Simulator shows projected show‑rate lift, timezone burden changes, and rotation effects side‑by‑side before a change goes live; Auto Rebalance then applies the chosen shift to the whole series in one click. Slipstream is available today for TimeMeld Pro and Enterprise plans. Admins can set rotation policies, max late/early burden thresholds, and reschedule approval rules centrally, with granular overrides at the team level. APIs and admin logs provide auditability for compliance‑minded organizations. “Leaders need speed without surprises,” said Maya Laurent, TimeMeld’s head of product. “By carrying the agenda, links, and permissions forward and locking equity at the moment of change, Slipstream ensures reschedules are surgical, not disruptive. Our goal is simple: rebook once, stay fair, and get back to work.” About TimeMeld TimeMeld is the lightweight scheduling assistant that eliminates timezone friction for remote‑first teams. It proposes timezone‑weighted, ergonomic meeting windows, automates calendar invites, and displays a shared equity scoreboard that rotates meeting ownership—cutting scheduling time, preventing repeated inconvenient slots, and improving attendance. Customers use TimeMeld to protect maker hours, run humane cadences, and keep critical rituals on track across AMER/EMEA/APAC. Availability Slipstream Rescheduler is generally available starting today with no additional charge for Pro and Enterprise. Admin configuration and APIs are live. For pricing, demos, and onboarding, visit timemeld.com/slipstream. Media Contact Elena Park, Communications Lead press@timemeld.com +1 (415) 555‑0147

P

TimeMeld Launches Global Observance Graph and Holiday Mesh to Respect Local Calendars and Boost Attendance

Imagined Press Article

San Francisco, CA — TimeMeld today launched Global Observance Graph and Holiday Mesh, a coordinated set of capabilities that brings real‑time, locale‑aware context into every scheduling decision. By automatically mapping public holidays, partial observances, and quiet weeks across all attendee regions, TimeMeld helps remote‑first teams schedule with respect, lift show‑rates, and reduce last‑minute cancellations. Distributed teams juggle more than time zones—they navigate cultures, customs, and seasons that aren’t visible on a single calendar. Without that context, even well‑meaning organizers collide with regional realities, hurting attendance and trust. TimeMeld’s new features solve this by baking observance intelligence into proposals, reschedules, and reminders, so humane choices become the default. The launch includes: - Observance Graph: A unified, auto‑updating map of public holidays, regional observances, and org quiet weeks across attendee locales that feeds TimeMeld’s weighting model. No manual calendar checking, fewer surprise absences, and more respectful scheduling by default. - Blackout Guardrails: Automatic flags and enforcement of hard blackouts on full‑closure days, skipping or pausing affected occurrences in a series. If a session can’t be avoided, the system suggests humane alternatives (skip, async summary, or compensating rotation). - Stagger Builder: One‑click creation of staggered session sets around holiday clusters, preserving facilitator rotation, and localizing reminders—maintaining momentum and coverage without overburdening any timezone. - QuietWeek Mesh: Detection of declared quiet weeks and low‑activity periods across teams, with cadence adjustments (pre‑load, pause, or stretch) ranked by projected attendance and equity impact. - Client Holiday Sync: For external meetings, inferred customer holidays from domain, locale, and meeting region signals or optional ICS import. Proposals automatically avoid culturally sensitive days and half‑days. - Observance Sensitivity: Soft weighting for partial observances (evenings, half‑days, school breaks) instead of blanket blocks. Windows shift earlier or later with clear impact scores, improving attendance without unnecessary cancellations. “Respect is a retention strategy,” said Arjun Rao, co‑founder and CEO of TimeMeld. “When teams treat regional observances as first‑class inputs, people feel seen and participation rises. With Observance Graph and Holiday Mesh, we’ve encoded those considerations into the engine, so organizers don’t need to be experts on every locale—they simply get better outcomes.” The observance features work hand‑in‑glove with TimeMeld’s attendance intelligence. Adaptive Baselines learn normal show‑rates by region and season, while Drift Heatmap visualizes when and where windows underperform. If an upcoming holiday is likely to depress attendance in EMEA, for example, Impact Simulator shows projected lift from a slight time shift or a staggered plan; Auto Rebalance applies the change across the series in one click. Customer‑facing teams gain particular leverage. “We run trainings across AMER/EMEA/APAC and historically tripped over regional half‑days,” said Casey Morgan, a revenue enablement leader at a global SaaS company. “Client Holiday Sync and Observance Sensitivity surface the nuance we missed. Our sessions land on better days, no‑shows dropped, and CSAT went up.” For internal cadences, Blackout Guardrails prevent late scramble cancels. If a retrospective or planning session conflicts with a full‑closure day, TimeMeld nudges toward humane alternatives: skip and carry forward decisions async, stagger sessions by region with Stagger Builder, or run a one‑time rotation that shifts the burden fairly and logs compensation to the Equity Pulse. All observance intelligence flows into invites and reminders. Auto‑Localize renders dates and times in each guest’s locale with DST handling; Smart Nudges schedule reminders at respectful local hours; and Calendar Deeplink ensures the correct timezone and conferencing link land in Google, Outlook, and Apple with ICS fallback. For externals, LinkLock preserves secure, account‑free entry with recipient‑bound magic links and lightweight OTP verification. “Global consideration shouldn’t require heroics from organizers,” said Lina Abbas, principal data scientist at TimeMeld. “We built an observance knowledge layer that updates continuously and influences proposals probabilistically. The result is a scheduler that ‘feels’ culturally aware at scale, and the data shows the difference.” Availability and Admin Controls Observance Graph and Holiday Mesh are available today across TimeMeld Pro and Enterprise. Admins can manage global and regional observance sources, define org quiet weeks, and set blackout enforcement rules. Compliance and privacy are built‑in: observance data is used solely to weight proposals, not to infer sensitive personal attributes. About TimeMeld TimeMeld is the lightweight scheduling assistant for remote‑first startups. It proposes timezone‑weighted, ergonomic meeting windows, automates invites, and displays a shared equity scoreboard that rotates meeting ownership—cutting scheduling time, preventing repeated inconvenient slots, and improving attendance across AMER/EMEA/APAC. Media Contact Elena Park, Communications Lead press@timemeld.com +1 (415) 555‑0147

P

TimeMeld Introduces Maker‑Hours Protection Stack to Safeguard Deep Work While Keeping Teams in Sync

Imagined Press Article

San Francisco, CA — TimeMeld today introduced the Maker‑Hours Protection Stack, a comprehensive set of capabilities that preserves engineers’ and designers’ deep‑work time while sustaining the operating rhythm of remote‑first teams. By treating focus as a first‑class constraint—not a nice‑to‑have—the stack prevents accidental erosion of maker hours, reduces context switching, and improves attendance at the meetings that actually matter. For years, leaders have asked teams to “protect time” without tools that make it automatic. TimeMeld’s approach hard‑guards deep work in the scheduler and then guides organizers to humane overlaps with transparent tradeoffs. The result: fewer pings, fewer apologies, and more thoughtful sessions that start on time and finish with outcomes. The Maker‑Hours Protection Stack includes: - Auto Block Sync: Continuous ingestion of personal focus blocks, PTO, travel, and team maker hours from connected calendars and org defaults, with recurring patterns and DST handled automatically. - Guarded Proposals: Hard constraints in the scheduler that keep proposals out of protected windows, clearly labeled with protection badges. - Humane Finder: Instant nearest‑fit options when a requested slot collides with a guard, ranked by explicit tradeoff scores—context‑switch cost, timezone burden, and rotation impact. - Focus Buffers: Smart pre/post buffers around focus blocks and long meetings, adjusted by meeting type and role to prevent back‑to‑back context switching. - Graceful Overrides: Controlled exceptions with reason codes and time‑bound waivers. If urgency requires a break, the system suggests compensation (swap ownership, extend future buffer, grant make‑up focus time) and updates equity metrics. - Drift Radar and Drift Heatmap: Early alerts and visualization of attempted and actual guard breaches by team, timezone, and hour—plus recommended policy tweaks to realign. - Adaptive Baselines: Learned attendance norms by region and season to reduce false alarms and make drift alerts timely and trustworthy. “Protecting maker hours is both a cultural and a systems problem,” said Arjun Rao, co‑founder and CEO of TimeMeld. “We built a stack that encodes the culture teams want—clear focus, humane overlaps, transparent tradeoffs—so the system does the heavy lifting and people don’t have to be calendar cops.” Engineers and designers feel the difference. “I used to scramble to defend my focus blocks every sprint,” said Sanaa Idrissi, a design operations lead at a distributed product team. “Guarded Proposals never even land inside my protected time, and Humane Finder gives my PM two fair choices with clear tradeoffs. My creative energy isn’t getting taxed by calendar debates anymore.” Organizers retain flexibility without normalizing exceptions. When a critical incident requires a temporary override, Graceful Overrides applies a time‑bound waiver, previews the equity impact, proposes compensation, and logs the event to the Equity Pulse. The next window automatically reverts to maker‑hour protections, and managers can review trends in Drift Radar to address hotspots before they become norms. The stack also improves meeting quality. Focus Buffers reduce late starts and “context catch‑up” by ensuring attendees have ramp‑up/down time. Title Tuner and Agenda Cards clarify purpose and outcomes. Link Auditor, Join Precheck, and Prep Pack eliminate “which link?” confusion and permissions friction, while Smart Nudges deliver local‑hour reminders with a single Join Now button and backup dial‑in. For cross‑time‑zone teams, the Maker‑Hours Protection Stack pairs with TimeMeld’s equity model and Observance Graph to propose humane overlaps that shift modestly by region over time. Equity Ledger Lock ensures rotation and burden limits are enforced when meetings move, and Impact Simulator forecasts attendance changes before a shift goes live. Auto Rebalance applies a chosen change across a series with one click and keeps conferencing links intact via Asset Carry‑Through. “Deep work isn’t a luxury at a startup; it’s your competitive edge,” said Priya Nair, VP Engineering at a machine‑learning company that adopted TimeMeld. “Since enabling maker‑hour protections, our sprint throughput improved without adding meetings, and we spend far less time negotiating calendars. People focus, then we meet to decide.” Availability and Admin Controls The Maker‑Hours Protection Stack is available today across TimeMeld Pro and Enterprise. Admins can define standard maker‑hour windows per team and region, set default buffer policies, and configure override rules and compensation options. Detailed logs and APIs support auditability and analytics. About TimeMeld TimeMeld is the lightweight scheduling assistant that eliminates timezone friction for remote‑first teams. It proposes timezone‑weighted, ergonomic meeting windows, automates invites, and maintains a shared equity scoreboard that rotates meeting ownership—cutting scheduling time, preventing repeated inconvenient slots, and improving attendance. Media Contact Elena Park, Communications Lead press@timemeld.com +1 (415) 555‑0147

P

TimeMeld Debuts Invite Hygiene Engine to Eliminate Meeting Confusion and Raise Show‑Rates

Imagined Press Article

San Francisco, CA — TimeMeld today debuted the Invite Hygiene Engine, a practical toolkit that turns vague, messy invites into clear, action‑ready sessions that people actually attend. By standardizing titles, agendas, links, roles, and reminders—with one‑click fixes—TimeMeld removes the confusion and friction that quietly drain show‑rates and burn time across remote‑first teams. Leaders optimize when to meet and who to include, but too often they ignore the invite itself. Missing agendas, stale links, and unclear roles are the hidden tax on execution. TimeMeld’s Invite Hygiene Engine raises the floor by auditing every invite in real time and giving organizers a set of smart, respectful defaults that get results. The Invite Hygiene Engine includes: - Title Tuner: Auto‑rewrites vague subjects into concise, action‑oriented titles with smart tags (Decision, Review, Retro), enforces length and clarity guidelines, and flags filler words. - Agenda Cards: Builds a crisp, time‑boxed agenda from micro‑cards (topic, owner, expected outcome, minutes), suggests realistic durations, and formats clean bullets in the invite. - Link Auditor: Validates conferencing links before send—checks provider, expiry, passcode embedding, host/guest permissions—and auto‑fixes with a safe default to prevent “which link?” confusion. - Prep Pack: Scans the invite for referenced docs, auto‑attaches or links pre‑reads with correct access for externals, adds a brief “Prep by” note, and estimates prep time. - Role Badges: Labels attendees with lightweight roles (Owner, Facilitator, Decision‑Maker, Scribe, Optional) in the invite and ICS so expectations are clear. - Hygiene Score: Real‑time 0–100 score that audits title clarity, agenda completeness, conferencing readiness, attachments, and roles; offers one‑click fixes and optional minimum‑score gating. - Join Precheck and Calendar Deeplink: A pre‑join diagnostic and one‑tap add‑to‑calendar for Google, Outlook, and Apple with ICS fallback ensure smooth entry and up‑to‑date links. - Smart Nudges: Localized reminders at respectful local hours with a single Join Now button and backup dial‑in reduce no‑shows. “Clarity is kindness,” said Arjun Rao, co‑founder and CEO of TimeMeld. “By defaulting to crisp titles, realistic agendas, working links, and clear roles, TimeMeld stops the churn of ‘what is this?’ and ‘which link?’ that frustrate teams and scare off customers. Better invites mean better meetings—fewer, shorter, and more decisive.” Ops leaders and developer advocates are already seeing value. “Our global demo days used to suffer from last‑minute link confusion and unclear objectives,” said Diego Alvarez, a developer relations manager at a distributed dev‑tools company. “With Hygiene Score and Link Auditor, we ship invites that just work, and attendance has noticeably improved.” The engine also supports equity and accessibility. Agenda Cards highlight time‑boxed topics with named owners, giving quieter voices space to prepare. Title Tuner’s smart tags make intent legible across cultures. Auto‑Localize renders dates and times in each guest’s locale with DST handled automatically, while LinkLock provides recipient‑bound magic links with lightweight OTP to keep external entry secure and account‑free. Invite quality ties directly to outcomes in TimeMeld’s analytics. Hygiene Scores correlate with show‑rates and on‑time starts; Drift Heatmap reveals underperforming windows by region and hour; and Impact Simulator lets organizers test whether small time shifts plus better hygiene can lift attendance more humanely than broad changes. Auto Rebalance applies chosen adjustments across series without breaking agendas or conferencing links thanks to Asset Carry‑Through. For leaders, admin policies make quality scalable. Teams can set minimum Hygiene Scores for invites that include customers or executives, enable auto‑fixes for missing links and roles, and standardize agenda templates by meeting type. Alerts identify recurring issues—like stale rooms or missing dial‑ins—so enablement teams can educate once and fix for good. “Invite hygiene is the quiet multiplier for every scheduling decision,” said Maya Laurent, head of product at TimeMeld. “We’re giving teams the fastest path to clear, respectful invites that improve participation without adding process overhead. It’s one of those upgrades you feel immediately.” Availability The Invite Hygiene Engine is available today across TimeMeld Pro and Enterprise with no additional charge. Admins can configure default templates, minimum score gates, and auto‑fix policies; APIs expose Hygiene Scores and invite metadata for reporting. About TimeMeld TimeMeld is the lightweight scheduling assistant that eliminates timezone friction for remote‑first teams. It proposes timezone‑weighted, ergonomic meeting windows, automates invites, and maintains a shared equity scoreboard that rotates meeting ownership—cutting scheduling time, preventing repeated inconvenient slots, and improving attendance. Media Contact Elena Park, Communications Lead press@timemeld.com +1 (415) 555‑0147

P

TimeMeld Rolls Out Ownership Rotation and Continuity Suite to Keep Critical Rituals on Track and Fair

Imagined Press Article

San Francisco, CA — TimeMeld today rolled out the Ownership Rotation and Continuity Suite, a practical set of tools that keeps recurring rituals—standups, retros, postmortems, sprint reviews—on track and fair across time zones. By automating facilitator hand‑offs, surfacing risks early, and enforcing rotation with humane safeguards, TimeMeld helps teams avoid last‑minute scrambles and silent bias creep. Recurring ceremonies thrive on clarity and continuity. In distributed environments, ownership often slips between the cracks, leading to rushed prep, uneven burden on the same regions, and missed opportunities for inclusive participation. TimeMeld now closes those gaps with a suite that combines proactive nudges with equity‑aware automation, all wired into the shared scoreboard teams can trust. The suite includes: - Owner Heads‑Up: A proactive DM and email to the next facilitator with one‑tap Confirm, Swap, or Defer. Includes date/time in their locale, agenda preview, and a prep checklist with a confirm‑by timer. - Handoff Watch: A lightweight checklist that tracks the ownership hand‑off—facilitator role, agenda finalization, links, recording prefs. If any step lags, it nudges the current and next owner with specific to‑dos and due times. - QuickSwap: Instant swap from DM/email with auto‑suggested eligible alternates based on availability, timezone burden, and rotation fairness. One tap updates role badges, the equity scoreboard, and reminders—no back‑and‑forth. - Auto‑Rotate Failover: If the upcoming owner hasn’t confirmed by the deadline, TimeMeld auto‑assigns the next fair facilitator, notifies stakeholders, and logs the equity adjustment, respecting PTO/travel and quiet hours. - Equity Pulse: Live micro‑updates to the equity scoreboard with a post‑meeting fairness receipt that shows who carried early/late and who’s up next. Subtle alerts trigger when someone nears an over‑burden threshold. - Nudge Ladder: Adaptive escalation that starts with a quiet‑hours‑aware DM, then a friendly thread ping, and finally a discreet manager heads‑up if needed—stopping as soon as ownership is confirmed. - Backup Buddy: Owners can designate a backup facilitator. When risk signals appear (travel, non‑response), the backup is auto‑prepped with agenda and links and can be promoted in one tap. “Great rituals run on trust and preparation,” said Arjun Rao, co‑founder and CEO of TimeMeld. “We built a system that takes ownership seriously without adding ceremony about the ceremony. It keeps rotations fair, gives facilitators the context they need, and quietly rescues sessions when life happens.” Teams feel the difference in both predictability and inclusion. “We rotate sprint reviews across regions, and before TimeMeld the hand‑off was ad‑hoc,” said Ivy Chen, a talent and operations leader at a growth‑stage startup. “Owner Heads‑Up and Handoff Watch make the next facilitator crystal clear, and QuickSwap resolves conflicts without politics. Our show‑rates are up, and everyone knows when it’s their turn.” The suite integrates deeply with TimeMeld’s scheduling engine. Equity Ledger Lock enforces burden limits when meeting times shift; Observance Graph and Holiday Mesh prevent inadvertent clashes with local observances; and the Invite Hygiene Engine ensures titles, agendas, and links are crisp. If a reschedule becomes necessary, Slipstream’s RippleGuard Rebook finds the nearest fair window that protects maker hours, and Asset Carry‑Through preserves the agenda and conferencing details. Leaders gain visibility without micromanaging. Equity Pulse dashboards show rotation health by team and region, highlighting who has carried early/late and where the next few owners sit. Drift Radar surfaces attempted guard breaches that correlate with ownership risk, while Adaptive Baselines ensure alerts trigger only when deviations are meaningful for that team’s seasonality. For external‑facing rituals—customer councils, community AMAs, partner QBRs—the suite pairs with LinkLock for secure, account‑free entry and Auto‑Localize for accurate regional timing. Smart Nudges send clean, localized reminders with a Join Now button and backup dial‑in, improving attendance without flooding inboxes. “Ownership is a muscle; we just needed better fibers,” said Omar Haddad, head of engineering operations at a distributed fintech. “Since enabling Auto‑Rotate Failover and Backup Buddy, we haven’t missed a retro, and nobody feels singled out. The fairness receipts actually changed the conversation for the better.” Availability and Admin Controls The Ownership Rotation and Continuity Suite is available today across TimeMeld Pro and Enterprise. Admins can define rotation rules, confirm‑by windows, and escalation policies; map facilitator eligibility by role; and export Equity Pulse data to analytics tools via API. About TimeMeld TimeMeld is the lightweight scheduling assistant that eliminates timezone friction for remote‑first teams. It proposes timezone‑weighted, ergonomic meeting windows, automates invites, and maintains a shared equity scoreboard that rotates meeting ownership—cutting scheduling time, preventing repeated inconvenient slots, and improving attendance across AMER/EMEA/APAC. Media Contact Elena Park, Communications Lead press@timemeld.com +1 (415) 555‑0147

Want More Amazing Product Ideas?

Subscribe to receive a fresh, AI-generated product idea in your inbox every day. It's completely free, and you might just discover your next big thing!

Product team collaborating

Transform ideas into products

Full.CX effortlessly brings product visions to life.

This product was entirely generated using our AI and advanced algorithms. When you upgrade, you'll gain access to detailed product requirements, user personas, and feature specifications just like what you see below.