# Projects+ Phase 6: Goal Completion & Settings - Development Document ## Overview Phase 6 completes the Projects+ MVP by implementing goal completion workflows with reflection, archived goal views, and a dedicated settings tab. This document provides detailed implementation guidance, edge cases, and UI specifications. --- ## Table of Contents 1. [Goal Completion Flow](#1-goal-completion-flow) 2. [Archived Goals View](#2-archived-goals-view) 3. [Projects+ Settings Tab](#3-projects-settings-tab) 4. [Implementation Details](#4-implementation-details) 5. [Edge Cases & Error Handling](#5-edge-cases--error-handling) 6. [Testing Checklist](#6-testing-checklist) --- ## 1. Goal Completion Flow ### 1.1 Triggering the Completion Modal The completion modal can be triggered from multiple locations: #### Entry Points | Location | UI Element | Action | | ---------------------------- | --------------------------- | ---------------------------------------------------- | | **ProjectDetail Footer** | "Complete" button (primary) | Opens `ProjectStatusDialog` with `action="complete"` | | **ProjectCard Context Menu** | "Complete" menu item | Opens `ProjectStatusDialog` with `action="complete"` | | **ProjectCard Quick Action** | Checkmark icon button | Opens `ProjectStatusDialog` with `action="complete"` | #### Current Implementation The completion flow is already wired in `ProjectDetail.tsx`: ```typescript // ProjectDetail.tsx:430-431 ``` This triggers `handleStatusAction("complete")` which opens `ProjectStatusDialog`: ```typescript // ProjectDetail.tsx:135-138 const handleStatusAction = useCallback((action: StatusAction) => { setStatusAction(action); setStatusDialogOpen(true); }, []); ``` ### 1.2 Completion Modal UI Specification The `ProjectStatusDialog` renders different content based on the action type. For completion: ``` ┌─────────────────────────────────────────────────────────┐ │ Complete Project [X] │ ├─────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ You've been working on this project for **5 days** │ │ │ │ with **12 notes** and **3 conversations**. │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ Reflection (optional) │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ What did you learn or accomplish? │ │ │ │ │ │ │ │ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ [Cancel] [Complete Project] │ └─────────────────────────────────────────────────────────┘ ``` #### Journey Summary Component The journey summary uses `calculateJourneySummary()` from `utils.ts`: ```typescript // utils.ts export function calculateJourneySummary(project: Project) { const now = Date.now(); const daysActive = Math.ceil((now - project.createdAt) / (1000 * 60 * 60 * 24)); return { daysActive, notesCount: project.notes.length, conversationsCount: project.conversations.length, }; } ``` ### 1.3 Completion Confirmation Handler ```typescript // ProjectDetail.tsx:140-155 const handleConfirmStatus = useCallback( async (reflection?: string) => { switch (statusAction) { case "complete": await plugin.projectsPlusManager.completeProject(projectId, reflection); break; case "archive": await plugin.projectsPlusManager.archiveProject(projectId); break; case "reactivate": await plugin.projectsPlusManager.reactivateProject(projectId); break; } }, [plugin.projectsPlusManager, projectId, statusAction] ); ``` ### 1.4 Project Status Transitions ``` ┌──────────────┐ │ active │ └──────────────┘ │ ┌─────────┴─────────┐ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ completed │ │ archived │ └──────────────┘ └──────────────┘ │ │ └─────────┬─────────┘ ▼ ┌──────────────┐ │ active │ (reactivate) └──────────────┘ ``` --- ## 2. Archived Goals View ### 2.1 Goal List Filtering Behavior **Design Decision:** Completed goals are NOT shown in the main list by default. Users must use the status filter dropdown to view them. The `ProjectsPanel` already implements this via a status filter: ```typescript // ProjectsPanel.tsx:167-176 ``` ### 2.2 Default Filter Behavior The default filter is `"all"` which shows all projects. However, projects are sorted by `updatedAt` descending, so active projects with recent activity appear first. **Implementation Note:** There is no separate setting for "show completed in list" - the filter dropdown provides this functionality directly. ### 2.3 Completed/Archived Project Detail View When viewing a completed or archived project, the UI should reflect the read-only nature: #### Visual Indicators 1. **Status Badge** - Shows "Completed" or "Archived" with appropriate styling 2. **Reflection Section** - Displays the reflection text (if provided) 3. **Disabled Actions** - "Add Notes", "Suggest Notes" buttons hidden for non-active projects Current implementation in `ProjectDetail.tsx`: ```typescript // Notes section actions - only shown for active projects {project.status === "active" && (
)} ``` #### Footer Actions by Status | Status | Available Actions | | ----------- | ------------------------- | | `active` | Edit, Archive, Complete | | `completed` | Edit, Archive, Reactivate | | `archived` | Edit, Reactivate | ### 2.4 ProjectStatusBadge Component Create a reusable badge component for consistent status display: ```typescript // src/components/projects-plus/ProjectStatusBadge.tsx interface ProjectStatusBadgeProps { status: ProjectStatus; className?: string; } export function ProjectStatusBadge({ status, className }: ProjectStatusBadgeProps) { return ( {status} ); } ``` The `getStatusBadgeStyles` function from `utils.ts`: ```typescript export function getStatusBadgeStyles(status: ProjectStatus): string { switch (status) { case "active": return "tw-bg-modifier-success-rgb/20 tw-text-success"; case "completed": return "tw-bg-blue-rgb/20 tw-text-context-manager-blue"; case "archived": return "tw-bg-modifier-hover tw-text-muted"; default: return ""; } } ``` --- ## 3. Projects+ Settings Tab ### 3.1 Settings Tab Location Add a new tab to `SettingsMainV2.tsx` OR integrate into an existing tab. **Recommended Approach:** Integrate into the existing settings structure rather than adding a new tab. Projects+ settings should be part of the "Plus" or "Advanced" tab since Projects+ is a premium feature. ### 3.2 Settings Interface Based on the design decisions: ```typescript // Settings that will be added to CopilotSettings interface ProjectsPlusSettings { /** Folder path for Projects+ data */ projectsPlusFolder: string; // Already exists, default: "copilot/projects" // REMOVED SETTINGS: // projectsPlusEnabled: boolean; - REMOVED (feature always enabled) // autoSaveEnabled: boolean; - REMOVED (always enabled) // defaultDiscussModel: string; - REMOVED (uses main model) // showCompletedInList: boolean; - REMOVED (use filter dropdown instead) // noteSuggestionCount: number; - REMOVED (handled by search system) // excludedFolders: string[]; - REMOVED (follows main qaExclusions setting) } ``` ### 3.3 Settings Tab UI Design Since most settings have been consolidated, the Projects+ settings section is minimal: ``` ┌─────────────────────────────────────────────────────────────────┐ │ Projects+ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Projects Folder │ │ Folder where project data is stored. │ │ ┌─────────────────────────────────────────────────────────────┐│ │ │ copilot/projects ││ │ └─────────────────────────────────────────────────────────────┘│ │ │ │ ───────────────────────────────────────────────────────────── │ │ │ │ ℹ️ Note: Projects+ uses the same inclusion/exclusion │ │ settings as QA Mode for note suggestions. │ │ Configure them in the "QA" settings tab. │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ### 3.4 ProjectsPlusSettings Component Implementation ```typescript // src/settings/v2/components/ProjectsPlusSettings.tsx import { SettingItem } from "@/components/ui/setting-item"; import { updateSetting, useSettingsValue } from "@/settings/model"; import React from "react"; export const ProjectsPlusSettings: React.FC = () => { const settings = useSettingsValue(); return (
Projects+
{/* Projects Folder */} updateSetting("projectsPlusFolder", value)} placeholder="copilot/projects" /> {/* Info about shared settings */}

Note: Projects+ uses the same inclusion/exclusion settings as QA Mode for note suggestions. Configure them in the QA settings tab.

); }; ``` ### 3.5 Integrating into Settings **Option A: Add to CopilotPlusSettings.tsx** Since Projects+ is a Plus feature, add it to the existing Plus settings tab: ```typescript // In CopilotPlusSettings.tsx, add: import { ProjectsPlusSettings } from "./ProjectsPlusSettings"; // In the component render: ``` **Option B: Add to AdvancedSettings.tsx** Alternatively, add to Advanced settings as a separate section. ### 3.6 Note Suggestion Configuration **Key Design Decision:** Note suggestions follow the main QA inclusion/exclusion settings. The `NoteAssignmentService` should use `qaExclusions` and `qaInclusions` from the main settings: ```typescript // In NoteAssignmentService.ts import { getSettings } from "@/settings/model"; class NoteAssignmentService { async suggestNotes(projectDescription: string, options?: NoteAssignmentOptions) { const settings = getSettings(); // Apply the same exclusions as QA mode const exclusions = settings.qaExclusions; const inclusions = settings.qaInclusions; // ... use these for filtering note suggestions } } ``` --- ## 4. Implementation Details ### 4.1 Naming Convention Update **Important:** The original design document (`projects-plus-technical-design.md`) uses "Goal" terminology (e.g., `GoalStatusBadge.tsx`, `GoalCompletion.tsx`). However, the actual implementation uses "Project" terminology throughout. This phase should continue using "Project" naming: | Original Design Name | Actual Implementation Name | | --------------------- | ----------------------------------------------------- | | `GoalStatusBadge.tsx` | `ProjectStatusBadge.tsx` | | `GoalCompletion.tsx` | `ProjectStatusDialog.tsx` (already exists) | | `ArchivedGoals.tsx` | Not needed (handled by filter in `ProjectsPanel.tsx`) | ### 4.2 Files to Create | File | Purpose | | ----------------------------------------------------- | ------------------------------- | | `src/settings/v2/components/ProjectsPlusSettings.tsx` | Settings tab component | | `src/components/projects-plus/ProjectStatusBadge.tsx` | Reusable status badge component | ### 4.3 Files to Modify | File | Changes | | ---------------------------------------------------- | ------------------------------------------------------------- | | `src/settings/model.ts` | Remove `projectsPlusEnabled` from `CopilotSettings` interface | | `src/constants.ts` | Remove `projectsPlusEnabled` from `DEFAULT_SETTINGS` | | `src/main.ts` | Remove any conditional checks for `projectsPlusEnabled` | | `src/settings/v2/components/CopilotPlusSettings.tsx` | Import and render `ProjectsPlusSettings` | | `src/core/projects-plus/NoteAssignmentService.ts` | Use `qaExclusions`/`qaInclusions` for filtering | | `src/components/projects-plus/ProjectDetail.tsx` | Replace inline badge with `ProjectStatusBadge` component | | `src/components/projects-plus/ProjectCard.tsx` | Replace inline badge with `ProjectStatusBadge` component | ### 4.4 Conversation Auto-Save Behavior Conversations are auto-saved per message exchange. This is NOT configurable - it's always enabled. The save happens in `ConversationPersistence.ts`: ```typescript // After each message exchange: await conversationPersistence.saveConversation(project, conversation); ``` ### 4.5 Model Configuration for Discuss The Discuss feature uses the default chat model (`defaultModelKey`) rather than a separate model setting. This simplifies configuration and ensures consistency. --- ## 5. Edge Cases & Error Handling ### 5.1 Completion Edge Cases | Scenario | Handling | | ---------------------------------- | ------------------------------------------------------------ | | **Empty reflection** | Allow completion - reflection is optional | | **Very long reflection** | No limit, but consider adding a soft warning for >1000 chars | | **Completion fails** | Show error notice, keep dialog open | | **Project already completed** | Button should not be visible; if API called, return silently | | **Concurrent completion attempts** | Use loading state to prevent double-submission | ### 5.2 Settings Edge Cases | Scenario | Handling | | -------------------------------------- | -------------------------------------------------------- | | **Invalid folder path** | Validate path, show error if contains illegal characters | | **Folder doesn't exist** | Create folder on first project creation, not on save | | **Empty folder path** | Fall back to default `copilot/projects` | | **Path with leading/trailing slashes** | Normalize path on save | ### 5.3 Filter Edge Cases | Scenario | Handling | | --------------------------------------------- | ----------------------------------------------------------- | | **Filter shows no results** | Show empty state with helpful message | | **Search + filter combination** | Apply both filters, show combined empty state if no results | | **Project status changes while viewing list** | Reactive update via subscription | ### 5.4 Archived Goal View Edge Cases | Scenario | Handling | | -------------------------------------------- | -------------------------------------------------- | | **Viewing archived goal with deleted notes** | Show warning icon next to missing notes | | **Attempting to discuss archived goal** | "Discuss" button hidden for archived status | | **Reactivating a goal** | Status changes to "active", all actions re-enabled | --- ## 6. Testing Checklist ### 6.1 Goal Completion Flow - [ ] Click "Complete" from ProjectDetail footer opens dialog - [ ] Journey summary shows correct days, notes, conversations counts - [ ] Empty reflection is accepted - [ ] Reflection with text is saved to project - [ ] Cancel closes dialog without changes - [ ] Completing updates project status to "completed" - [ ] Completed project shows in list when filter is "All" or "Completed" - [ ] Completed project does NOT appear when filter is "Active" - [ ] `goal.md` file contains `status: "completed"` and `completedAt` timestamp - [ ] `goal.md` file contains reflection text ### 6.2 Archived Goals View - [ ] Archived projects appear in list when filter is "All" or "Archived" - [ ] Archived project detail shows "Archived" badge - [ ] "Add Notes" and "Suggest" buttons hidden for archived projects - [ ] Footer shows only "Edit" and "Reactivate" for archived projects - [ ] Reactivating changes status back to "active" - [ ] All actions re-enabled after reactivation ### 6.3 Settings Tab - [ ] Projects+ settings appear in Plus/Advanced tab - [ ] Folder path input accepts valid paths - [ ] Info message about shared QA settings is visible - [ ] Settings persist after Obsidian reload - [ ] Changing folder path affects new project creation ### 6.4 Note Suggestions with Exclusions - [ ] Notes in excluded folders (from QA settings) don't appear in suggestions - [ ] Notes matching inclusion patterns appear in suggestions - [ ] Exclusions take precedence over inclusions - [ ] Suggestions work correctly with empty exclusions/inclusions ### 6.5 Persistence - [ ] Create project, complete it, reload Obsidian - project still completed - [ ] Reflection text persists after reload - [ ] Settings persist after reload - [ ] Projects folder setting affects file storage location --- ## Appendix A: ProjectStatusBadge Styles Reference ```typescript // Current implementation in utils.ts (used by ProjectStatusBadge) export function getStatusBadgeStyles(status: ProjectStatus): string { switch (status) { case "active": return "tw-bg-modifier-success-rgb/20 tw-text-success"; case "completed": return "tw-bg-blue-rgb/20 tw-text-context-manager-blue"; case "archived": return "tw-bg-modifier-hover tw-text-muted"; default: return ""; } } ``` ## Appendix B: Default Settings Values ```typescript // From constants.ts export const DEFAULT_PROJECTS_FOLDER = "copilot/projects"; // From DEFAULT_SETTINGS projectsPlusFolder: DEFAULT_PROJECTS_FOLDER, // Note: projectsPlusEnabled has been removed - feature is always enabled ``` ## Appendix C: Removed Settings Rationale | Removed Setting | Reason | | --------------------- | ----------------------------------------------------- | | `projectsPlusEnabled` | Feature is always enabled, no toggle needed | | `showCompletedInList` | Filter dropdown provides this functionality directly | | `noteSuggestionCount` | Handled by search system, no user-facing limit needed | | `excludedFolders` | Consolidated with main `qaExclusions` setting | | `autoSaveEnabled` | Always enabled per design decision | | `defaultDiscussModel` | Uses main `defaultModelKey` for consistency | This consolidation reduces settings complexity and ensures consistent behavior across the plugin.