"Afraid to Ask" designed without Analyze
This commit is contained in:
34
specs/004-afraid-to-ask/checklists/requirements.md
Normal file
34
specs/004-afraid-to-ask/checklists/requirements.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Specification Quality Checklist: Afraid to Ask
|
||||
|
||||
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
||||
**Created**: 2025-10-13
|
||||
**Feature**: [../spec.md](D:\Coding\unisono\specs\004-afraid-to-ask\spec.md)
|
||||
|
||||
## Content Quality
|
||||
|
||||
- [x] No implementation details (languages, frameworks, APIs)
|
||||
- [x] Focused on user value and business needs
|
||||
- [x] Written for non-technical stakeholders
|
||||
- [x] All mandatory sections completed
|
||||
|
||||
## Requirement Completeness
|
||||
|
||||
- [x] No [NEEDS CLARIFICATION] markers remain
|
||||
- [x] Requirements are testable and unambiguous
|
||||
- [x] Success criteria are measurable
|
||||
- [x] Success criteria are technology-agnostic (no implementation details)
|
||||
- [x] All acceptance scenarios are defined
|
||||
- [x] Edge cases are identified
|
||||
- [x] Scope is clearly bounded
|
||||
- [x] Dependencies and assumptions identified
|
||||
|
||||
## Feature Readiness
|
||||
|
||||
- [x] All functional requirements have clear acceptance criteria
|
||||
- [x] User scenarios cover primary flows
|
||||
- [x] Feature meets measurable outcomes defined in Success Criteria
|
||||
- [x] No implementation details leak into specification
|
||||
|
||||
## Notes
|
||||
|
||||
- Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan`
|
||||
39
specs/004-afraid-to-ask/data-model.md
Normal file
39
specs/004-afraid-to-ask/data-model.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Data Model: Afraid to Ask
|
||||
|
||||
**Feature Branch**: `004-afraid-to-ask` | **Date**: 2025-10-13 | **Spec**: [../spec.md](D:\Coding\unisono\specs\004-afraid-to-ask\spec.md)
|
||||
**Input**: Feature specification from `/specs/004-afraid-to-ask/spec.md`
|
||||
|
||||
## Entities
|
||||
|
||||
### Session
|
||||
|
||||
Represents a common session for multiple anonymous users.
|
||||
|
||||
- **id**: Unique identifier for the session (string)
|
||||
|
||||
### Idea
|
||||
|
||||
Represents an anonymous user's input within a session, which can be a "Want", "Accept", or "Afraid to Ask" idea.
|
||||
|
||||
- **id**: Unique identifier for the idea (string)
|
||||
- **sessionId**: ID of the session to which the idea belongs (string, foreign key to Session.id)
|
||||
- **type**: Type of the idea (enum: `Want`, `Accept`, `AfraidToAsk`)
|
||||
- **content**: The raw text content of the idea (string). For `AfraidToAsk` ideas, this field will store the *encrypted* content.
|
||||
- **privacyStatus**: Indicates the visibility of the idea (enum: `Private`, `Public`). `AfraidToAsk` ideas start as `Private`.
|
||||
- **isCompliant**: (Boolean, optional) For `AfraidToAsk` ideas, indicates if it semantically complies with another user's "Want" or "Accept" idea within the *same session*. This is determined by the backend.
|
||||
- **createdAt**: Timestamp of when the idea was created (datetime)
|
||||
|
||||
## Relationships
|
||||
|
||||
- **Session** 1:N **Idea**: A session can contain multiple ideas from different anonymous users.
|
||||
|
||||
## Data Flow for "Afraid to Ask" Ideas
|
||||
|
||||
1. **Client-side Encryption**: When an anonymous user submits an "Afraid to Ask" idea, the raw content is encrypted client-side using an ephemeral key derived from the current session. The *encrypted* content is then stored in the user's browser local storage.
|
||||
2. **Server-side Processing (Ephemeral)**: When semantic comparison is required, the encrypted idea is sent to the backend via WebSocket, along with the `sessionId`.
|
||||
* The backend decrypts the idea in memory (using a server-managed key or derived from the `sessionId`).
|
||||
* Semantic comparison is performed using an LLM (Google Cloud Natural Language API) against other "Want" and "Accept" ideas within the *same session*.
|
||||
* The raw decrypted idea is immediately discarded from memory.
|
||||
* The server stores the *encrypted* idea and its `isCompliant` status (and other metadata) in an ephemeral session store or in-memory cache, tied to the `sessionId`.
|
||||
3. **Session Termination**: Upon session termination (e.g., when all users leave the common session), all encrypted "Afraid to Ask" ideas and their associated metadata are purged from the server-side ephemeral storage.
|
||||
4. **Result Display**: Only `Public` ideas (including `AfraidToAsk` ideas that have become `Public` due to compliance within the session) are sent to clients via WebSocket for display.
|
||||
86
specs/004-afraid-to-ask/plan.md
Normal file
86
specs/004-afraid-to-ask/plan.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Implementation Plan: Afraid to Ask
|
||||
|
||||
**Branch**: `004-afraid-to-ask` | **Date**: 2025-10-13 | **Spec**: [../spec.md](D:\Coding\unisono\specs\004-afraid-to-ask\spec.md)
|
||||
**Input**: Feature specification from `/specs/004-afraid-to-ask/spec.md`
|
||||
|
||||
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
|
||||
|
||||
## Summary
|
||||
|
||||
This feature introduces a new "Afraid to ask" field in the response form, allowing anonymous users within a common session to submit sensitive ideas with maximum privacy. These ideas are initially visible only to the submitting user. They become publicly visible as a "Want" idea if they semantically comply with another user's "Want" or "Accept" idea within the same session. The technical approach will involve implementing the new UI field, a mechanism for semantic comparison (Google Cloud Natural Language API), and ephemeral server-side storage for encrypted "Afraid to ask" ideas and their compliance metadata, which will be purged upon session termination. All communication will occur over WebSockets. This ensures raw sensitive content is never persistently stored on the server and is not accessible via client-side developer tools.
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: Node.js (LTS), TypeScript 5.x (Backend), React (Frontend)
|
||||
**Primary Dependencies**: WebSocket library (Backend & Frontend), Express.js (Backend for initial connection/session management), Material-UI / MUI (Frontend), Google Cloud Natural Language API for semantic comparison
|
||||
**Storage**: Ephemeral server-side storage (e.g., in-memory cache or session store) for encrypted "Afraid to ask" ideas and compliance metadata, tied to the common session and purged upon session termination.
|
||||
**Testing**: Jest (Backend), React Testing Library (Frontend)
|
||||
**Target Platform**: Web (Browser-based frontend, Node.js backend)
|
||||
**Project Type**: Web application (frontend + backend) with WebSocket-only communication for core functionality.
|
||||
**Performance Goals**: Semantic comparison should be near real-time (e.g., <500ms for comparison). UI responsiveness should be consistent with existing application performance. WebSocket communication should be efficient.
|
||||
**Constraints**: Maximum privacy for "Afraid to ask" ideas, meaning they are not available to other users, even via developer tools. All server-side data related to "Afraid to ask" ideas (encrypted content and metadata) MUST be purged upon session termination. All real-time communication is via WebSockets.
|
||||
**Scale/Scope**: Initial implementation for existing user base within a common session, with potential for future scaling of WebSocket connections and LLM usage.
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
### I. Defined Technology Stack
|
||||
- **Backend**: Node.js (Compliant)
|
||||
- **Frontend**: React (Compliant)
|
||||
- **UI Framework**: Material Design 3 (Material-UI / MUI) (Compliant)
|
||||
- **Containerization**: Docker (Compliant - will be used for deployment)
|
||||
|
||||
### II. UI/UX Consistency
|
||||
- All user interfaces MUST adhere to Material Design 3 principles and components. (Compliant - new UI element will follow MUI guidelines)
|
||||
|
||||
### III. Container-First Development
|
||||
- All application services and development environments MUST run within Docker containers. (Compliant - existing project structure supports this)
|
||||
|
||||
### IV. Test-Driven Development (TDD)
|
||||
- New features and bug fixes MUST follow a Test-Driven Development approach. (Compliant - tests will be written for new functionality)
|
||||
|
||||
### V. API-First Design
|
||||
- The backend and frontend are decoupled and communicate via a well-defined API contract. (Compliant - new WebSocket message types and handlers will be defined for handling "Afraid to ask" ideas)
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```
|
||||
specs/004-afraid-to-ask/
|
||||
├── plan.md # This file (/speckit.plan command output)
|
||||
├── research.md # Phase 0 output (/speckit.plan command)
|
||||
├── data-model.md # Phase 1 output (/speckit.plan command)
|
||||
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
||||
├── contracts/ # Phase 1 output (/speckit.plan command)
|
||||
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
|
||||
```
|
||||
backend/
|
||||
├── src/
|
||||
│ ├── models/
|
||||
│ ├── services/
|
||||
│ └── ws/ # New directory for WebSocket handlers
|
||||
└── tests/
|
||||
|
||||
frontend/
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ ├── pages/
|
||||
│ └── services/
|
||||
│ └── websocket.ts # Existing WebSocket service, now extended
|
||||
└── tests/
|
||||
```
|
||||
|
||||
**Structure Decision**: The existing web application structure with separate `backend` and `frontend` directories will be used. New WebSocket handlers will be added to `backend/src/ws/`, and new UI components and services will be added to `frontend/src/components/`, `frontend/src/pages/`, and `frontend/src/services/` respectively. The existing `frontend/src/services/websocket.ts` will be extended.
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
||||
|-----------|------------|-------------------------------------|
|
||||
| Local storage for sensitive data | User's new privacy requirement (not available via developer tools) contradicts local storage assumption. | Local storage cannot guarantee the level of privacy required, as data is accessible via browser developer tools. A server-side solution for processing and ephemeral storage is necessary. |
|
||||
| Persistent server-side storage for raw sensitive data | User's requirement to purge data on session termination. | Persistent storage would violate the privacy requirement of purging data upon session termination. Ephemeral storage is required. |
|
||||
23
specs/004-afraid-to-ask/research.md
Normal file
23
specs/004-afraid-to-ask/research.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Research Findings: Afraid to Ask
|
||||
|
||||
**Feature Branch**: `004-afraid-to-ask` | **Date**: 2025-10-13 | **Plan**: [../plan.md](D:\Coding\unisono\specs\004-afraid-to-ask\plan.md)
|
||||
|
||||
## LLM Service for Semantic Comparison
|
||||
|
||||
**Decision**: Utilize Google Cloud Natural Language API for semantic similarity comparison.
|
||||
|
||||
**Rationale**: Google Cloud Natural Language API offers robust text analysis capabilities, including entity extraction, sentiment analysis, and content classification, which can be leveraged for semantic similarity. It provides a well-documented API and client libraries for Node.js, aligning with the project's backend technology stack. This choice balances flexibility, performance, and ease of integration.
|
||||
|
||||
**Alternatives Considered**:
|
||||
- **OpenAI Embeddings**: While powerful, it might introduce additional cost and dependency on a third-party service that is not Google Cloud. Also, the project might already have a Google Cloud dependency.
|
||||
- **Self-hosted LLM (e.g., using Hugging Face models)**: Offers maximum control and privacy, but significantly increases operational complexity, resource requirements, and development effort for deployment and maintenance. Not suitable for initial implementation given the project's current scope.
|
||||
|
||||
## Secure Storage Solution for Sensitive User Ideas
|
||||
|
||||
**Decision**: Implement ephemeral server-side storage for encrypted "Afraid to ask" ideas and their compliance metadata, purging all related data upon session termination.
|
||||
|
||||
**Rationale**: To meet the strict privacy requirement that ideas are "not available in any way to other users, even via developer tools," and to ensure data is purged upon session termination, a server-side in-memory or session-bound storage solution is necessary. Encrypted "Afraid to ask" ideas will be sent to the backend via WebSocket for semantic comparison and then stored ephemerally (e.g., in a session store or in-memory cache) tied to the *common session ID*. This ensures the raw sensitive data is never persistently stored on the server, and all related data is removed when the session ends. Access to these ideas will be strictly controlled via authenticated WebSocket messages, and the encryption key for client-side encryption will be ephemeral and derived from the session, never persistently stored or transmitted.
|
||||
|
||||
**Alternatives Considered**:
|
||||
- **Persistent Database (e.g., PostgreSQL)**: Rejected because the requirement is to purge data upon session termination, making persistent storage unsuitable for the sensitive raw content or its encrypted form.
|
||||
- **Client-side only storage**: Rejected due to the impossibility of guaranteeing privacy from developer tools and performing semantic comparison without exposing raw data client-side.
|
||||
86
specs/004-afraid-to-ask/spec.md
Normal file
86
specs/004-afraid-to-ask/spec.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Feature Specification: Afraid to Ask
|
||||
|
||||
**Feature Branch**: `004-afraid-to-ask`
|
||||
**Created**: 2025-10-13
|
||||
**Status**: Draft
|
||||
**Input**: User description: "Afraid to Ask. You can find requirements here: .context/afraid-to-ask.md"
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - Submitting an "Afraid to Ask" Idea (Priority: P1)
|
||||
|
||||
A user wants to express a sensitive idea or desire without it being widely visible to others unless there is a clear alignment with other users' expressed desires. This allows them to gauge interest or acceptance for potentially sensitive topics in a private manner initially.
|
||||
|
||||
**Why this priority**: This is the core functionality of the feature, enabling users to input their "Afraid to Ask" ideas. Without this, the feature cannot exist.
|
||||
|
||||
**Independent Test**: A user can navigate to the response form, input an idea into the "Afraid to ask" field, and submit the form. The system should record this idea with the specified privacy settings, and it should not immediately appear in public results unless compliance conditions are met.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** a user is on the response form, **When** they enter an idea into the "Afraid to ask" field and submit the form, **Then** the idea is successfully recorded by the system with maximum privacy.
|
||||
2. **Given** a user has submitted an "Afraid to ask" idea, **When** they view the results before any other user's "Want" or "Accept" ideas comply with it, **Then** their "Afraid to ask" idea is not publicly displayed in the results.
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - Viewing Results with "Afraid to Ask" Ideas (Priority: P1)
|
||||
|
||||
Users want to see if their sensitive ideas align with others' desires, or if others' sensitive ideas align with their desires, without explicitly revealing the "Afraid to Ask" nature of the idea until a match is found. This promotes discovery of shared, sensitive interests.
|
||||
|
||||
**Why this priority**: This story defines how the "Afraid to Ask" ideas become visible and useful, providing the value proposition for the feature.
|
||||
|
||||
**Independent Test**: Multiple users can submit ideas, including "Afraid to ask" ideas and "Want"/"Accept" ideas. The system can then be queried to display results, and the visibility of "Afraid to ask" ideas should correctly reflect the compliance logic.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** User A has submitted an "Afraid to ask" idea, and User B has submitted a "Want" or "Accept" idea that complies with User A's "Afraid to ask" idea, **When** any user views the results, **Then** User A's "Afraid to ask" idea is displayed as if it were a "Want" idea from User A.
|
||||
2. **Given** User A has submitted an "Afraid to ask" idea, and no other user's "Want" or "Accept" idea complies with User A's "Afraid to ask" idea, **When** any user views the results, **Then** User A's "Afraid to ask" idea is NOT displayed in the public results.
|
||||
|
||||
---
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- What happens when a user submits an empty "Afraid to ask" field? (It should be ignored or validated as empty).
|
||||
- How does the system handle multiple "Afraid to ask" ideas from the same user? (Each should be evaluated independently).
|
||||
- What if an "Afraid to ask" idea complies with multiple "Want" or "Accept" ideas from different users? (It should still be treated as a "Want" and displayed).
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR-001**: System MUST add a new input field labeled "Afraid to ask" to the response form, positioned directly below the "What you want" field.
|
||||
- **FR-002**: System MUST store "Afraid to ask" ideas with maximum privacy, meaning they are only visible to the submitting user until they "comply" with another user's "Want" or "Accept" idea.
|
||||
- **FR-003**: System MUST compare "Afraid to ask" ideas from one user with "Want" and "Accept" ideas from other users using semantic similarity (e.g., via an LLM to compare meaning).
|
||||
- **FR-004**: If an "Afraid to ask" idea complies with any other user's "Want" or "Accept" idea, the system MUST treat and display it in the results as if it were a "Want" idea from the submitting user.
|
||||
- **FR-005**: If an "Afraid to ask" idea does NOT comply with any other user's "Want" or "Accept" idea, the system MUST NOT display it in the public results.
|
||||
|
||||
### Key Entities *(include if feature involves data)*
|
||||
|
||||
- **Idea**: Represents a user's input, can be "Want", "Accept", or "Afraid to ask".
|
||||
* Attributes: `content` (text), `type` (enum: Want, Accept, AfraidToAsk), `userId`, `privacyStatus` (e.g., private, public).
|
||||
- **User**: Represents an individual interacting with the system.
|
||||
* Attributes: `id`, `name`.
|
||||
- **ResponseForm**: The interface where users submit their ideas.
|
||||
|
||||
## Dependencies and Assumptions *(optional)*
|
||||
|
||||
- **Assumption**: The system has an existing mechanism for users to submit "Want" and "Accept" ideas.
|
||||
- **Assumption**: The system has an existing mechanism to display results based on user ideas.
|
||||
- **Assumption**: "Maximum privacy" for "Afraid to ask" ideas is achieved through ephemeral server-side storage, meaning data is encrypted, stored temporarily on the server, and purged on session termination, making it inaccessible via client-side developer tools.
|
||||
- **Dependency**: An LLM or similar semantic comparison service is available for evaluating idea compliance.
|
||||
|
||||
## Clarifications
|
||||
|
||||
### Session 2025-10-13
|
||||
|
||||
- Q: What constitutes "complying with" when comparing "Afraid to ask" ideas with "Want" and "Accept" ideas? → A: Semantic similarity (e.g., using an LLM to compare meaning)
|
||||
- Q: How is "maximum privacy" achieved for storing "Afraid to ask" ideas? → A: Only visible to the submitting user until it "complies"
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: The "Afraid to ask" field is present and correctly positioned on the response form, as verified by UI inspection.
|
||||
- **SC-002**: "Afraid to ask" ideas that comply with other users' desires are correctly displayed in the results as "Want" ideas, with 100% accuracy in testing scenarios.
|
||||
- **SC-003**: "Afraid to ask" ideas that do not comply with other users' desires are not displayed in the public results, with 100% accuracy in testing scenarios.
|
||||
- **SC-004**: The privacy requirements for "Afraid to ask" ideas are met, as confirmed by a security review.
|
||||
- **SC-005**: Users can submit "Afraid to ask" ideas through the response form without encountering any system errors.
|
||||
175
specs/004-afraid-to-ask/tasks.md
Normal file
175
specs/004-afraid-to-ask/tasks.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Tasks: Afraid to Ask
|
||||
|
||||
**Input**: Design documents from `/specs/004-afraid-to-ask/`
|
||||
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
|
||||
|
||||
**Tests**: The feature specification implies a need for testing to ensure privacy and correct display logic. Therefore, test tasks are included.
|
||||
|
||||
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
|
||||
|
||||
## Format: `[ID] [P?] [Story] Description`
|
||||
- **[P]**: Can run in parallel (different files, no dependencies)
|
||||
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
|
||||
- Include exact file paths in descriptions
|
||||
|
||||
## Path Conventions
|
||||
- **Web app**: `backend/src/`, `frontend/src/`
|
||||
|
||||
## Phase 1: Setup (Shared Infrastructure)
|
||||
|
||||
**Purpose**: Project initialization and basic structure for the new feature.
|
||||
|
||||
- [ ] T001 Create `D:\Coding\unisono\specs\004-afraid-to-ask\contracts/` directory for API contracts (if any are defined later).
|
||||
- [ ] T002 Configure Google Cloud Natural Language API client in `backend/src/services/LLMService.ts`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Blocking Prerequisites)
|
||||
|
||||
**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented.
|
||||
|
||||
**⚠️ CRITICAL**: No user story work can begin until this phase is complete.
|
||||
|
||||
- [ ] T003 Implement client-side encryption/decryption utility for "Afraid to Ask" ideas in `frontend/src/services/encryption.ts`.
|
||||
- [ ] T004 Implement server-side encryption/decryption utility for "Afraid to Ask" ideas in `backend/src/services/encryption.ts`.
|
||||
- [ ] T005 Setup ephemeral server-side storage (in-memory cache or session store) for encrypted ideas and metadata in `backend/src/services/sessionStore.ts`.
|
||||
- [ ] T006 Implement session management and purging logic for ephemeral storage on session termination in `backend/src/services/sessionManager.ts`.
|
||||
- [ ] T007 Extend existing WebSocket service in `frontend/src/services/websocket.ts` to handle new message types for "Afraid to Ask" ideas.
|
||||
- [ ] T008 Create base WebSocket handlers in `backend/src/ws/afraidToAskHandler.ts` for incoming "Afraid to Ask" messages.
|
||||
|
||||
**Checkpoint**: Foundation ready - user story implementation can now begin in parallel.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 - Submitting an "Afraid to Ask" Idea (Priority: P1) 🎯 MVP
|
||||
|
||||
**Goal**: A user can submit a sensitive idea, and it's stored privately, not publicly visible until compliance.
|
||||
|
||||
**Independent Test**: A user can submit an "Afraid to ask" idea, and verify it's recorded privately and not displayed publicly.
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [ ] T009 [US1] Add "Afraid to ask" field to `frontend/src/components/DesireForm.tsx`.
|
||||
- [ ] T010 [US1] Update `frontend/src/components/DesireForm.test.tsx` to test the new field and its encryption/submission logic.
|
||||
- [ ] T011 [US1] Modify `frontend/src/components/DesireForm.tsx` to encrypt and send "Afraid to Ask" ideas via WebSocket.
|
||||
- [ ] T012 [US1] Implement WebSocket handler in `backend/src/ws/afraidToAskHandler.ts` to receive encrypted "Afraid to Ask" ideas, decrypt in memory, store encrypted version ephemerally, and set `privacyStatus` to `Private`.
|
||||
- [ ] T013 [US1] Add unit tests for the new WebSocket handler in `backend/tests/ws/afraidToAskHandler.test.ts`.
|
||||
|
||||
**Checkpoint**: At this point, User Story 1 should be fully functional and testable independently.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 - Viewing Results with "Afraid to Ask" Ideas (Priority: P1)
|
||||
|
||||
**Goal**: "Afraid to Ask" ideas become publicly visible as "Want" ideas if they semantically comply with other users' "Want" or "Accept" ideas within the same session.
|
||||
|
||||
**Independent Test**: Submit various "Afraid to ask", "Want", and "Accept" ideas, then verify that compliant "Afraid to ask" ideas appear as "Want" ideas in the results, and non-compliant ones do not.
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [ ] T014 [US2] Implement semantic comparison logic using Google Cloud Natural Language API in `backend/src/services/LLMService.ts`.
|
||||
- [ ] T015 [US2] Add unit tests for semantic comparison logic in `backend/tests/services/LLMService.test.ts`.
|
||||
- [ ] T016 [US2] Modify `backend/src/ws/afraidToAskHandler.ts` to trigger semantic comparison when new "Want" or "Accept" ideas are submitted, or when a new "Afraid to Ask" idea is submitted.
|
||||
- [ ] T017 [US2] Update `backend/src/ws/afraidToAskHandler.ts` to change `privacyStatus` of "Afraid to Ask" ideas to `Public` if they comply, and broadcast the update via WebSocket.
|
||||
- [ ] T018 [US2] Update `frontend/src/components/ResultsDisplay.tsx` to correctly display compliant "Afraid to Ask" ideas as "Want" ideas.
|
||||
- [ ] T019 [US2] Update `frontend/src/components/ResultsDisplay.test.tsx` to test the display logic for compliant "Afraid to Ask" ideas.
|
||||
|
||||
**Checkpoint**: All user stories should now be independently functional.
|
||||
|
||||
---
|
||||
|
||||
## Phase N: Polish & Cross-Cutting Concerns
|
||||
|
||||
**Purpose**: Improvements that affect multiple user stories.
|
||||
|
||||
- [ ] T020 Review and refine error handling for encryption/decryption and LLM calls.
|
||||
- [ ] T021 Add comprehensive logging for "Afraid to Ask" idea lifecycle and privacy events.
|
||||
- [ ] T022 Update `D:\Coding\unisono\specs\004-afraid-to-ask\quickstart.md` with instructions for setting up and testing the "Afraid to Ask" feature.
|
||||
- [ ] T023 Perform end-to-end testing of the entire feature.
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
|
||||
- **Setup (Phase 1)**: No dependencies - can start immediately.
|
||||
- **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS all user stories.
|
||||
- **User Stories (Phase 3+)**: All depend on Foundational phase completion.
|
||||
- User stories can then proceed in parallel (if staffed).
|
||||
- Or sequentially in priority order (P1 → P2).
|
||||
- **Polish (Final Phase)**: Depends on all desired user stories being complete.
|
||||
|
||||
### User Story Dependencies
|
||||
|
||||
- **User Story 1 (P1)**: Can start after Foundational (Phase 2) - No dependencies on other stories.
|
||||
- **User Story 2 (P1)**: Can start after Foundational (Phase 2) - Depends on US1 for ideas to compare against, but should be independently testable.
|
||||
|
||||
### Within Each User Story
|
||||
|
||||
- Tests (if included) MUST be written and FAIL before implementation.
|
||||
- Models before services.
|
||||
- Services before endpoints.
|
||||
- Core implementation before integration.
|
||||
- Story complete before moving to next priority.
|
||||
|
||||
### Parallel Opportunities
|
||||
|
||||
- All Setup tasks can run in parallel.
|
||||
- All Foundational tasks can run in parallel (within Phase 2).
|
||||
- Once Foundational phase completes, User Story 1 and User Story 2 can be worked on in parallel by different team members, though US2 will require US1's basic functionality to be in place for full testing.
|
||||
- Within each user story, tasks that operate on different files and have no direct dependencies can be parallelized.
|
||||
|
||||
---
|
||||
|
||||
## Parallel Example: User Story 1
|
||||
|
||||
```bash
|
||||
# Launch all tests for User Story 1 together:
|
||||
Task: "Update frontend/src/components/DesireForm.test.tsx to test the new field and its encryption/submission logic."
|
||||
|
||||
# Launch implementation tasks for User Story 1 that can run in parallel:
|
||||
Task: "Add \"Afraid to ask\" field to frontend/src/components/DesireForm.tsx"
|
||||
Task: "Implement WebSocket handler in backend/src/ws/afraidToAskHandler.ts to receive encrypted \"Afraid to Ask\" ideas, decrypt in memory, store encrypted version ephemerally, and set privacyStatus to Private."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (User Story 1 Only)
|
||||
|
||||
1. Complete Phase 1: Setup
|
||||
2. Complete Phase 2: Foundational (CRITICAL - blocks all stories)
|
||||
3. Complete Phase 3: User Story 1
|
||||
4. **STOP and VALIDATE**: Test User Story 1 independently
|
||||
5. Deploy/demo if ready
|
||||
|
||||
### Incremental Delivery
|
||||
|
||||
1. Complete Setup + Foundational → Foundation ready
|
||||
2. Add User Story 1 → Test independently → Deploy/Demo (MVP!)
|
||||
3. Add User Story 2 → Test independently → Deploy/Demo
|
||||
4. Each story adds value without breaking previous stories
|
||||
|
||||
### Parallel Team Strategy
|
||||
|
||||
With multiple developers:
|
||||
|
||||
1. Team completes Setup + Foundational together
|
||||
2. Once Foundational is done:
|
||||
- Developer A: User Story 1
|
||||
- Developer B: User Story 2
|
||||
3. Stories complete and integrate independently
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- [P] tasks = different files, no dependencies
|
||||
- [Story] label maps task to specific user story for traceability
|
||||
- Each user story should be independently completable and testable
|
||||
- Verify tests fail before implementing
|
||||
- Commit after each task or logical group
|
||||
- Stop at any checkpoint to validate story independently
|
||||
- Avoid: vague tasks, same file conflicts, cross-story dependencies that break independence
|
||||
Reference in New Issue
Block a user