# Round: Mentoring (Finalist Collaboration Layer)

## 1. Purpose & Position in Flow

The MENTORING round is **not a judging stage** — it is a collaboration layer that activates between Jury 2 finalist selection and the Live Finals. It provides finalist teams who requested mentoring with a private workspace to refine their submissions with guidance from an assigned mentor.

| Aspect | Detail |
|--------|--------|
| Position | Round 6 (after Jury 2, before Live Finals) |
| Participants | Finalist teams + assigned mentors |
| Duration | Configurable (typically 2-4 weeks) |
| Output | Better-prepared finalist submissions; some mentoring files promoted to official submissions |

### Who Gets Mentoring

- Only projects that have `Project.wantsMentorship = true` AND have advanced to finalist status (ProjectRoundState PASSED in the Jury 2 round)
- Admin can override: assign mentoring to projects that didn't request it, or skip projects that did

---

## 2. Data Model

### Round Record

```
Round {
  id: "round-mentoring"
  competitionId: "comp-2026"
  name: "Finalist Mentoring"
  roundType: MENTORING
  status: ROUND_DRAFT → ROUND_ACTIVE → ROUND_CLOSED
  sortOrder: 5
  windowOpenAt: "2026-06-01"       // Mentoring period start
  windowCloseAt: "2026-06-30"      // Mentoring period end
  juryGroupId: null                 // No jury for mentoring
  submissionWindowId: null          // Mentoring doesn't collect formal submissions
  configJson: { ...MentoringConfig }
}
```

### MentoringConfig

```typescript
type MentoringConfig = {
  // Who gets mentoring
  eligibility: "all_advancing" | "requested_only"
  //   all_advancing: Every finalist gets a mentor
  //   requested_only: Only projects with wantsMentorship=true

  // Workspace features
  chatEnabled: boolean              // Bidirectional messaging (default: true)
  fileUploadEnabled: boolean        // Mentor + team can upload files (default: true)
  fileCommentsEnabled: boolean      // Threaded comments on files (default: true)
  filePromotionEnabled: boolean     // Promote workspace file to official submission (default: true)

  // Promotion target
  promotionTargetWindowId: string | null
  //   Which SubmissionWindow promoted files go to
  //   Usually the most recent window (Round 2 docs)
  //   If null, promotion creates files without a window (admin must assign)

  // Auto-assignment
  autoAssignMentors: boolean        // Use AI/algorithm to assign (default: false)
  maxProjectsPerMentor: number      // Mentor workload cap (default: 3)

  // Notifications
  notifyTeamsOnOpen: boolean        // Email teams when mentoring opens (default: true)
  notifyMentorsOnAssign: boolean    // Email mentors when assigned (default: true)
  reminderBeforeClose: number[]     // Days before close to remind (default: [7, 3, 1])
}
```

### Related Models

| Model | Purpose |
|-------|---------|
| `MentorAssignment` | Links mentor to project (existing, enhanced) |
| `MentorMessage` | Chat messages between mentor and team (existing) |
| `MentorNote` | Mentor's private notes (existing) |
| `MentorFile` | **NEW** — Files uploaded in workspace |
| `MentorFileComment` | **NEW** — Threaded comments on files |
| `ProjectFile` | Target for file promotion |
| `SubmissionFileRequirement` | Requirement slot that promoted file fills |

---

## 3. Mentor Assignment

### 3.1 Assignment Methods

| Method | Description |
|--------|-------------|
| `MANUAL` | Admin picks mentor for each project |
| `AI_SUGGESTED` | AI recommends matches, admin approves |
| `AI_AUTO` | AI auto-assigns, admin can override |
| `ALGORITHM` | Round-robin or expertise-matching algorithm |

### 3.2 Assignment Criteria

The existing `mentor-matching.ts` service evaluates:
- **Expertise overlap** — mentor's tags vs project's tags/category
- **Country/region diversity** — avoid same-country bias
- **Workload balance** — distribute evenly across mentors
- **Language** — match if language preferences exist

### 3.3 Assignment Flow

```
1. MENTORING round opens (status → ROUND_ACTIVE)
2. System identifies eligible projects:
   - All finalists (if eligibility = "all_advancing")
   - Only finalists with wantsMentorship (if "requested_only")
3. For each eligible project without a mentor:
   a. If autoAssignMentors: Run AI/algorithm assignment
   b. Else: Flag as "needs mentor" in admin dashboard
4. Admin reviews assignments, can:
   - Accept suggestions
   - Reassign mentors
   - Skip projects (no mentoring needed)
5. Assigned mentors receive email notification
6. Workspace becomes active for mentor+team
```

### 3.4 Workspace Activation

When a mentor is assigned and the MENTORING round is ROUND_ACTIVE:

```typescript
// MentorAssignment is updated:
{
  workspaceEnabled: true,
  workspaceOpenAt: round.windowOpenAt,
  workspaceCloseAt: round.windowCloseAt,
}
```

The workspace is accessible from:
- **Mentor dashboard** → "My Projects" → select project → Workspace tab
- **Applicant dashboard** → "Mentor" section → Workspace tab
- **Admin** → can view any workspace at any time

---

## 4. Workspace Features

### 4.1 Messaging (Chat)

Bidirectional chat between mentor and team members:

```
┌────────────────────────────────────────────────┐
│ Mentor Workspace — OceanClean AI               │
│ ──────────────────────────────────────────── │
│ [💬 Chat] [📁 Files] [📋 Milestones]          │
│                                                │
│ ┌────────────────────────────────────────┐     │
│ │ Dr. Martin (Mentor)       Apr 5, 10:30│     │
│ │ Welcome! I've reviewed your business   │     │
│ │ plan. Let's work on the financial      │     │
│ │ projections section.                   │     │
│ │                                        │     │
│ │ Sarah (Team Lead)         Apr 5, 14:15│     │
│ │ Thank you! We've uploaded a revised    │     │
│ │ version. See the Files tab.            │     │
│ │                                        │     │
│ │ Dr. Martin (Mentor)       Apr 6, 09:00│     │
│ │ Great improvement! I've left comments  │     │
│ │ on the file. One more round should do. │     │
│ └────────────────────────────────────────┘     │
│                                                │
│ [Type a message...              ] [Send]       │
└────────────────────────────────────────────────┘
```

**Implementation:**
- Uses existing `MentorMessage` model
- Messages auto-marked as read when the chat is viewed
- Real-time updates via polling (every 10s) or WebSocket if available
- Both mentor and any team member can send messages

### 4.2 File Upload & Comments

The core new feature: a private file space with threaded discussion.

```
┌────────────────────────────────────────────────┐
│ [💬 Chat] [📁 Files] [📋 Milestones]          │
│                                                │
│ ┌── Workspace Files ───────────────────────┐   │
│ │                                          │   │
│ │ 📄 Business Plan v2.pdf                  │   │
│ │    Uploaded by Sarah (Team) · Apr 5      │   │
│ │    💬 3 comments                         │   │
│ │    [Download] [Comment] [Promote →]      │   │
│ │                                          │   │
│ │ 📄 Financial Model.xlsx                  │   │
│ │    Uploaded by Dr. Martin (Mentor) · Apr 6│  │
│ │    💬 1 comment                          │   │
│ │    [Download] [Comment]                  │   │
│ │                                          │   │
│ │ 📄 Pitch Deck Draft.pptx                │   │
│ │    Uploaded by Sarah (Team) · Apr 8      │   │
│ │    ✅ Promoted → "Presentation" slot     │   │
│ │    [Download] [View Comments]            │   │
│ │                                          │   │
│ └──────────────────────────────────────────┘   │
│                                                │
│ [📤 Upload File]                               │
└────────────────────────────────────────────────┘
```

**File Upload Flow:**
1. User (mentor or team member) clicks "Upload File"
2. Client calls `mentor.getWorkspaceUploadUrl(mentorAssignmentId, fileName, mimeType)`
3. Server generates MinIO pre-signed PUT URL
4. Client uploads directly to MinIO
5. Client calls `mentor.saveWorkspaceFile(mentorAssignmentId, fileName, mimeType, size, bucket, objectKey, description)`
6. Server creates `MentorFile` record

**File Comments:**

```
┌── Comments on: Business Plan v2.pdf ──────────┐
│                                                │
│ Dr. Martin (Mentor) · Apr 5, 16:00            │
│ Section 3.2 needs stronger market analysis.    │
│ Consider adding competitor comparisons.        │
│   └─ Sarah (Team) · Apr 5, 18:30             │
│      Good point — we'll add a competitive      │
│      landscape section. See updated version.   │
│                                                │
│ Dr. Martin (Mentor) · Apr 6, 10:00            │
│ Revenue projections look much better now.      │
│ Ready for promotion to official submission?    │
│   └─ Sarah (Team) · Apr 6, 11:00             │
│      Yes, let's promote it!                    │
│                                                │
│ [Add comment...                    ] [Post]    │
└────────────────────────────────────────────────┘
```

**Implementation:**
- `MentorFileComment` with `parentCommentId` for threading
- Both mentor and team members can comment
- Admin can view all comments
- Comments are timestamped and attributed

### 4.3 File Promotion to Official Submission

The key feature: converting a private mentoring file into an official submission document.

**Promotion Flow:**

```
1. Team member (or admin) clicks "Promote →" on a workspace file
2. Dialog appears:
   ┌────────────────────────────────────────┐
   │ Promote File to Official Submission    │
   │                                        │
   │ File: Business Plan v2.pdf             │
   │                                        │
   │ Target submission window:              │
   │ [Round 2 Docs ▾]                       │
   │                                        │
   │ Replaces requirement:                  │
   │ [Business Plan ▾]                      │
   │                                        │
   │ ⚠ This will replace the current       │
   │ "Business Plan" file for this project. │
   │                                        │
   │ [Cancel]  [Promote & Replace]          │
   └────────────────────────────────────────┘

3. On confirmation:
   a. System creates a new ProjectFile record:
      - projectId: project's ID
      - submissionWindowId: selected window
      - requirementId: selected requirement slot
      - fileName, mimeType, size: copied from MentorFile
      - bucket, objectKey: SAME as MentorFile (no file duplication)
      - version: incremented from previous file in slot
   b. Previous file in that slot gets `replacedById` set to new file
   c. MentorFile updated:
      - isPromoted: true
      - promotedToFileId: new ProjectFile ID
      - promotedAt: now
      - promotedByUserId: actor ID
   d. Audit log entry created:
      - action: "MENTOR_FILE_PROMOTED"
      - details: { mentorFileId, projectFileId, submissionWindowId, requirementId, replacedFileId }
```

**Key Rules:**
- Only files in **active** mentoring workspaces can be promoted
- Promotion **replaces** the existing file for that requirement slot (per user's decision)
- The MinIO object is **not duplicated** — both MentorFile and ProjectFile point to the same objectKey
- Once promoted, the MentorFile shows a "Promoted" badge and the promote button is disabled
- Admin can un-promote (revert) if needed, which deletes the ProjectFile and resets MentorFile flags
- Promotion is audited with full provenance chain

**Who Can Promote:**
- Team lead (Project.submittedByUserId or TeamMember.role = LEAD)
- Admin (always)
- Mentor (only if `MentoringConfig.mentorCanPromote` is true — default false for safety)

### 4.4 Privacy Model

```
Visibility Matrix:
┌──────────────────┬────────┬──────────┬───────┬──────┐
│ Content          │ Mentor │ Team     │ Admin │ Jury │
├──────────────────┼────────┼──────────┼───────┼──────┤
│ Chat messages    │ ✅     │ ✅       │ ✅    │ ❌   │
│ Workspace files  │ ✅     │ ✅       │ ✅    │ ❌   │
│ File comments    │ ✅     │ ✅       │ ✅    │ ❌   │
│ Mentor notes     │ ✅     │ ❌       │ ✅*   │ ❌   │
│ Promoted files   │ ✅     │ ✅       │ ✅    │ ✅** │
└──────────────────┴────────┴──────────┴───────┴──────┘

* Only if MentorNote.isVisibleToAdmin = true
** Promoted files become official submissions visible to jury
```

---

## 5. Mentor Dashboard

```
┌──────────────────────────────────────────────────────────┐
│ Mentor Dashboard                                         │
│ ─────────────────────────────────────────────────────── │
│                                                          │
│ Mentoring Period: June 1 – June 30                       │
│ ⏱ 18 days remaining                                     │
│                                                          │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐                   │
│ │ 3       │ │ 12      │ │ 5        │                    │
│ │ Teams   │ │ Messages│ │ Files    │                    │
│ └─────────┘ └─────────┘ └──────────┘                    │
│                                                          │
│ My Assigned Teams                                        │
│ ┌────────────────────────────────────────────────────┐  │
│ │ OceanClean AI (Startup)                            │  │
│ │ 💬 2 unread messages · 📁 3 files · Last: Apr 6    │  │
│ │ [Open Workspace]                                   │  │
│ ├────────────────────────────────────────────────────┤  │
│ │ Blue Carbon Hub (Concept)                          │  │
│ │ 💬 0 unread · 📁 1 file · Last: Apr 4              │  │
│ │ [Open Workspace]                                   │  │
│ ├────────────────────────────────────────────────────┤  │
│ │ SeaWatch Monitor (Startup)                         │  │
│ │ ⚠ No activity yet                                  │  │
│ │ [Open Workspace]                                   │  │
│ └────────────────────────────────────────────────────┘  │
│                                                          │
│ Milestones                                               │
│ ┌────────────────────────────────────────────────────┐  │
│ │ ☑ Initial review (3/3 teams)                       │  │
│ │ ☐ Business plan feedback (1/3 teams)               │  │
│ │ ☐ Pitch deck review (0/3 teams)                    │  │
│ └────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────┘
```

---

## 6. Applicant Experience

On the applicant dashboard, a "Mentoring" section appears when mentoring is active:

```
┌────────────────────────────────────────────────┐
│ Your Mentor: Dr. Martin Duval                  │
│ Expertise: Marine Biology, Sustainability       │
│                                                │
│ Mentoring Period: June 1 – June 30             │
│ ⏱ 18 days remaining                           │
│                                                │
│ [💬 Messages (2 unread)]                       │
│ [📁 Workspace Files (3)]                       │
│ [📋 Milestones]                                │
└────────────────────────────────────────────────┘
```

Clicking "Workspace Files" opens the same workspace view as the mentor (with appropriate permissions).

---

## 7. Admin Experience

Admin can:
- **Assign/reassign mentors** via bulk or individual assignment
- **View any workspace** (read-only or with full edit access)
- **Promote files** on behalf of teams
- **Track activity** — dashboard showing mentor engagement:
  - Messages sent per mentor
  - Files uploaded
  - Milestones completed
  - Last activity timestamp
- **Extend/close mentoring window** per team or globally
- **Export workspace data** for audit purposes

---

## 8. API — New and Modified Procedures

### New Procedures (mentor-workspace router)

| Procedure | Auth | Purpose |
|-----------|------|---------|
| `mentorWorkspace.getUploadUrl` | Mentor or Team | Get MinIO pre-signed URL for workspace upload |
| `mentorWorkspace.saveFile` | Mentor or Team | Create MentorFile record after upload |
| `mentorWorkspace.listFiles` | Mentor, Team, Admin | List workspace files with comment counts |
| `mentorWorkspace.deleteFile` | Uploader or Admin | Delete workspace file |
| `mentorWorkspace.getFileDownloadUrl` | Mentor, Team, Admin | Get MinIO pre-signed URL for download |
| `mentorWorkspace.addComment` | Mentor, Team, Admin | Add comment to file (with optional parentCommentId) |
| `mentorWorkspace.listComments` | Mentor, Team, Admin | Get threaded comments for a file |
| `mentorWorkspace.deleteComment` | Author or Admin | Delete a comment |
| `mentorWorkspace.promoteFile` | Team Lead or Admin | Promote workspace file to official submission |
| `mentorWorkspace.unpromoteFile` | Admin only | Revert a promotion |
| `mentorWorkspace.getWorkspaceStatus` | Any participant | Get workspace summary (file count, message count, etc.) |

### Modified Existing Procedures

| Procedure | Change |
|-----------|--------|
| `mentor.getMyProjects` | Include workspace status (file count, unread messages) |
| `mentor.getProjectDetail` | Include MentorFile[] with comment counts |
| `applicant.getMyDashboard` | Include mentor workspace summary if mentoring active |
| `file.listByProjectForRound` | Promoted files visible to jury (via ProjectFile record) |

---

## 9. Service: `mentor-workspace.ts`

### Key Functions

```typescript
// Upload handling
async function getWorkspaceUploadUrl(
  mentorAssignmentId: string,
  fileName: string,
  mimeType: string,
  actorId: string,
  prisma: PrismaClient
): Promise<{ uploadUrl: string; objectKey: string }>

// Save file metadata after upload
async function saveWorkspaceFile(
  mentorAssignmentId: string,
  uploadedByUserId: string,
  file: { fileName, mimeType, size, bucket, objectKey },
  description: string | null,
  prisma: PrismaClient
): Promise<MentorFile>

// Promote file to official submission
async function promoteFileToSubmission(
  mentorFileId: string,
  submissionWindowId: string,
  requirementId: string | null,
  actorId: string,
  prisma: PrismaClient
): Promise<{ mentorFile: MentorFile; projectFile: ProjectFile }>
// Steps:
//   1. Validate mentorFile exists, is not already promoted, workspace is active
//   2. If requirementId: find existing ProjectFile for that requirement, set replacedById
//   3. Create new ProjectFile (reusing same bucket/objectKey — no MinIO duplication)
//   4. Update MentorFile: isPromoted=true, promotedToFileId, promotedAt, promotedByUserId
//   5. Audit log with full provenance

// Revert promotion
async function unpromoteFile(
  mentorFileId: string,
  actorId: string,
  prisma: PrismaClient
): Promise<void>
// Steps:
//   1. Find the ProjectFile created by promotion
//   2. If it replaced a previous file, restore that file's replacedById=null
//   3. Delete the promoted ProjectFile
//   4. Reset MentorFile flags
//   5. Audit log
```

---

## 10. Edge Cases

| Scenario | Handling |
|----------|----------|
| Team doesn't want mentoring but admin assigns anyway | Assignment created; team sees mentor in dashboard |
| Mentor goes inactive during period | Admin can reassign; previous workspace preserved |
| File promoted then mentor period closes | Promoted file remains as official submission |
| Team tries to promote file for a requirement that doesn't exist | Error — must select valid requirement or leave requirementId null |
| Two files promoted to the same requirement slot | Second promotion replaces first (versioning) |
| Mentoring file is larger than requirement maxSizeMB | Warning shown but promotion allowed (admin override implicit) |
| Workspace closed but team needs one more upload | Admin can extend via round window or grant grace |
| Promoted file deleted from workspace | ProjectFile remains (separate record); audit shows provenance |
