From 4378ec4b20e11644547a730c24b098b7132114c9 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Tue, 3 Feb 2026 18:51:27 -0500 Subject: [PATCH] docs: Refine implementation plan and document draft feature - Updated IMPLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md with design decisions: - Custom steps persistence: separate `custom_steps` field in sessions - Custom step navigation: full step type support (decision/action/solution) - Validation warnings: inline dismissible, no confirmation modal - Added backend migration task (B.10) for custom_steps field - Updated file count: 10 new, 8 modified, 1 migration - Clarified acceptance criteria for validation behavior - Created docs/plans/2026-02-03-draft-trees-feature.md: - Comprehensive design for draft trees and custom steps - Database schema, API changes, frontend UX patterns - Implementation phases and success metrics - Related to Issue #25 (planned for Phase 3) Co-Authored-By: Claude Sonnet 4.5 --- ...PLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md | 270 +++++++-- docs/plans/2026-02-03-draft-trees-feature.md | 520 ++++++++++++++++++ 2 files changed, 744 insertions(+), 46 deletions(-) create mode 100644 docs/plans/2026-02-03-draft-trees-feature.md diff --git a/docs/IMPLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md b/docs/IMPLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md index 54c85d93..bab73fdf 100644 --- a/docs/IMPLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md +++ b/docs/IMPLEMENTATION-PLAN-STEP-LIBRARY-FRONTEND.md @@ -1,9 +1,29 @@ # Implementation Plan: Step Library Frontend + Tree Editor Validation -> **Date:** February 3, 2026 +> **Date:** February 3, 2026 (Updated after refinement session) > **Scope:** Issues #1, #8, #9, #10 -> **Estimated Components:** 8 new files, 4 modified files +> **Estimated Components:** 10 new files, 8 modified files, 1 migration > **Parallel Workstreams:** 2 +> **Related Planning:** Issue #25 (Draft Trees - Phase 3) + +--- + +## Plan Refinements (Feb 3, 2026) + +This plan was refined through collaborative design discussion. Key changes from initial draft: + +1. **Custom Steps Persistence** - Changed from storing in `decisions` array to separate `custom_steps` JSONB field + - Added: Backend migration task (B.10) + - Added: Session schema updates + - Enables: Session resuming with custom steps + +2. **Custom Step Navigation** - Expanded to support all step types (decision/action/solution) + - Added: Detailed rendering logic for each type in B.11 + - Enables: Custom branching decisions during troubleshooting + +3. **Validation Warnings** - Clarified as inline/dismissible (no confirmation modal) + - Updated: Acceptance criteria to specify warning behavior + - Deferred: "Save as Draft" feature to Issue #25 (Phase 3) --- @@ -108,10 +128,11 @@ Features: 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) +2. Show ValidationSummary when errors or warnings exist +3. Block save if any severity='error' exists (disable save button) +4. Warnings are **informational only** - do not block save, no confirmation modal +5. Add "Validate" button in toolbar for manual check +6. Auto-validate on blur from form fields (debounced) #### A.4: Visual Node Error Indicators **File:** `frontend/src/components/tree-editor/NodeList.tsx` @@ -123,13 +144,14 @@ Modifications: ### Acceptance Criteria - Workstream A -- [ ] Cannot save tree without a name -- [ ] Cannot save tree without at least one solution node +- [ ] Cannot save tree without a name (error blocks save) +- [ ] Cannot save tree without at least one solution node (error blocks save) - [ ] 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) +- [ ] Circular references are detected and blocked (error) +- [ ] Orphan nodes show as warnings (informational, do not block save) - [ ] Save button disabled when errors exist +- [ ] Warnings are dismissible/ignorable - user can save with warnings present --- @@ -387,7 +409,66 @@ interface CustomStepModalProps { ### Issue #8: Add Custom Step Button in Tree Navigation -#### B.10: Modify TreeNavigationPage +#### B.10: Add Custom Steps Backend Support +**Files:** +- `backend/alembic/versions/XXXX_add_custom_steps_to_sessions.py` (NEW - migration) +- `backend/app/schemas/session.py` (MODIFIED) +- `backend/app/api/endpoints/sessions.py` (MODIFIED) + +**Migration:** +```python +def upgrade(): + # Add custom_steps JSONB column to sessions table + op.add_column('sessions', + sa.Column('custom_steps', JSONB, nullable=False, server_default='[]') + ) + +def downgrade(): + op.drop_column('sessions', 'custom_steps') +``` + +**Schema Updates:** +```python +# In DecisionRecord - no changes needed (still uses node_id) + +# In SessionResponse - add custom_steps field +class SessionResponse(BaseModel): + # ... existing fields + custom_steps: list[dict[str, Any]] = Field(default_factory=list) # NEW + +# In SessionUpdate - add custom_steps field +class SessionUpdate(BaseModel): + # ... existing fields + custom_steps: Optional[list[dict[str, Any]]] = None # NEW +``` + +**Custom Step Structure in Database:** +```python +# Each item in custom_steps array: +{ + "id": "uuid-string", + "inserted_after_node_id": "parent-node-id", + "step_data": { + "title": "Check Additional Logs", + "step_type": "action", # decision | action | solution + "content": { + "instructions": "Check /var/log/...", + "help_text": "Optional help", + "commands": [...] # optional + }, + "category_id": "optional-uuid", + "tags": ["optional"] + }, + "timestamp": "2026-02-03T10:30:00Z" +} +``` + +**API Logic:** +- `PUT /api/v1/sessions/{id}` - Accept `custom_steps` in request body +- Validation: Ensure `step_data.step_type` is valid enum value +- No cascade delete needed - custom steps are session-scoped + +#### B.11: Modify TreeNavigationPage **File:** `frontend/src/pages/TreeNavigationPage.tsx` Add state: @@ -413,31 +494,83 @@ const [customSteps, setCustomSteps] = useState([]) 3. Handle insert: ```typescript const handleInsertCustomStep = (step: Step | CustomStepDraft) => { - // Insert after current node in session + // Create custom step object const customStep: CustomStep = { id: crypto.randomUUID(), inserted_after_node_id: currentNodeId, step_data: step, timestamp: new Date().toISOString() } - setCustomSteps([...customSteps, customStep]) + + // Add to local state + const newCustomSteps = [...customSteps, customStep] + setCustomSteps(newCustomSteps) // Navigate to custom step (becomes current) setCurrentNodeId(customStep.id) setShowCustomStepModal(false) + + // Save to backend + if (session) { + sessionsApi.update(session.id, { + custom_steps: newCustomSteps + }).catch(err => console.error('Failed to save custom step:', err)) + } } ``` -4. Render custom steps in the navigation flow with visual indicator: +4. Render custom steps based on type: ```tsx -{/* Custom Step Badge */} - - Custom Step - +{/* Render custom step in navigation flow */} +{currentNode?.id.startsWith('custom-') && ( +
+ {/* Custom Step Badge */} + + Custom Step + + + {/* Render based on step type */} + {customStepNode.step_data.step_type === 'decision' && ( + <> +

{customStepNode.step_data.title}

+ + {/* Render decision options - user creates them inline or uses predefined */} +
+ + +
+ + )} + + {customStepNode.step_data.step_type === 'action' && ( + <> +

{customStepNode.step_data.title}

+ + {customStepNode.step_data.content.commands?.map(cmd => ( +
{cmd.command}
+ ))} + + + )} + + {customStepNode.step_data.step_type === 'solution' && ( + <> +

{customStepNode.step_data.title}

+ + + + )} +
+)} ``` -#### B.11: Update Session Export -**File:** `frontend/src/components/session/ExportPreviewModal.tsx` +**Navigation Logic:** +- Custom decision: User selects option → continues to next tree node or another custom step +- Custom action: User clicks Continue → returns to tree flow (next_node_id of original tree node) +- Custom solution: User clicks Complete → ends session + +#### B.12: Update Session Export +**File:** `frontend/src/components/session/ExportPreviewModal.tsx` or `backend/app/api/endpoints/sessions.py` Ensure custom steps are included in export with clear marking: @@ -448,7 +581,7 @@ Ensure custom steps are included in export with clear marking: Instructions: ... ``` -#### B.12: Update Session Types +#### B.13: Update Session Types **File:** `frontend/src/types/index.ts` Add: @@ -487,26 +620,29 @@ export interface CustomStepDraft { | 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 | +| `frontend/components/tree-editor/ValidationSummary.tsx` | #1 | Error/warning display | +| `frontend/api/steps.ts` | #10 | Steps API client | +| `frontend/api/stepCategories.ts` | #10 | Categories API client | +| `frontend/types/step.ts` | #10 | Step TypeScript types | +| `frontend/components/step-library/StepCard.tsx` | #10 | Step list item card | +| `frontend/components/step-library/StepDetailModal.tsx` | #10 | Step preview modal | +| `frontend/components/step-library/StepLibraryBrowser.tsx` | #10 | Main browser component | +| `frontend/components/step-library/StepForm.tsx` | #9 | Step creation form | +| `frontend/components/step-library/CustomStepModal.tsx` | #9 | Tabbed modal wrapper | +| `backend/alembic/versions/XXXX_add_custom_steps.py` | #8 | Add custom_steps to sessions | -### Modified Files (5) +### Modified Files (6) | 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 | +| `frontend/store/treeEditorStore.ts` | #1 | Add circular reference detection | +| `frontend/pages/TreeEditorPage.tsx` | #1 | Integrate validation UI | +| `frontend/components/tree-editor/NodeList.tsx` | #1 | Node error indicators | +| `frontend/pages/TreeNavigationPage.tsx` | #8 | Add custom step button + rendering | +| `frontend/api/index.ts` | #10 | Export new API clients | +| `frontend/types/index.ts` | #8 | Add CustomStep types | +| `backend/app/schemas/session.py` | #8 | Add custom_steps field | +| `backend/app/api/endpoints/sessions.py` | #8 | Handle custom_steps in update | --- @@ -536,8 +672,9 @@ Workstream A Workstream B ───────────── ───────────── Testing & polish B.8 StepForm B.9 CustomStepModal - B.10 TreeNavigationPage integration - B.11-12 Export & types updates + B.10 Backend custom steps support (migration + schemas) + B.11 TreeNavigationPage integration + B.12-13 Export & types updates ``` --- @@ -578,13 +715,54 @@ Testing & polish B.8 StepForm --- -## Questions to Resolve Before Starting +## Design Decisions (Resolved) -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 +### 1. Custom Steps Persistence ✅ +**Decision:** Separate `custom_steps` JSONB field in sessions table -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 +**Rationale:** +- Clean separation of concerns (decisions track actions taken, custom_steps store step content) +- Enables session resuming with custom steps intact +- Easier to query and export custom steps separately +- Follows normalized data structure patterns -3. **Rate limiting**: Should step creation have rate limiting to prevent spam? - - *Recommendation*: Backend concern, out of scope for this plan +**Implementation:** Task B.10 adds migration + schema updates + +### 2. Custom Step Navigation Flow ✅ +**Decision:** Full step type support (decision/action/solution) + +**Rationale:** +- Real-world troubleshooting requires branching after custom actions +- Example: "Try clearing cache" (action) → "Did it work?" (decision) +- Consistent with tree structure mental model +- Maximum flexibility for engineers + +**Implementation:** Task B.11 renders custom steps based on `step_type` + +### 3. Validation Warning UX ✅ +**Decision:** Inline dismissible warnings, no confirmation modal + +**Rationale:** +- Warnings are informational, not critical +- Orphan nodes might be intentional (work in progress) +- Trust users to manage their own tree quality +- Simpler UX, fewer clicks +- Draft feature (Issue #25) handles "save incomplete work" use case + +**Implementation:** Task A.2-A.3 show warnings in ValidationSummary, don't block save + +--- + +## Future Enhancements (Out of Scope) + +1. **Draft Trees Feature** - Documented in Issue #25 + - Save incomplete trees without validation errors blocking + - Planned for Phase 3 after Step Library is complete + +2. **Standalone Step Library Page** - `/steps` route + - Browse/manage personal step library outside of active sessions + - Add after Issue #10 is complete and usage patterns are understood + +3. **Rate Limiting** - Backend concern + - Prevent step library spam + - Add if abuse is observed in production diff --git a/docs/plans/2026-02-03-draft-trees-feature.md b/docs/plans/2026-02-03-draft-trees-feature.md new file mode 100644 index 00000000..9ea8faf1 --- /dev/null +++ b/docs/plans/2026-02-03-draft-trees-feature.md @@ -0,0 +1,520 @@ +# Feature Design: Draft Trees & Custom Steps + +> **Date:** February 3, 2026 +> **Status:** Planned for Phase 3 +> **Related Issues:** TBD +> **Dependencies:** Tree Editor Validation UI (Issue #1) + +--- + +## Overview + +Enable users to save incomplete trees and custom steps as drafts, allowing them to return later to finish editing without validation errors blocking their work. + +**Use Cases:** +- Building a complex tree over multiple sessions +- Starting a tree without all solution nodes defined +- Experimenting with tree structures before publishing +- Saving custom steps for later refinement + +--- + +## Motivation + +Currently, validation errors block saving trees. This creates friction when: +- User wants to save progress on a complex tree (10+ nodes) +- User is interrupted mid-editing and needs to save incomplete work +- User wants to experiment without committing to a "valid" structure +- User creates a custom step during troubleshooting but wants to refine it later + +**Goal:** Allow users to save work-in-progress without bypassing quality checks for published trees. + +--- + +## Design + +### Database Changes + +#### Trees Table +Add `status` column to `trees` table: + +```sql +ALTER TABLE trees +ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'published'; + +ALTER TABLE trees +ADD CONSTRAINT trees_status_check +CHECK (status IN ('draft', 'published')); + +CREATE INDEX idx_trees_status ON trees(status); +``` + +**Statuses:** +- `draft` - Incomplete, may have validation errors, only visible to author +- `published` - Complete, passes validation, visible per sharing settings + +#### Step Library Table +Add `status` column to `step_library` table: + +```sql +ALTER TABLE step_library +ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'published'; + +ALTER TABLE step_library +ADD CONSTRAINT step_library_status_check +CHECK (status IN ('draft', 'published')); + +CREATE INDEX idx_step_library_status ON step_library(status); +``` + +--- + +## API Changes + +### Trees Endpoints + +#### GET /api/v1/trees +Add query parameter: +```python +@router.get("/") +async def list_trees( + include_drafts: bool = False, # NEW + category_id: Optional[UUID] = None, + tags: Optional[str] = None, + # ... existing params +): + """ + List trees. + + By default, only returns published trees. + Set include_drafts=true to include user's own draft trees. + """ +``` + +**Logic:** +- Default: Only return `status='published'` trees +- `include_drafts=true`: Return published trees + current user's drafts +- Never show other users' drafts + +#### POST /api/v1/trees +```python +class TreeCreate(BaseModel): + name: str + description: Optional[str] = None + tree_structure: dict + status: str = "published" # NEW: default to published + # ... existing fields +``` + +**Validation:** +- `status='draft'`: Skip validation, allow saving with errors +- `status='published'`: Run full validation, reject if errors exist + +#### PUT /api/v1/trees/{id} +```python +class TreeUpdate(BaseModel): + name: Optional[str] = None + tree_structure: Optional[dict] = None + status: Optional[str] = None # NEW: allow status change + # ... existing fields +``` + +**Validation:** +- Changing `draft` → `published`: Run validation, reject if errors +- Changing `published` → `draft`: Allow without validation +- Updating draft: Skip validation +- Updating published: Run validation + +#### GET /api/v1/trees/{id}/can-publish +```python +@router.get("/{id}/can-publish") +async def can_publish_tree(id: UUID) -> dict: + """ + Check if a draft tree can be published. + + Returns: + { + "can_publish": bool, + "errors": ValidationError[], + "warnings": ValidationError[] + } + """ +``` + +**Use case:** Frontend calls this before showing "Publish" button to preview errors. + +### Step Library Endpoints + +Same pattern as trees: +- `GET /api/v1/steps?include_drafts=true` +- `POST /api/v1/steps` with `status` field +- `PUT /api/v1/steps/{id}` with status change validation +- `GET /api/v1/steps/{id}/can-publish` + +--- + +## Frontend Changes + +### Tree Library Page + +**Visual Changes:** +```tsx +// Draft badge on tree cards +{tree.status === 'draft' && ( + + Draft + +)} + +// Filter toggle + +``` + +**Default:** Only show published trees +**With "Show my drafts" enabled:** Show published + user's drafts + +### Tree Editor Page + +**Save Button Logic:** + +```tsx +const { canSave, validationErrors, validationWarnings } = useValidation() +const isDraft = tree.status === 'draft' + +// Two-button layout when draft has errors +{isDraft && validationErrors.length > 0 ? ( + <> + + + +) : ( + +)} +``` + +**Validation Display:** + +```tsx +// Show validation summary for drafts +{isDraft && ( + +)} + +// Show validation summary for published (blocks save) +{!isDraft && validationErrors.length > 0 && ( + +)} +``` + +**Status Badge in Editor:** +```tsx +
+

{tree.name}

+ {tree.status === 'draft' && ( + + Draft + + )} +
+``` + +### Tree Navigation Page + +**Draft trees behavior:** +- Can be selected and used for navigation +- Show warning banner: "⚠️ This is a draft tree and may be incomplete" +- Allow session creation (useful for testing draft trees) + +### Step Library Browser + +**Draft custom steps:** +```tsx +// In CustomStepModal, add checkbox: + + +// In StepLibraryBrowser, filter control: + +``` + +--- + +## User Flows + +### Flow 1: Save Draft Tree + +1. User creates new tree, clicks "Create Tree" +2. Tree Editor opens, user adds nodes +3. User clicks "Save Draft" (or just "Save" if creating as draft from start) +4. Validation runs but doesn't block—tree saved with `status='draft'` +5. Success message: "Draft saved. Publish when ready." + +### Flow 2: Publish Draft Tree + +1. User opens draft tree in editor +2. ValidationSummary shows errors/warnings +3. User fixes all errors +4. "Publish" button becomes enabled +5. User clicks "Publish" +6. Tree status changes to `published` +7. Success message: "Tree published and available to team" + +### Flow 3: Unpublish Tree + +1. User opens published tree +2. Clicks "Convert to Draft" (in dropdown menu) +3. Confirmation modal: "This will hide the tree from others. Continue?" +4. Tree status changes to `draft` +5. Tree removed from other users' tree library view + +### Flow 4: Save Draft Custom Step + +1. User adds custom step during navigation +2. In CustomStepModal, checks "Save as draft" +3. Step saved to personal library with `status='draft'` +4. Step inserted into current session (works like published step) +5. Later, user opens "My Steps" page, refines draft, publishes + +--- + +## Validation Rules + +### Draft Trees +- ✅ Can save with missing required fields +- ✅ Can save with orphan nodes +- ✅ Can save with circular references +- ✅ Can save without solution nodes +- ❌ Still validate JSONB structure (prevent corrupted data) + +### Published Trees +- ❌ Cannot save with any validation errors +- ⚠️ Can save with warnings (orphan nodes, etc.) +- ✅ Must have at least one solution node +- ✅ Must have valid tree_structure + +### Publishing Transition +- When `draft` → `published`: Run full validation, reject if errors +- Show clear error message: "Cannot publish: 3 errors found. [View Details]" + +--- + +## UI Mockup Descriptions + +### Tree Library Page +``` +┌─────────────────────────────────────────────────┐ +│ Tree Library │ +│ │ +│ [Search...] [Category ▼] [+ New Tree] │ +│ │ +│ ☑ Show my drafts │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ Citrix Connection Issues [DRAFT]│ │ +│ │ Last edited: 2 hours ago │ │ +│ │ 5 nodes · 2 errors │ │ +│ │ [Continue Editing] │ │ +│ └─────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────┐ │ +│ │ Outlook Won't Start │ │ +│ │ Last used: Yesterday │ │ +│ │ 12 nodes · Published │ │ +│ │ [Start Session] │ │ +│ └─────────────────────────────────┘ │ +└─────────────────────────────────────────────────┘ +``` + +### Tree Editor - Draft Mode +``` +┌─────────────────────────────────────────────────┐ +│ Citrix Connection Issues [DRAFT] │ +│ │ +│ ⚠ Validation (2 errors, 1 warning) │ +│ ├─ ❌ Tree must have at least one solution node│ +│ ├─ ❌ Node "Check firewall" is orphaned │ +│ └─ ⚠ Node "Reboot" has no help text │ +│ │ +│ [Node editing area...] │ +│ │ +│ [Cancel] [Save Draft] [Publish] ← disabled │ +└─────────────────────────────────────────────────┘ +``` + +### Tree Editor - Ready to Publish +``` +┌─────────────────────────────────────────────────┐ +│ Citrix Connection Issues [DRAFT] │ +│ │ +│ ✅ No validation errors │ +│ ⚠ 1 warning: Node "Reboot" has no help text │ +│ │ +│ [Node editing area...] │ +│ │ +│ [Cancel] [Save Draft] [Publish] ← enabled │ +└─────────────────────────────────────────────────┘ +``` + +--- + +## Implementation Phases + +### Phase 1: Backend Foundation +- [ ] Add `status` column to `trees` table +- [ ] Update Trees API endpoints (list, create, update) +- [ ] Add `can_publish` endpoint +- [ ] Update validation logic to respect status +- [ ] Write tests for draft/publish transitions + +### Phase 2: Frontend - Trees +- [ ] Update Tree Library to filter by status +- [ ] Add "Show my drafts" toggle +- [ ] Update Tree Editor save button logic +- [ ] Add "Publish" button for drafts +- [ ] Add status badge to tree cards and editor +- [ ] Add confirmation modal for unpublishing + +### Phase 3: Backend - Step Library +- [ ] Add `status` column to `step_library` table +- [ ] Update Step Library API endpoints +- [ ] Add `can_publish` endpoint for steps +- [ ] Write tests + +### Phase 4: Frontend - Step Library +- [ ] Update CustomStepModal with draft option +- [ ] Update StepLibraryBrowser to filter drafts +- [ ] Add "Publish" action to step detail modal +- [ ] Add status badge to step cards + +--- + +## Testing Checklist + +### Trees +- [ ] Create draft tree with validation errors → saves successfully +- [ ] Try to publish draft with errors → rejected with clear message +- [ ] Fix errors, publish draft → becomes published +- [ ] Edit published tree, introduce error → cannot save +- [ ] Convert published tree to draft → hidden from others +- [ ] Other users cannot see my draft trees +- [ ] Draft trees show in "My Trees" when filter enabled + +### Step Library +- [ ] Save custom step as draft → appears in "My Steps" with badge +- [ ] Draft steps not shown in team/public views +- [ ] Publish draft step → validation runs +- [ ] Draft step can be inserted into session (works like published) +- [ ] Edit draft step, publish when ready + +### Edge Cases +- [ ] Create draft → close browser → reopen → draft still there +- [ ] Two users editing same tree: User A drafts, User B can't see draft +- [ ] Published tree with 100 uses → convert to draft → sessions still work +- [ ] Delete draft tree → no orphaned sessions + +--- + +## Open Questions + +1. **Auto-save for drafts?** + - Should drafts auto-save every N seconds like Google Docs? + - Recommendation: Phase 5 enhancement, manual save for now + +2. **Draft expiration?** + - Should drafts older than 30 days be auto-deleted? + - Recommendation: No expiration for now, add later if storage becomes issue + +3. **Version history for drafts?** + - Should we track versions of draft edits? + - Recommendation: Out of scope, add with general version control feature later + +4. **Team drafts?** + - Should teams be able to collaborate on draft trees? + - Recommendation: Phase 6 - "shared drafts" with permissions + +--- + +## Migration Plan + +### Database Migration +```python +# Migration: add_tree_status_column +def upgrade(): + # Add column with default 'published' for existing trees + op.add_column('trees', sa.Column('status', sa.String(20), nullable=False, server_default='published')) + op.create_check_constraint('trees_status_check', 'trees', "status IN ('draft', 'published')") + op.create_index('idx_trees_status', 'trees', ['status']) + + # Same for step_library + op.add_column('step_library', sa.Column('status', sa.String(20), nullable=False, server_default='published')) + op.create_check_constraint('step_library_status_check', 'step_library', "status IN ('draft', 'published')") + op.create_index('idx_step_library_status', 'step_library', ['status']) +``` + +**Rollback safety:** All existing trees default to `published`, no data loss. + +--- + +## Success Metrics + +- **Adoption:** % of users who create at least one draft tree per month +- **Completion:** % of drafts that get published (vs abandoned) +- **Time savings:** Avg time to create complex trees (before/after draft feature) +- **Error reduction:** % reduction in "cannot save" frustration incidents + +**Target:** 60% of users with 5+ trees use draft feature within 2 months of launch. + +--- + +## Related Features + +- **Tree Editor Validation** (Issue #1) - Prerequisite +- **Step Library Browser** (Issue #10) - Will benefit from draft steps +- **Tree Forking** (Issue #13) - Forked trees could start as drafts +- **Tree Sharing** (Issue #16) - Published status required to share + +--- + +## Notes + +- Draft feature inspired by Gmail drafts, Google Docs, Notion page publishing +- Key principle: **Never lose work** - always allow saving, validate on publish +- This feature enables iterative tree building, which is critical for complex MSP workflows