Add change spec: email-based conversation matching

Replace thread-ID-based conversation matching with email-address-based
matching for more reliable conversation continuity. Key changes:

- One conversation per email address (simpler model)
- No data expiration (conversations persist indefinitely)
- Post-completion support (questions and registration updates)
- Versioned storage for registration updates (audit trail)
- Admin notifications for registration changes

This addresses the gap where parents sending new emails (instead of
replying) would lose their registration progress.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-20 22:00:21 +01:00
co-authored by Claude Opus 4.5
parent 4d44d4ee58
commit b10ff7a4fe
7 changed files with 346 additions and 0 deletions
@@ -0,0 +1,42 @@
## MODIFIED Requirements
### Requirement: System identifies conversations by sender email address
The system SHALL identify conversations by the sender's email address, not by email threading headers. Each unique email address corresponds to exactly one conversation.
#### Scenario: New email from unknown address
- **WHEN** an email arrives from an address with no existing conversation
- **THEN** the system SHALL create a new conversation keyed by that email address
#### Scenario: New email from known address (any thread)
- **WHEN** an email arrives from an address with an existing conversation
- **THEN** the system SHALL continue that existing conversation regardless of email threading headers
#### Scenario: Email address normalization
- **WHEN** comparing email addresses for matching
- **THEN** the system SHALL normalize addresses (lowercase, trim whitespace) so that `Maria@Example.com` matches `maria@example.com`
### Requirement: Thread headers used for reply threading only
The system SHALL use email threading headers (`In-Reply-To`, `References`) for outbound replies to maintain proper email client threading, but SHALL NOT use them for conversation matching.
#### Scenario: Reply includes threading headers
- **WHEN** the agent sends a reply email
- **THEN** the reply SHALL include `In-Reply-To` referencing the most recent inbound message ID
- **AND** the reply SHALL include `References` header for the email thread chain
#### Scenario: Threading headers ignored for matching
- **WHEN** an inbound email has threading headers pointing to a different conversation
- **THEN** the system SHALL ignore those headers and match by sender email address only
## REMOVED Requirements
### Requirement: Email data retention and expiration
**Reason**: With email-address-based matching, conversations are permanent records. No automatic expiration needed.
**Migration**: Remove any scheduled cleanup jobs; existing conversations remain accessible indefinitely.
### Requirement: Day 30 data clearing
**Reason**: No longer applicable; data persists indefinitely.
**Migration**: None required.
### Requirement: "Registration will expire" warning
**Reason**: No expiration means no warning needed.
**Migration**: Remove from reminder sequence.
@@ -0,0 +1,52 @@
## MODIFIED Requirements
### Requirement: Conversations keyed by email address
The system SHALL store conversations using the sender's normalized email address as the unique key, replacing thread-ID-based storage.
#### Scenario: Conversation file naming
- **WHEN** storing a conversation for `parent@example.com`
- **THEN** the system SHALL use a filename derived from the email address (e.g., `parent_at_example.com.json`)
#### Scenario: Conversation lookup
- **WHEN** loading a conversation for an incoming email
- **THEN** the system SHALL lookup by normalized sender email address
### Requirement: Registration updates stored as versions
The system SHALL store registration updates as separate versions, preserving the original and all subsequent changes for audit purposes.
#### Scenario: Initial registration stored
- **WHEN** a registration is completed for the first time
- **THEN** the system SHALL store it as version 1 with timestamp
#### Scenario: Registration update creates new version
- **WHEN** a parent requests changes to a completed registration
- **THEN** the system SHALL store the updated data as a new version
- **AND** the system SHALL preserve all previous versions
#### Scenario: Version metadata
- **WHEN** storing a registration version
- **THEN** the version SHALL include: version number, timestamp, and change summary (which fields changed)
### Requirement: Current registration accessible
The system SHALL provide easy access to the current (latest) registration data while preserving version history.
#### Scenario: Retrieve current registration
- **WHEN** the admin or system requests the current registration for an email address
- **THEN** the system SHALL return the most recent version
#### Scenario: Retrieve version history
- **WHEN** the admin requests registration history for an email address
- **THEN** the system SHALL return all versions in chronological order
## ADDED Requirements
### Requirement: Post-completion conversation state
The system SHALL support a "completed" conversation state that allows continued interaction for questions and updates.
#### Scenario: Conversation continues after completion
- **WHEN** a parent sends an email after their registration is complete
- **THEN** the system SHALL load the existing conversation and process the message
#### Scenario: Intent detection for post-completion messages
- **WHEN** processing a message in a completed conversation
- **THEN** the system SHALL detect intent: question, update request, or new child registration
@@ -0,0 +1,48 @@
## ADDED Requirements
### Requirement: Notify admin on registration updates
The system SHALL send an email notification to the admin when an existing registration is updated, including details of what changed.
#### Scenario: Update notification sent
- **WHEN** a parent updates their completed registration
- **THEN** the admin SHALL receive an email notification
#### Scenario: Update notification content
- **WHEN** sending an update notification
- **THEN** the notification SHALL include:
- Child name and registration ID
- What changed (field name, old value → new value)
- When the change was made
- Version number (e.g., "Version 2 of 2")
#### Scenario: Update notification routing
- **WHEN** sending an update notification
- **THEN** the notification SHALL be routed to the same recipients as the original registration (based on playgroup type)
### Requirement: Distinguish new vs update notifications
The system SHALL clearly distinguish between new registration notifications and update notifications in the email subject and content.
#### Scenario: New registration subject
- **WHEN** sending a notification for a new registration
- **THEN** the subject SHALL be "New Registration: [Child Name] for [Playgroup Type]"
#### Scenario: Update notification subject
- **WHEN** sending a notification for a registration update
- **THEN** the subject SHALL be "Registration Updated: [Child Name]"
## MODIFIED Requirements
### Requirement: Email reminders for incomplete registrations
The system SHALL send reminder emails for incomplete registrations, but SHALL NOT threaten data deletion since data no longer expires.
#### Scenario: Reminder content without expiration warning
- **WHEN** sending a reminder for an incomplete registration
- **THEN** the reminder SHALL encourage completion but SHALL NOT mention data expiration or deletion
#### Scenario: Reminder schedule unchanged
- **WHEN** an incomplete registration exists
- **THEN** reminders SHALL be sent at Day 3, Day 10, and Day 25 after last activity
#### Scenario: Reminders stop after completion
- **WHEN** a registration is completed
- **THEN** no further reminders SHALL be sent for that conversation