docs: Add implementation plan and project review from stale branches
Cherry-picked useful documentation from branches being cleaned up: - IMPLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md: Planning doc for Step Library frontend - PROJECT-REVIEW-2026-02-02.md: Project status review from February 2026 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
590
docs/IMPLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md
Normal file
590
docs/IMPLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md
Normal file
@@ -0,0 +1,590 @@
|
|||||||
|
# Implementation Plan: Step Library Frontend + Tree Editor Validation
|
||||||
|
|
||||||
|
> **Date:** February 3, 2026
|
||||||
|
> **Scope:** Issues #1, #8, #9, #10
|
||||||
|
> **Estimated Components:** 8 new files, 4 modified files
|
||||||
|
> **Parallel Workstreams:** 2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This plan covers two parallel workstreams:
|
||||||
|
|
||||||
|
| Workstream | Issues | Description |
|
||||||
|
|------------|--------|-------------|
|
||||||
|
| **A** | #1 | Tree Editor Validation UI |
|
||||||
|
| **B** | #10 → #9 → #8 | Step Library Frontend (sequential) |
|
||||||
|
|
||||||
|
Both workstreams are independent and can be developed simultaneously.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workstream A: Tree Editor Validation (Issue #1)
|
||||||
|
|
||||||
|
### Current State
|
||||||
|
|
||||||
|
The validation logic **already exists** in `treeEditorStore.ts:519-658`. It checks:
|
||||||
|
- ✅ Tree name required
|
||||||
|
- ✅ Decision nodes need question + options
|
||||||
|
- ✅ Option labels required
|
||||||
|
- ✅ Action/Solution nodes need titles
|
||||||
|
- ✅ At least one solution node
|
||||||
|
- ✅ Orphan node detection
|
||||||
|
- ✅ Invalid node reference detection
|
||||||
|
|
||||||
|
### What's Missing
|
||||||
|
|
||||||
|
1. **UI to display validation errors** - No visual feedback shown to user
|
||||||
|
2. **Prevent save on errors** - Save button should be disabled or show confirmation
|
||||||
|
3. **Circular reference detection** - Not implemented in current validation
|
||||||
|
4. **Real-time validation** - Currently only validates on explicit call
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
#### A.1: Add Circular Reference Detection
|
||||||
|
**File:** `frontend/src/store/treeEditorStore.ts`
|
||||||
|
|
||||||
|
Add to the `validate()` function after line 624:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Check for circular references in next_node_id chains
|
||||||
|
const detectCircularRefs = (startId: string, visited: Set<string> = new Set()): boolean => {
|
||||||
|
if (visited.has(startId)) return true
|
||||||
|
visited.add(startId)
|
||||||
|
|
||||||
|
const node = findNodeInTree(startId, state.treeStructure)
|
||||||
|
if (!node) return false
|
||||||
|
|
||||||
|
// Check options
|
||||||
|
if (node.options) {
|
||||||
|
for (const opt of node.options) {
|
||||||
|
if (opt.next_node_id && detectCircularRefs(opt.next_node_id, new Set(visited))) {
|
||||||
|
errors.push({
|
||||||
|
nodeId: node.id,
|
||||||
|
message: `Circular reference detected: "${opt.label}" creates a loop`,
|
||||||
|
severity: 'error'
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check next_node_id
|
||||||
|
if (node.next_node_id && detectCircularRefs(node.next_node_id, new Set(visited))) {
|
||||||
|
errors.push({
|
||||||
|
nodeId: node.id,
|
||||||
|
message: `Circular reference detected in node "${node.title || node.id}"`,
|
||||||
|
severity: 'error'
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run from root
|
||||||
|
detectCircularRefs('root')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### A.2: Create Validation Summary Component
|
||||||
|
**File:** `frontend/src/components/tree-editor/ValidationSummary.tsx` (NEW)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ValidationSummaryProps {
|
||||||
|
errors: ValidationError[]
|
||||||
|
onSelectNode: (nodeId: string) => void
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Collapsible panel showing error/warning count
|
||||||
|
- Click error to select the problematic node
|
||||||
|
- Color-coded: red for errors, yellow for warnings
|
||||||
|
- Icon indicators (AlertCircle, AlertTriangle from lucide-react)
|
||||||
|
|
||||||
|
#### A.3: Integrate Validation UI into TreeEditorPage
|
||||||
|
**File:** `frontend/src/pages/TreeEditorPage.tsx`
|
||||||
|
|
||||||
|
Modifications:
|
||||||
|
1. Call `validate()` before save attempt
|
||||||
|
2. Show ValidationSummary when errors exist
|
||||||
|
3. Block save if any severity='error' exists (warnings allow save)
|
||||||
|
4. Add "Validate" button in toolbar for manual check
|
||||||
|
5. Auto-validate on blur from form fields (debounced)
|
||||||
|
|
||||||
|
#### A.4: Visual Node Error Indicators
|
||||||
|
**File:** `frontend/src/components/tree-editor/NodeList.tsx`
|
||||||
|
|
||||||
|
Modifications:
|
||||||
|
- Add red border/highlight to nodes with validation errors
|
||||||
|
- Show error icon badge on problem nodes
|
||||||
|
- Tooltip on hover showing the specific error
|
||||||
|
|
||||||
|
### Acceptance Criteria - Workstream A
|
||||||
|
|
||||||
|
- [ ] Cannot save tree without a name
|
||||||
|
- [ ] Cannot save tree without at least one solution node
|
||||||
|
- [ ] Validation errors display in a clear, clickable list
|
||||||
|
- [ ] Clicking an error selects the problematic node
|
||||||
|
- [ ] Circular references are detected and blocked
|
||||||
|
- [ ] Orphan nodes show as warnings (allow save with confirmation)
|
||||||
|
- [ ] Save button disabled when errors exist
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workstream B: Step Library Frontend (Issues #10, #9, #8)
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- Backend API complete ✅ (`/api/v1/steps/*`, `/api/v1/step-categories/*`)
|
||||||
|
- No frontend API client exists yet
|
||||||
|
|
||||||
|
### Execution Order
|
||||||
|
```
|
||||||
|
#10 Step Library Browser Component
|
||||||
|
↓
|
||||||
|
#9 Custom Step Creation Modal (embeds browser)
|
||||||
|
↓
|
||||||
|
#8 Add Custom Step Button (triggers modal)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue #10: Step Library Browser Component
|
||||||
|
|
||||||
|
#### B.1: Create Steps API Client
|
||||||
|
**File:** `frontend/src/api/steps.ts` (NEW)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// API client for step library endpoints
|
||||||
|
export const stepsApi = {
|
||||||
|
list: (params?: StepListParams) => Promise<StepListItem[]>
|
||||||
|
get: (id: string) => Promise<Step>
|
||||||
|
create: (data: StepCreate) => Promise<Step>
|
||||||
|
update: (id: string, data: StepUpdate) => Promise<Step>
|
||||||
|
delete: (id: string) => Promise<void>
|
||||||
|
search: (query: string) => Promise<StepListItem[]>
|
||||||
|
getPopularTags: () => Promise<PopularTag[]>
|
||||||
|
rate: (id: string, data: RatingCreate) => Promise<Rating>
|
||||||
|
updateRating: (id: string, data: RatingUpdate) => Promise<Rating>
|
||||||
|
deleteRating: (id: string) => Promise<void>
|
||||||
|
getReviews: (id: string) => Promise<Review[]>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### B.2: Create Step Categories API Client
|
||||||
|
**File:** `frontend/src/api/stepCategories.ts` (NEW)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export const stepCategoriesApi = {
|
||||||
|
list: () => Promise<StepCategory[]>
|
||||||
|
get: (id: string) => Promise<StepCategory>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### B.3: Add TypeScript Types
|
||||||
|
**File:** `frontend/src/types/step.ts` (NEW)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export interface StepCommand {
|
||||||
|
label: string
|
||||||
|
command: string
|
||||||
|
command_type?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StepContent {
|
||||||
|
instructions: string
|
||||||
|
help_text?: string
|
||||||
|
commands?: StepCommand[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Step {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
step_type: 'decision' | 'action' | 'solution'
|
||||||
|
content: StepContent
|
||||||
|
visibility: 'private' | 'team' | 'public'
|
||||||
|
category_id?: string
|
||||||
|
category_name?: string
|
||||||
|
tags: string[]
|
||||||
|
usage_count: number
|
||||||
|
rating_average: number
|
||||||
|
rating_count: number
|
||||||
|
helpful_yes: number
|
||||||
|
helpful_no: number
|
||||||
|
is_featured: boolean
|
||||||
|
is_verified: boolean
|
||||||
|
created_by: string
|
||||||
|
author_name?: string
|
||||||
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StepListItem {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
step_type: string
|
||||||
|
visibility: string
|
||||||
|
category_id?: string
|
||||||
|
category_name?: string
|
||||||
|
tags: string[]
|
||||||
|
usage_count: number
|
||||||
|
rating_average: number
|
||||||
|
rating_count: number
|
||||||
|
is_featured: boolean
|
||||||
|
created_by: string
|
||||||
|
author_name?: string
|
||||||
|
created_at: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StepCategory {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
description?: string
|
||||||
|
display_order: number
|
||||||
|
team_id?: string
|
||||||
|
is_active: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StepListParams {
|
||||||
|
visibility?: 'private' | 'team' | 'public'
|
||||||
|
category_id?: string
|
||||||
|
tags?: string[]
|
||||||
|
min_rating?: number
|
||||||
|
step_type?: 'decision' | 'action' | 'solution'
|
||||||
|
sort_by?: 'recent' | 'popular' | 'highest_rated' | 'most_used'
|
||||||
|
limit?: number
|
||||||
|
offset?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PopularTag {
|
||||||
|
tag: string
|
||||||
|
count: number
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### B.4: Create Step Card Component
|
||||||
|
**File:** `frontend/src/components/step-library/StepCard.tsx` (NEW)
|
||||||
|
|
||||||
|
A card displaying:
|
||||||
|
- Step title and type badge (decision/action/solution)
|
||||||
|
- Category name
|
||||||
|
- Star rating (if rated) or "Not rated" placeholder
|
||||||
|
- Tags as chips (max 3 visible, "+N more" overflow)
|
||||||
|
- Author name and created date
|
||||||
|
- Usage count
|
||||||
|
- [Preview] and [Insert] buttons
|
||||||
|
|
||||||
|
#### B.5: Create Step Detail Modal
|
||||||
|
**File:** `frontend/src/components/step-library/StepDetailModal.tsx` (NEW)
|
||||||
|
|
||||||
|
Full step preview showing:
|
||||||
|
- Title, type, category, tags
|
||||||
|
- Full rating breakdown (star distribution chart)
|
||||||
|
- Instructions (markdown rendered)
|
||||||
|
- Commands (copyable code blocks)
|
||||||
|
- Help text
|
||||||
|
- Top reviews (2-3 shown, "See all" link)
|
||||||
|
- [Cancel] and [Insert Into Session] buttons
|
||||||
|
|
||||||
|
#### B.6: Create Step Library Browser Component
|
||||||
|
**File:** `frontend/src/components/step-library/StepLibraryBrowser.tsx` (NEW)
|
||||||
|
|
||||||
|
Main browser component with:
|
||||||
|
|
||||||
|
**Header:**
|
||||||
|
- Search input (full-text, debounced 300ms)
|
||||||
|
- Filter dropdowns: Category, Type, Min Rating, Sort By
|
||||||
|
- Popular tags as clickable chips
|
||||||
|
|
||||||
|
**Body:**
|
||||||
|
- Grouped sections: "My Steps", "Team Steps", "Community"
|
||||||
|
- Each section collapsible
|
||||||
|
- Virtualized list for performance (if >50 items)
|
||||||
|
- Loading skeletons while fetching
|
||||||
|
- Empty state: "No steps found. Create your first step!"
|
||||||
|
|
||||||
|
**Footer:**
|
||||||
|
- [+ Create New Step] button (optional, for standalone use)
|
||||||
|
|
||||||
|
**Props:**
|
||||||
|
```typescript
|
||||||
|
interface StepLibraryBrowserProps {
|
||||||
|
onInsert: (step: Step) => void
|
||||||
|
onCreateNew?: () => void
|
||||||
|
showCreateButton?: boolean
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### B.7: Update API Index
|
||||||
|
**File:** `frontend/src/api/index.ts`
|
||||||
|
|
||||||
|
Add exports for `stepsApi` and `stepCategoriesApi`.
|
||||||
|
|
||||||
|
### Acceptance Criteria - Issue #10
|
||||||
|
|
||||||
|
- [ ] Can search steps with full-text query
|
||||||
|
- [ ] Can filter by category, type, minimum rating
|
||||||
|
- [ ] Can sort by recent, popular, highest rated, most used
|
||||||
|
- [ ] Steps grouped by visibility (My Steps, Team, Community)
|
||||||
|
- [ ] Can click step to see full preview modal
|
||||||
|
- [ ] Can copy commands from preview
|
||||||
|
- [ ] Can click "Insert" to select a step
|
||||||
|
- [ ] Popular tags shown and clickable as quick filters
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue #9: Custom Step Creation Modal
|
||||||
|
|
||||||
|
#### B.8: Create Step Form Component
|
||||||
|
**File:** `frontend/src/components/step-library/StepForm.tsx` (NEW)
|
||||||
|
|
||||||
|
Form fields:
|
||||||
|
- Step Type: Radio group (Decision / Action / Solution)
|
||||||
|
- Title: Text input (required)
|
||||||
|
- Instructions: Textarea with markdown support (required)
|
||||||
|
- Help Text: Textarea (optional)
|
||||||
|
- Commands: Dynamic array field (optional)
|
||||||
|
- Each command: label + command + type dropdown
|
||||||
|
- Category: Dropdown (optional)
|
||||||
|
- Tags: Tag input with autocomplete (optional)
|
||||||
|
- Visibility: Dropdown (Private / Team / Public)
|
||||||
|
- Checkbox: "Save to My Step Library for reuse"
|
||||||
|
|
||||||
|
#### B.9: Create Custom Step Modal
|
||||||
|
**File:** `frontend/src/components/step-library/CustomStepModal.tsx` (NEW)
|
||||||
|
|
||||||
|
Tabbed modal with:
|
||||||
|
- **Tab 1: "Type My Own"** - StepForm component
|
||||||
|
- **Tab 2: "Browse Library"** - StepLibraryBrowser component
|
||||||
|
|
||||||
|
**Props:**
|
||||||
|
```typescript
|
||||||
|
interface CustomStepModalProps {
|
||||||
|
isOpen: boolean
|
||||||
|
onClose: () => void
|
||||||
|
onInsertStep: (step: Step | CustomStepDraft) => void
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Behavior:**
|
||||||
|
- Tab 1: User fills form, clicks [Insert Step]
|
||||||
|
- If "Save to library" checked, POST to `/api/v1/steps` first
|
||||||
|
- Returns step data to parent
|
||||||
|
- Tab 2: User browses, clicks Insert on a step
|
||||||
|
- Returns selected step to parent
|
||||||
|
|
||||||
|
### Acceptance Criteria - Issue #9
|
||||||
|
|
||||||
|
- [ ] Modal has two tabs: "Type My Own" and "Browse Library"
|
||||||
|
- [ ] Can create custom step with type, title, instructions
|
||||||
|
- [ ] Can optionally add commands, help text, category, tags
|
||||||
|
- [ ] Can optionally save step to personal library
|
||||||
|
- [ ] Can switch to Browse tab and select existing step
|
||||||
|
- [ ] Insert button returns step data to parent component
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue #8: Add Custom Step Button in Tree Navigation
|
||||||
|
|
||||||
|
#### B.10: Modify TreeNavigationPage
|
||||||
|
**File:** `frontend/src/pages/TreeNavigationPage.tsx`
|
||||||
|
|
||||||
|
Add state:
|
||||||
|
```typescript
|
||||||
|
const [showCustomStepModal, setShowCustomStepModal] = useState(false)
|
||||||
|
const [customSteps, setCustomSteps] = useState<CustomStep[]>([])
|
||||||
|
```
|
||||||
|
|
||||||
|
**UI Changes:**
|
||||||
|
|
||||||
|
1. After each decision node's options, add:
|
||||||
|
```tsx
|
||||||
|
<button
|
||||||
|
onClick={() => setShowCustomStepModal(true)}
|
||||||
|
className="mt-2 text-sm text-primary hover:underline"
|
||||||
|
>
|
||||||
|
+ Add Custom Step
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add CustomStepModal at bottom of component
|
||||||
|
|
||||||
|
3. Handle insert:
|
||||||
|
```typescript
|
||||||
|
const handleInsertCustomStep = (step: Step | CustomStepDraft) => {
|
||||||
|
// Insert after current node in session
|
||||||
|
const customStep: CustomStep = {
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
inserted_after_node_id: currentNodeId,
|
||||||
|
step_data: step,
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
}
|
||||||
|
setCustomSteps([...customSteps, customStep])
|
||||||
|
|
||||||
|
// Navigate to custom step (becomes current)
|
||||||
|
setCurrentNodeId(customStep.id)
|
||||||
|
setShowCustomStepModal(false)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Render custom steps in the navigation flow with visual indicator:
|
||||||
|
```tsx
|
||||||
|
{/* Custom Step Badge */}
|
||||||
|
<span className="rounded-full bg-purple-100 px-2 py-1 text-xs font-medium text-purple-800">
|
||||||
|
Custom Step
|
||||||
|
</span>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### B.11: Update Session Export
|
||||||
|
**File:** `frontend/src/components/session/ExportPreviewModal.tsx`
|
||||||
|
|
||||||
|
Ensure custom steps are included in export with clear marking:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Step 5: [CUSTOM] Check Additional Logs
|
||||||
|
*Custom step added by user*
|
||||||
|
|
||||||
|
Instructions: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
#### B.12: Update Session Types
|
||||||
|
**File:** `frontend/src/types/index.ts`
|
||||||
|
|
||||||
|
Add:
|
||||||
|
```typescript
|
||||||
|
export interface CustomStep {
|
||||||
|
id: string
|
||||||
|
inserted_after_node_id: string
|
||||||
|
step_data: Step | CustomStepDraft
|
||||||
|
timestamp: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CustomStepDraft {
|
||||||
|
title: string
|
||||||
|
step_type: 'decision' | 'action' | 'solution'
|
||||||
|
content: StepContent
|
||||||
|
category_id?: string
|
||||||
|
tags?: string[]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Acceptance Criteria - Issue #8
|
||||||
|
|
||||||
|
- [ ] "+ Add Custom Step" button visible at each decision point
|
||||||
|
- [ ] Button opens CustomStepModal
|
||||||
|
- [ ] Can insert step from "Type My Own" tab
|
||||||
|
- [ ] Can insert step from "Browse Library" tab
|
||||||
|
- [ ] Custom steps appear in session flow with visual indicator
|
||||||
|
- [ ] Custom steps included in session export
|
||||||
|
- [ ] Session continues after custom step
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Summary
|
||||||
|
|
||||||
|
### New Files (10)
|
||||||
|
|
||||||
|
| File | Issue | Description |
|
||||||
|
|------|-------|-------------|
|
||||||
|
| `components/tree-editor/ValidationSummary.tsx` | #1 | Error/warning display |
|
||||||
|
| `api/steps.ts` | #10 | Steps API client |
|
||||||
|
| `api/stepCategories.ts` | #10 | Categories API client |
|
||||||
|
| `types/step.ts` | #10 | Step TypeScript types |
|
||||||
|
| `components/step-library/StepCard.tsx` | #10 | Step list item card |
|
||||||
|
| `components/step-library/StepDetailModal.tsx` | #10 | Step preview modal |
|
||||||
|
| `components/step-library/StepLibraryBrowser.tsx` | #10 | Main browser component |
|
||||||
|
| `components/step-library/StepForm.tsx` | #9 | Step creation form |
|
||||||
|
| `components/step-library/CustomStepModal.tsx` | #9 | Tabbed modal wrapper |
|
||||||
|
|
||||||
|
### Modified Files (5)
|
||||||
|
|
||||||
|
| File | Issue | Changes |
|
||||||
|
|------|-------|---------|
|
||||||
|
| `store/treeEditorStore.ts` | #1 | Add circular reference detection |
|
||||||
|
| `pages/TreeEditorPage.tsx` | #1 | Integrate validation UI |
|
||||||
|
| `components/tree-editor/NodeList.tsx` | #1 | Node error indicators |
|
||||||
|
| `pages/TreeNavigationPage.tsx` | #8 | Add custom step button + modal |
|
||||||
|
| `api/index.ts` | #10 | Export new API clients |
|
||||||
|
| `types/index.ts` | #8 | Add CustomStep types |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Execution Plan
|
||||||
|
|
||||||
|
### Phase 1: Foundation (Do First)
|
||||||
|
```
|
||||||
|
Workstream A Workstream B
|
||||||
|
───────────── ─────────────
|
||||||
|
A.1 Circular ref detection B.1 Steps API client
|
||||||
|
B.2 Categories API client
|
||||||
|
B.3 TypeScript types
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 2: Core Components
|
||||||
|
```
|
||||||
|
Workstream A Workstream B
|
||||||
|
───────────── ─────────────
|
||||||
|
A.2 ValidationSummary B.4 StepCard
|
||||||
|
A.3 TreeEditorPage integration B.5 StepDetailModal
|
||||||
|
A.4 NodeList indicators B.6 StepLibraryBrowser
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 3: Integration
|
||||||
|
```
|
||||||
|
Workstream A Workstream B
|
||||||
|
───────────── ─────────────
|
||||||
|
Testing & polish B.8 StepForm
|
||||||
|
B.9 CustomStepModal
|
||||||
|
B.10 TreeNavigationPage integration
|
||||||
|
B.11-12 Export & types updates
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Checklist
|
||||||
|
|
||||||
|
### Workstream A - Validation
|
||||||
|
- [ ] Create tree without name → Error shown, save blocked
|
||||||
|
- [ ] Create tree without solution → Error shown, save blocked
|
||||||
|
- [ ] Create decision without options → Error shown
|
||||||
|
- [ ] Create circular reference (A → B → A) → Error detected
|
||||||
|
- [ ] Create orphan node → Warning shown (can still save)
|
||||||
|
- [ ] Click error → Node selected
|
||||||
|
- [ ] Fix all errors → Save enabled
|
||||||
|
|
||||||
|
### Workstream B - Step Library
|
||||||
|
- [ ] Open browser → Steps load, grouped by visibility
|
||||||
|
- [ ] Search "citrix" → Filtered results appear
|
||||||
|
- [ ] Filter by category → Results filtered
|
||||||
|
- [ ] Click step → Preview modal opens
|
||||||
|
- [ ] Click copy command → Copied to clipboard
|
||||||
|
- [ ] Click Insert → Modal closes, step returned
|
||||||
|
- [ ] Create custom step → Form validates, step inserted
|
||||||
|
- [ ] Save to library checked → Step saved to API
|
||||||
|
- [ ] Add custom step in navigation → Step appears with badge
|
||||||
|
- [ ] Complete session → Export includes custom steps
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes for Implementation
|
||||||
|
|
||||||
|
1. **Use existing patterns**: Follow Modal.tsx, TagInput.tsx, and existing page structures
|
||||||
|
2. **Dark mode**: All components must support light/dark themes via Tailwind classes
|
||||||
|
3. **Keyboard navigation**: Support Escape to close modals, Enter to submit
|
||||||
|
4. **Loading states**: Show skeletons or spinners during API calls
|
||||||
|
5. **Error handling**: Display user-friendly error messages, log details to console
|
||||||
|
6. **Accessibility**: Use proper ARIA labels, maintain focus management in modals
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions to Resolve Before Starting
|
||||||
|
|
||||||
|
1. **Custom steps persistence**: Should custom steps be saved to the session in the database, or only exist in frontend state until export?
|
||||||
|
- *Recommendation*: Save to session.decisions with a `is_custom_step: true` flag
|
||||||
|
|
||||||
|
2. **Step library page**: Should there be a standalone `/steps` page for browsing the library outside of navigation?
|
||||||
|
- *Recommendation*: Yes, add this as a future enhancement after Issue #10
|
||||||
|
|
||||||
|
3. **Rate limiting**: Should step creation have rate limiting to prevent spam?
|
||||||
|
- *Recommendation*: Backend concern, out of scope for this plan
|
||||||
172
docs/PROJECT-REVIEW-2026-02-02.md
Normal file
172
docs/PROJECT-REVIEW-2026-02-02.md
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
# Patherly Project Review
|
||||||
|
|
||||||
|
**Date:** February 2, 2026
|
||||||
|
**Reviewer:** Claude Opus 4.5
|
||||||
|
**Project Phase:** Phase 2 - Tree Editor (In Progress)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
|
||||||
|
Patherly is in solid shape with **Phase 2 (Tree Editor) substantially complete**. The project has a well-architected backend with 23+ API endpoints and 30+ passing tests, a functional frontend with all core features, and production deployment working on Railway.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What's Complete
|
||||||
|
|
||||||
|
### Core MVP Features
|
||||||
|
- User authentication with JWT, refresh tokens, and invite codes
|
||||||
|
- Full tree CRUD with JSONB-based flexible node structure
|
||||||
|
- Decision tree navigation with session tracking and note capture
|
||||||
|
- Session export in Markdown, Text, and HTML formats
|
||||||
|
- Full-text search on trees
|
||||||
|
|
||||||
|
### Tree Editor (Phase 2)
|
||||||
|
- Form-based node editing with undo/redo
|
||||||
|
- Visual tree preview with solution indicators and shared link detection
|
||||||
|
- Markdown preview toggle in description fields
|
||||||
|
- All node types supported: Decision, Action, Solution
|
||||||
|
|
||||||
|
### Organization System
|
||||||
|
- Categories (global + team-specific, admin-managed)
|
||||||
|
- Tags with autocomplete and usage tracking
|
||||||
|
- Personal folder hierarchy (max 3 levels) with context menus
|
||||||
|
- Tree filtering by category, tags, and folders
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
- Production deployment on Railway (app.patherly.com / api.patherly.com)
|
||||||
|
- PR preview environments enabled
|
||||||
|
- Comprehensive structured logging with correlation IDs
|
||||||
|
- 7 seed trees covering Tier 1-3 troubleshooting scenarios
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## In Progress / Partially Complete
|
||||||
|
|
||||||
|
| Feature | Status | What's Missing |
|
||||||
|
|---------|--------|----------------|
|
||||||
|
| User Preferences | Schema exists | UI for export format default not built |
|
||||||
|
| TypeScript Strict Mode | Disabled | Some type safety gaps |
|
||||||
|
| Tree Editor Validation | Basic | No orphan node or cycle detection |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Next Steps
|
||||||
|
|
||||||
|
### High Priority (Improves Current Experience)
|
||||||
|
|
||||||
|
1. **Export Format Preference UI**
|
||||||
|
- User preference schema exists but UI isn't built
|
||||||
|
- Quick win: Add dropdown in user settings to set default export format
|
||||||
|
- Impact: Reduces friction for frequent exporters
|
||||||
|
|
||||||
|
2. **Copy-to-Clipboard for Exports**
|
||||||
|
- Currently must export to file
|
||||||
|
- One-click copy of Markdown output would save time
|
||||||
|
- MSPs often paste into ConnectWise/tickets directly
|
||||||
|
|
||||||
|
3. **Tree Editor Validation Improvements**
|
||||||
|
- Detect orphan nodes (not reachable from root)
|
||||||
|
- Detect cycles (infinite loops)
|
||||||
|
- Required field validation before save
|
||||||
|
- Shows warnings in visual preview
|
||||||
|
|
||||||
|
4. **Session Resume from History**
|
||||||
|
- Can view session history but resuming isn't obvious
|
||||||
|
- Add clear "Resume" button on incomplete sessions
|
||||||
|
|
||||||
|
### Medium Priority (Prepares for Growth)
|
||||||
|
|
||||||
|
5. **Frontend Testing**
|
||||||
|
- No frontend tests currently
|
||||||
|
- Add Vitest for unit tests, Playwright for E2E
|
||||||
|
- Critical flows: login, tree navigation, export
|
||||||
|
|
||||||
|
6. **Keyboard Shortcuts Documentation**
|
||||||
|
- Hook exists but not fully utilized
|
||||||
|
- Add shortcuts for common editor actions (save, undo, add node)
|
||||||
|
- Display shortcut hints in UI or help panel
|
||||||
|
|
||||||
|
7. **Tree Duplication/Clone**
|
||||||
|
- Currently must recreate trees manually
|
||||||
|
- "Duplicate tree" would enable creating variations
|
||||||
|
- Useful for team templates
|
||||||
|
|
||||||
|
8. **Search Improvements**
|
||||||
|
- Add search within tree editor (find nodes by text)
|
||||||
|
- Filter session history by tree name or date range
|
||||||
|
|
||||||
|
### Lower Priority (Future Features - Phase 2.5+)
|
||||||
|
|
||||||
|
9. **Personal Branching** (as spec'd in PHASE-2.5-PERSONAL-BRANCHING.md)
|
||||||
|
- Let users add custom steps during sessions
|
||||||
|
- Step Library with categories and ratings
|
||||||
|
- This is the next major feature per roadmap
|
||||||
|
|
||||||
|
10. **File Attachments**
|
||||||
|
- Schema exists but storage not implemented
|
||||||
|
- Would enable screenshots/logs in sessions
|
||||||
|
- Requires S3-compatible backend
|
||||||
|
|
||||||
|
11. **Tree Analytics**
|
||||||
|
- Track which paths engineers take most often
|
||||||
|
- Identify common resolution points
|
||||||
|
- Could inform tree optimization
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommendation Summary
|
||||||
|
|
||||||
|
| Priority | Action | Effort | Impact |
|
||||||
|
|----------|--------|--------|--------|
|
||||||
|
| High | Export format preference UI | 2-3 hours | Reduces daily friction |
|
||||||
|
| High | Copy-to-clipboard exports | 1-2 hours | Major UX improvement |
|
||||||
|
| High | Tree editor validation | 4-6 hours | Prevents broken trees |
|
||||||
|
| Medium | Frontend tests | 1-2 days | Long-term stability |
|
||||||
|
| Medium | Tree duplication | 2-3 hours | Enables templates |
|
||||||
|
| Lower | Personal branching (Phase 2.5) | 1-2 weeks | Major new capability |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Path to Goal: "50% of Tickets in 3 Months"
|
||||||
|
|
||||||
|
To hit Michael's goal of using Patherly for 50% of tickets:
|
||||||
|
|
||||||
|
1. **Content first**: The 7 seed trees are good, but may need more trees for common scenarios
|
||||||
|
2. **Speed to clipboard**: Copy-to-clipboard export is the #1 workflow improvement
|
||||||
|
3. **Mobile/tablet access**: If often away from desk, responsive design matters
|
||||||
|
4. **Session continuity**: Easy resume for multi-day troubleshooting tickets
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Health
|
||||||
|
|
||||||
|
### Strengths
|
||||||
|
- Consistent async/await patterns throughout
|
||||||
|
- Proper timezone handling (documented lessons learned)
|
||||||
|
- Clean separation: pages, components, stores, API client
|
||||||
|
- Good commit hygiene with clear messages
|
||||||
|
- 30+ passing backend integration tests
|
||||||
|
|
||||||
|
### Minor Technical Debt
|
||||||
|
- Enable TypeScript strict mode and fix resulting issues
|
||||||
|
- Some components could be split for maintainability
|
||||||
|
- Consider React Query for server state management
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Stats
|
||||||
|
|
||||||
|
| Metric | Count |
|
||||||
|
|--------|-------|
|
||||||
|
| API Endpoints | 23+ |
|
||||||
|
| Database Models | 10 |
|
||||||
|
| Backend Tests | 30+ |
|
||||||
|
| Seed Decision Trees | 7 |
|
||||||
|
| Alembic Migrations | 6 |
|
||||||
|
| Frontend Pages | 7 |
|
||||||
|
| Frontend Components | 25+ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Report generated by Claude Opus 4.5 for Patherly project review.*
|
||||||
Reference in New Issue
Block a user