diff --git a/CLAUDE.md b/CLAUDE.md index 52e3c7ca..70086afe 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,7 +24,7 @@ The project was rebranded from "Patherly" to "ResolutionFlow" in the frontend (P | Repository / directory name | `patherly` | | Backend (FastAPI, env vars, APP_NAME) | ResolutionFlow | | Database / Docker container | `patherly` / `patherly_postgres` | -| Production URLs | `app.patherly.com` / `api.patherly.com` | +| Production URLs | `resolutionflow.com` / `api.resolutionflow.com` | | **Frontend UI (header, login, register)** | **ResolutionFlow** | | **Browser tab title** | **ResolutionFlow - Decision Tree Platform** | @@ -216,6 +216,7 @@ patherly/ ├── LESSONS-LEARNED.md # Bugs and fixes (READ THIS!) ├── PROGRESS.md # Detailed progress log ├── REBRAND-IMPLEMENTATION-GUIDE.md # Patherly → ResolutionFlow rebrand guide +├── docs/plans/ # Implementation plans ├── 01-PROJECT-OVERVIEW.md # Vision and goals ├── 02-TECHNICAL-ARCHITECTURE.md # System design, API specs ├── 03-DEVELOPMENT-ROADMAP.md # Phases and timeline @@ -468,12 +469,12 @@ if settings.ALLOW_RAILWAY_ORIGINS: if settings.ALLOW_RAILWAY_ORIGINS: app.add_middleware( CORSMiddleware, - allow_origins=settings.allowed_origins, # Custom domains like app.patherly.com + allow_origins=settings.allowed_origins, # Custom domains like resolutionflow.com allow_origin_regex=r"https://.*\.up\.railway\.app", # Railway PR domains # ... ) ``` -When using `allow_origin_regex` for wildcard patterns, also include `allow_origins` for explicit custom domains. The regex alone won't match custom domains like `app.patherly.com`. +When using `allow_origin_regex` for wildcard patterns, also include `allow_origins` for explicit custom domains. The regex alone won't match custom domains like `resolutionflow.com`. ### findNode Requires Tree Structure Parameter @@ -738,6 +739,7 @@ const response = await api.get('/api/v1/trees') # Secrets and local config backend/.env .claude.local.md +.claude/settings.local.json # Dependencies backend/venv/ @@ -778,8 +780,8 @@ backend/**/__pycache__/ ### Production -- **Frontend:** https://app.patherly.com -- **Backend:** https://api.patherly.com +- **Frontend:** +- **Backend:** - **Database:** Railway-managed PostgreSQL - Deploys automatically on push to `main` diff --git a/docs/plans/2026-02-04-feature-ideas-brainstorm.md b/docs/plans/2026-02-04-feature-ideas-brainstorm.md index da541661..3c5c231e 100644 --- a/docs/plans/2026-02-04-feature-ideas-brainstorm.md +++ b/docs/plans/2026-02-04-feature-ideas-brainstorm.md @@ -12,6 +12,7 @@ Every feature should follow the core principle that makes ResolutionFlow work: **Engineers don't document — they troubleshoot, and the tool captures documentation as a byproduct.** New features should: + - Reduce engineer cognitive load - Automate capture of what they're already doing - Make reusing knowledge frictionless @@ -42,23 +43,28 @@ New features should: **Effort:** Small (backend export change, no new UI) ### What + Every session automatically tracks duration (start → end) and includes it in the export. ### Export Output + ``` Session Duration: 23 minutes Started: 2:30 PM | Completed: 2:53 PM ``` ### Why + MSP engineers bill by the hour. They troubleshoot in ResolutionFlow, export notes, then separately log time in their PSA. This eliminates the second step. ### Implementation Notes + - Timestamps already exist in session decisions — just compute elapsed time - Add duration to export templates (markdown, text, HTML) - No new UI required — purely a backend export enhancement ### Future Enhancement + - When PSA integration exists: if no PSA connected, ResolutionFlow tracks time natively. If PSA connected, still track time but also push it directly to the ticket in the PSA. - Analytics: average resolution time per tree, per client, per engineer @@ -70,6 +76,7 @@ MSP engineers bill by the hour. They troubleshoot in ResolutionFlow, export note **Effort:** Medium ### What + Two mechanisms for sharing in-progress troubleshooting context: 1. **"Share Progress" button** (available mid-session) — generates a formatted summary of steps completed so far. Copy to clipboard, paste into Teams/Slack. One click instead of typing "here's what I've tried." @@ -77,6 +84,7 @@ Two mechanisms for sharing in-progress troubleshooting context: 2. **Read-only session link** — shareable URL where anyone with the link can see the session state. If they sign in and get assigned, they can resume from where the previous engineer left off. ### Workflow + 1. Junior engineer gets stuck → clicks "Share Progress" 2. Pastes formatted summary into Teams chat with senior 3. Senior reads structured summary (not a wall of chat text) @@ -84,11 +92,13 @@ Two mechanisms for sharing in-progress troubleshooting context: 5. If escalating: ticket reassigned in PSA, senior resumes the session in ResolutionFlow ### Implementation Notes + - Copy/paste version is nearly free — existing export logic on incomplete sessions + "Steps remaining" section - Read-only link: generate share token, create public read-only session view (no auth) - Resume capability: allow session reassignment to another user ### Why This Matters + Eliminates the "what have you tried so far?" back-and-forth that happens on every escalation. The structured format means the senior gets context in 30 seconds instead of 10 minutes of chat. --- @@ -99,9 +109,11 @@ Eliminates the "what have you tried so far?" back-and-forth that happens on ever **Effort:** Small ### What + Action nodes (which show commands to run) get an optional "Paste Output" text area. Engineer runs the command, copies output, pastes it in. ### Export Output + ``` > Ran: Get-Service -Name Spooler > Output: @@ -111,15 +123,18 @@ Action nodes (which show commands to run) get an optional "Paste Output" text ar ``` ### Why + Engineers already run commands and read output. Today the output is lost — the export says "ran this command" but not what it returned. This captures the evidence. ### Implementation Notes + - Add optional `command_output` field to session decision JSONB - Add collapsible text area below commands on action nodes in TreeNavigationPage - Include in export with code formatting - Pairs well with Scratchpad (Idea 6) and Share Progress (Idea 2) ### Future Enhancement + - Syntax highlighting for common output formats (PowerShell, JSON) - Image paste for screenshots of GUI-based evidence @@ -131,9 +146,11 @@ Engineers already run commands and read output. Today the output is lost — the **Effort:** Medium-Large ### What + A senior engineer (or anyone) can send a troubleshooting step directly to someone's active session. Flips the step library from a pull model (browse and find) to a push model (someone sends it to you). ### Workflow + 1. Junior shares progress link (Idea 2) 2. Senior sees they're stuck at "VDA not registering" 3. Senior picks a step from their personal library (or types one quickly) @@ -143,15 +160,18 @@ A senior engineer (or anyone) can send a troubleshooting step directly to someon 7. Step documented in export, optionally saved to junior's library ### Why + Replaces unstructured Teams/Slack troubleshooting advice with structured, documented, reusable steps. The knowledge stays in the system. ### Implementation Notes + - Requires lightweight notification/inbox system (polling or WebSocket) - Builds on: Share Progress (Idea 2) + Step Library (existing) - New API: `POST /api/v1/sessions/{id}/send-step` - Frontend: notification badge + step insertion flow ### Analytics Potential + - Which seniors send the most steps (mentorship tracking) - Which pushed steps get reused (knowledge value) - Which juniors receive fewer pushes over time (skill growth) @@ -164,6 +184,7 @@ Replaces unstructured Teams/Slack troubleshooting advice with structured, docume **Effort:** Medium ### What + Aggregate completed session data to show statistical hints on decision nodes: - Badge: "78% of engineers chose Option B here" @@ -171,9 +192,11 @@ Aggregate completed session data to show statistical hints on decision nodes: - At common stuck points: "Engineers often add a custom step here" ### Why + Delivers on the tagline. For a junior engineer staring at three options, seeing "most engineers went this way" is a confidence boost. For tree authors, analytics reveal dead-end branches. ### Implementation Notes + - Aggregate query on session `path_taken` and `decisions` JSONB - Compute per-node: choice distribution, resolve rate, custom step frequency - Cache aggregates (recompute daily or on-demand) @@ -181,6 +204,7 @@ Delivers on the tagline. For a junior engineer staring at three options, seeing - Resolve rate: track whether session completed at a solution node + optional "did this fix it?" prompt ### Data Requirements + - Needs sufficient session volume per tree to be statistically meaningful (suggest: show after 10+ sessions) - Weight recent sessions higher than old ones @@ -193,12 +217,15 @@ Delivers on the tagline. For a junior engineer staring at three options, seeing **Priority:** Must-have (per Michael) ### What + A persistent sidebar during active sessions for capturing ambient data: IP addresses, error codes, server names, usernames — anything that doesn't fit a specific decision node's notes field. ### Why + During troubleshooting, engineers accumulate bits of data (from `ipconfig`, Event Viewer, phone conversations) that live on sticky notes or in their head. This gives it a home and includes it in the export. ### Export Output + ``` ## Evidence / Reference - Server IP: 192.168.1.50 @@ -208,6 +235,7 @@ During troubleshooting, engineers accumulate bits of data (from `ipconfig`, Even ``` ### Implementation Notes + - Persistent sidebar (collapsible) in TreeNavigationPage - Store in session JSONB as `scratchpad` array of entries - Each entry: text + optional label + timestamp @@ -216,6 +244,7 @@ During troubleshooting, engineers accumulate bits of data (from `ipconfig`, Even - Future: structured key-value pairs, tags, image paste ### Pairs With + - Command Output Capture (Idea 3): structured output at nodes + freeform notes in scratchpad = complete evidence - Share Progress (Idea 2): scratchpad content included in shared summary @@ -227,9 +256,11 @@ During troubleshooting, engineers accumulate bits of data (from `ipconfig`, Even **Effort:** Large ### What + When troubleshooting reveals the problem is in a different domain, branch into another tree mid-session without losing context. The export captures the entire journey. ### Workflow + 1. Engineer is in "VPN Issues" tree, 5 steps deep 2. Discovers the actual problem is DNS, not VPN 3. Clicks "Open Related Tree" → selects "DNS Resolution Issues" @@ -238,6 +269,7 @@ When troubleshooting reveals the problem is in a different domain, branch into a 6. Export shows unified narrative with both trees ### Export Output + ``` ## VPN Connection Issues 1. Verified VPN client version: OK @@ -255,6 +287,7 @@ When troubleshooting reveals the problem is in a different domain, branch into a ``` ### Implementation Notes + - Session model needs: `parent_session_id`, `branched_at_node_id` - "Open Related Tree" action on any node (tree selector modal) - Breadcrumb shows tree chain: VPN > DNS @@ -262,6 +295,7 @@ When troubleshooting reveals the problem is in a different domain, branch into a - Back button returns to parent session at bookmark point ### Why + Real troubleshooting rarely stays in one domain. This captures the full diagnostic story. --- @@ -272,22 +306,27 @@ Real troubleshooting rarely stays in one domain. This captures the full diagnost **Effort:** Small-Medium ### What + When an engineer starts a session and enters a client name, show previous sessions for that client in that tree. If the same resolution keeps being reached, prompt for root cause action. ### UI + - At session start: "3 previous sessions for Warner Robins in this tree (last: Jan 28)" + link to view - At resolution (if recurring): "This is the 3rd time this issue was resolved the same way for this client. Consider documenting a permanent fix or escalating to address root cause." ### Why + Turns ResolutionFlow from reactive (fix the ticket) to proactive (fix the root cause). For MSP managers, recurring issues per client = business intelligence for infrastructure upgrade proposals. ### Implementation Notes + - Query: sessions grouped by client_name + tree_id, count + last date - Display at session start (inline, not blocking) - Recurrence prompt: compare resolution node_id across sessions - Future (with PSA/RMM): correlate with alert data for richer signals ### Data Model + - No schema changes needed — query existing sessions table - Optional: normalize client names (fuzzy match or client_id foreign key) @@ -299,9 +338,11 @@ Turns ResolutionFlow from reactive (fix the ticket) to proactive (fix the root c **Effort:** Medium ### What + Data-driven health indicators for trees, surfaced to tree authors and admins. ### Signals + - **Custom step frequency**: Engineers keep adding steps at the same node → tree is missing a branch - **Abandonment rate**: Sessions started but not completed → tree isn't leading to resolutions - **Low resolve rate**: Solution nodes that don't actually fix issues @@ -309,14 +350,17 @@ Data-driven health indicators for trees, surfaced to tree authors and admins. - **Escalation rate**: High percentage of sessions shared/escalated from this tree ### Display + - Green/yellow/red health badge on tree library cards - Author notification: "Your 'VPN Issues' tree has yellow health — 4 engineers added custom steps at 'Check Split Tunnel Config' this month" - Admin dashboard: team-wide tree health overview ### Why + Creates a self-improving ecosystem. Sessions generate data → data identifies weak trees → authors improve trees → next engineer gets a better experience. ### Implementation Notes + - Scheduled aggregation job (daily) - Health score algorithm: weighted combination of signals - Store as computed field on tree (or separate analytics table) @@ -331,21 +375,25 @@ Creates a self-improving ecosystem. Sessions generate data → data identifies w **Status:** Ultimate goal ### What + Three layers of AI, each building on the last, leveraging ResolutionFlow's unique structured troubleshooting dataset. ### Layer 1: Smart Tree Suggestions + - Engineer pastes ticket description: "User at Warner Robins reports Outlook keeps crashing after latest update" - AI suggests: "Recommended: Outlook/Email Issues tree → Start at 'Recent Update' branch" - Not just which tree — which branch to start at, skipping generic initial questions - **Implementation:** NLP parsing of ticket text, match against tree node content and tags ### Layer 2: Session-Driven Tree Evolution + - Aggregate session data reveals patterns: "35% of engineers add 'Check MFA Token' after 'Auth Failed' node, and it resolves 80% of the time" - Generate suggestion to tree author: "Recommended new branch based on 18 successful sessions" - Author reviews and approves with one click — tree evolves from real usage - **Implementation:** Aggregation queries + LLM formatting suggestions + author approval UI ### Layer 3: AI Tree Generation + - Senior describes: "We keep getting Azure AD Sync issues, no tree exists" - AI generates complete tree draft using: - Similar trees in the system @@ -356,9 +404,11 @@ Three layers of AI, each building on the last, leveraging ResolutionFlow's uniqu - **Implementation:** RAG over tree corpus + session data + LLM generation + tree editor integration ### Why This Is the Moat + ConnectWise or IT Glue could build a decision tree tool. But they don't have hundreds of structured session paths with outcomes to learn from. ResolutionFlow's data is structured by design — decision trees + session paths + outcomes — not unstructured ticket notes. That's a dataset purpose-built for learning optimal troubleshooting paths. ### Phasing + - Layer 1 can ship independently with basic NLP - Layer 2 needs sufficient session volume (6+ months of real usage) - Layer 3 needs Layers 1 + 2 data + LLM integration @@ -371,9 +421,11 @@ ConnectWise or IT Glue could build a decision tree tool. But they don't have hun **Effort:** Medium ### What + Replace the tree library as the default landing page with a troubleshooting command center. ### Sections + - **Resume sessions** — "VPN Issues - Acme Corp (started 20 min ago)" for incomplete sessions - **Quick starts** — Frequent tree+client combos: "File Share Access for Warner Robins — Quick start?" One tap. - **Team activity** — "Sarah completed 'AD Replication' for Client X (12 min)" — visibility without a standup @@ -381,6 +433,7 @@ Replace the tree library as the default landing page with a troubleshooting comm - **Recurring alerts** — Clients with repeat issues that need attention ### Why + Turns ResolutionFlow from a tool you visit per-ticket into something you keep open all day. Reduces friction from "open app → find tree → start session" to "open app → click the obvious next action." --- @@ -388,22 +441,26 @@ Turns ResolutionFlow from a tool you visit per-ticket into something you keep op ## Suggested Build Order ### Near-term (build now, small effort, immediate value) + 1. **Session Scratchpad** (Idea 6) — must-have per Michael 2. **Session Time Tracking** (Idea 1) — quick win, enhances every export 3. **Command Output Capture** (Idea 3) — quick win, pairs with scratchpad ### Mid-term (build next, medium effort, high value) + 4. **Share Progress / Escalation** (Idea 2) — daily use for team collaboration 5. **Recurring Issue Detection** (Idea 8) — leverages existing data immediately 6. **Quick Actions Dashboard** (Bonus) — improves daily UX 7. **Path Analytics** (Idea 5) — needs session volume, start collecting data now ### Later (larger effort, needs foundation) + 8. **Push Steps to Active Sessions** (Idea 4) — needs notification system 9. **Tree Health Scores** (Idea 9) — needs session volume + analytics infrastructure 10. **Multi-Tree Sessions** (Idea 7) — complex UX, large refactor ### Long-term vision + 11. **AI Tree Intelligence** (Idea 10) — phased rollout, ultimate differentiator --- diff --git a/docs/plans/2026-02-04-session-scratchpad-design.md b/docs/plans/2026-02-04-session-scratchpad-design.md new file mode 100644 index 00000000..8ec7a828 --- /dev/null +++ b/docs/plans/2026-02-04-session-scratchpad-design.md @@ -0,0 +1,276 @@ +# Session Scratchpad Design + +> **Date:** February 4, 2026 +> **Source:** Feature Ideas Brainstorm - Idea 6 +> **Priority:** Must-have (per Michael) +> **Category:** Context capture + +--- + +## Overview + +A collapsible right sidebar during active sessions for capturing ambient data — IP addresses, error codes, server names, usernames — anything that doesn't fit a specific decision node's notes field. + +**Core principle:** Engineers already accumulate scraps of data during troubleshooting (from `ipconfig`, Event Viewer, phone conversations) that live on sticky notes or in their head. This gives it a home and includes it automatically in the export. + +**Data model:** Single freeform `Text` column on the `sessions` table with markdown formatting support. Not JSONB — we're starting simple with a plain text field that the engineer writes in freely. + +**Save behavior:** Auto-save with 1000ms debounce. No manual save button. + +**Layout:** Collapsible right sidebar in `TreeNavigationPage`, 300px when open, 48px toggle strip when collapsed. + +--- + +## Section 1: Data Model + +### Database + +New `scratchpad` column on `sessions` table: + +```python +# SQLAlchemy model (session.py) +scratchpad: Mapped[Optional[str]] = mapped_column(Text, nullable=True, server_default=sa.text("''")) +``` + +### Migration + +```python +# alembic revision -m "add scratchpad to sessions" +def upgrade(): + op.add_column('sessions', sa.Column('scratchpad', sa.Text(), nullable=True, server_default=sa.text("''"))) + # Backfill existing rows + op.execute("UPDATE sessions SET scratchpad = '' WHERE scratchpad IS NULL") + +def downgrade(): + op.drop_column('sessions', 'scratchpad') +``` + +- `server_default=sa.text("''")` ensures new rows get `""` at the database level +- Backfill normalizes existing rows so no code path sees `NULL` + +### Schemas + +**SessionUpdate** — add field: +```python +scratchpad: Optional[str] = None +``` + +**SessionResponse** — add field with validator: +```python +scratchpad: str = "" + +@validator('scratchpad', pre=True, always=True) +def normalize_scratchpad(cls, v): + return v or "" +``` + +**New schema — ScratchpadUpdate:** +```python +class ScratchpadUpdate(BaseModel): + scratchpad: str +``` + +--- + +## Section 2: Frontend Component Design + +### Layout Restructuring + +Current `TreeNavigationPage` is a single-column `container mx-auto` div. Restructure to: + +``` +┌─────────────────────────────────────┬──────────────┐ +│ Existing tree navigation content │ Scratchpad │ +│ (header, breadcrumb, node card, │ sidebar │ +│ notes, back button, shortcuts) │ (300px) │ +│ │ │ +└─────────────────────────────────────┴──────────────┘ +``` + +- Outer wrapper: `flex` layout +- Main content: `flex-1 min-w-0` (prevents overflow) +- Sidebar: Fixed 300px open, 48px collapsed +- Collapse state persisted in `localStorage` as `scratchpad-collapsed` + +### ScratchpadSidebar Component + +**File:** `frontend/src/components/session/ScratchpadSidebar.tsx` + +**Props:** +```typescript +interface ScratchpadSidebarProps { + sessionId: string + initialContent: string + onSave: (content: string) => Promise +} +``` + +**Internal state:** +- `content: string` — textarea value, initialized from `initialContent`, **only reset when `sessionId` changes** (via `useEffect` with `[sessionId]` dependency) +- `isCollapsed: boolean` — sidebar open/closed, persisted in localStorage +- `isSaving: boolean` — network request in flight +- `hasUnsavedChanges: boolean` — `content !== lastSaved` +- `lastSaved: string` — last successfully saved content +- `showPreview: boolean` — toggle between edit and markdown preview + +### Save Flow + +1. User types → `content` updates → `hasUnsavedChanges = (content !== lastSaved)` +2. After 1000ms of no typing (debounce), if `hasUnsavedChanges`, fire `onSave(content)` +3. Set `isSaving = true` during request +4. On success: `lastSaved = content`, `isSaving = false`, `hasUnsavedChanges = false` +5. On blur: trigger immediate save if `hasUnsavedChanges` (cancel pending debounce) +6. On error: keep `hasUnsavedChanges = true`, show error indicator + +### Save Indicator (bottom of sidebar) + +| State | Display | +|-------|---------| +| Idle, no changes | Nothing shown | +| Typing, unsaved | "Unsaved changes" (muted text) | +| Saving | "Saving..." with subtle spinner | +| Just saved | "Saved" with checkmark (green, fades after 2s) | + +### beforeunload Warning + +- Register `window.addEventListener('beforeunload', handler)` only when `hasUnsavedChanges === true` +- Handler calls `e.preventDefault()` to trigger browser's "unsaved changes" dialog +- Clean up listener on unmount + +### Markdown Preview + +- Small toggle link below textarea: "Preview" / "Edit" +- Preview renders current `content` using existing `MarkdownContent` component +- No new dependencies required + +### Dimensions & Animation + +- Open width: 300px +- Collapsed width: 48px (notepad icon button) +- Transition: `width 200ms ease` +- Toggle icon: Notepad/pencil icon from Lucide + +--- + +## Section 3: Backend & API + +### New Endpoint + +``` +PATCH /api/v1/sessions/{id}/scratchpad +``` + +**Request body:** +```json +{ "scratchpad": "- Server IP: 192.168.1.50\n- Error: 0x80070005" } +``` + +**Response:** `SessionResponse` (full session object) + +**Handler logic:** +1. Load session by ID +2. Verify `session.user_id == current_user.id` (ownership check) +3. Set `session.scratchpad = data.scratchpad` +4. Commit and return updated session + +This is intentionally separate from the existing PUT endpoint. Auto-saving the scratchpad every second should not send the full session payload (`path_taken`, `decisions`, `custom_steps`) — that risks overwriting concurrent changes from decision tracking in the same session. + +### Frontend API Client + +```typescript +// sessions.ts +updateScratchpad: (id: string, content: string) => + api.patch(`/api/v1/sessions/${id}/scratchpad`, { scratchpad: content }) +``` + +### Router Registration + +Add to `backend/app/api/router.py` — the endpoint lives in the existing `sessions.py` endpoints file. + +--- + +## Section 4: Export Integration + +Add a "Evidence / Reference" section to all three export generators, inserted **between the header block and "Troubleshooting Steps"**. Only rendered when `scratchpad.strip()` is non-empty. + +### Markdown Export + +```markdown +## Evidence / Reference + +- Server IP: 192.168.1.50 +- Error code: 0x80070005 +- Affected user: jsmith@contoso.com + +--- + +## Troubleshooting Steps +``` + +Scratchpad content rendered as-is (user writes markdown, it appears as markdown). + +### Text Export + +``` +EVIDENCE / REFERENCE +-------------------- +- Server IP: 192.168.1.50 +- Error code: 0x80070005 +- Affected user: jsmith@contoso.com + +TROUBLESHOOTING STEPS +--------------------- +``` + +### HTML Export + +```html +

Evidence / Reference

+
+- Server IP: 192.168.1.50 +- Error code: 0x80070005 +
+

Troubleshooting Steps

+``` + +Start with `pre-wrap` for HTML export. Future enhancement: render scratchpad markdown to HTML. + +--- + +## Files Changed + +| File | Action | Description | +|------|--------|-------------| +| `backend/app/models/session.py` | Modify | Add `scratchpad` field | +| `backend/app/schemas/session.py` | Modify | Add to `SessionUpdate`, `SessionResponse` + new `ScratchpadUpdate` | +| `backend/app/api/endpoints/sessions.py` | Modify | Add PATCH endpoint + scratchpad in all 3 export generators | +| `backend/app/api/router.py` | Modify | Register new PATCH route | +| `backend/alembic/versions/xxx_add_scratchpad.py` | Create | Migration with backfill | +| `frontend/src/components/session/ScratchpadSidebar.tsx` | Create | New sidebar component | +| `frontend/src/pages/TreeNavigationPage.tsx` | Modify | Add flex layout + render sidebar | +| `frontend/src/api/sessions.ts` | Modify | Add `updateScratchpad` method | +| `frontend/src/types/session.ts` | Modify | Add `scratchpad` to Session type | + +--- + +## Design Decisions + +| Decision | Choice | Rationale | +|----------|--------|-----------| +| Storage type | `Text` column (not JSONB) | Freeform text is simpler; structured entries are a future enhancement | +| Save mechanism | Auto-save with 1000ms debounce | Reduces friction — engineer never thinks about saving | +| API endpoint | Dedicated PATCH (not reuse PUT) | Prevents scratchpad auto-saves from overwriting concurrent decision updates | +| Conflict detection | None (last-write-wins) | Sessions are single-user; multi-user requires broader solution | +| Markdown rendering | Preview toggle (not live) | Keeps the editing experience simple; preview is optional | +| Collapse persistence | localStorage | Survives page refreshes, per-browser preference | + +--- + +## Pairs With (Future) + +- **Command Output Capture** (Idea 3): Structured output at nodes + freeform notes in scratchpad = complete evidence +- **Share Progress** (Idea 2): Scratchpad content included in shared summary + +--- + +*Design finalized during brainstorming session, February 4, 2026*