Add tree organization system with categories, tags, and folders
Features: - Categories: Global and team-specific tree categorization (admin-managed) - Tags: Flexible tree tagging with autocomplete (author + admin) - User folders: Personal tree collections with subfolder support - Hierarchical structure (max 3 levels deep) - Right-click context menu for folder management - Cascade delete for subfolders - Filter trees by category, tags, and folder in library view Backend: - New models: Category, Tag, UserFolder with relationships - New API endpoints for categories, tags, and folders - Tree organization migrations (005, 006) Frontend: - FolderSidebar with hierarchical folder tree - FolderEditModal for create/edit with color picker - AddToFolderMenu for quick tree organization - TagInput with autocomplete and TagBadges display - Updated TreeMetadataForm and TreeLibraryPage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
563
CLAUDE.md
Normal file
563
CLAUDE.md
Normal file
@@ -0,0 +1,563 @@
|
||||
# CLAUDE.md - Patherly Project Context
|
||||
|
||||
> **Purpose:** This file provides Claude Code with essential context for working on the Patherly project.
|
||||
> **Last Updated:** February 2, 2026
|
||||
|
||||
---
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Patherly** is a troubleshooting decision tree application designed for MSP engineers. It guides engineers through proven troubleshooting paths, captures decisions and notes automatically, and generates professional ticket documentation.
|
||||
|
||||
**Tagline:** "Take the path MOST traveled."
|
||||
|
||||
**Primary User:** Michael Chihlas - Senior Systems Engineer at an MSP
|
||||
|
||||
**Goal:** Michael uses this tool for 50% of his tickets within 3 months.
|
||||
|
||||
---
|
||||
|
||||
## Current State
|
||||
|
||||
- **Phase:** Phase 2 - Tree Editor (In Progress)
|
||||
- **Backend:** Complete (18 API endpoints, 40+ integration tests, all passing)
|
||||
- **Frontend:** Core features complete, Tree Editor functional
|
||||
- **Database:** PostgreSQL with Docker (container name: `patherly_postgres`)
|
||||
|
||||
### What's Complete
|
||||
- User authentication (JWT, register, login, refresh, invite codes)
|
||||
- Trees CRUD with full-text search
|
||||
- Sessions tracking with decisions
|
||||
- Export API (Markdown, Text, HTML)
|
||||
- Tree Editor with form-based editing and visual preview
|
||||
- Dark/Light theme toggle
|
||||
- Markdown rendering in session player and node editor
|
||||
- 7 comprehensive seed decision trees
|
||||
- **Tree Organization System:**
|
||||
- Categories (global + team-specific, admin-managed)
|
||||
- Tags (author + admin managed, autocomplete)
|
||||
- User folders (personal tree collections)
|
||||
- Subfolder hierarchy (max 3 levels deep)
|
||||
- Right-click context menu for edit/delete/add subfolder
|
||||
- Cascade delete for subfolders
|
||||
- Team admin role with scoped permissions
|
||||
- Filter trees by category, tags, and folders
|
||||
|
||||
### What's In Progress
|
||||
- User preferences (export format default)
|
||||
- Deployment to Railway/Render
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
### Backend
|
||||
- **Framework:** Python FastAPI
|
||||
- **Database:** PostgreSQL 16 (async via SQLAlchemy 2.0 + asyncpg)
|
||||
- **Migrations:** Alembic
|
||||
- **Auth:** JWT tokens (python-jose) + bcrypt passwords
|
||||
- **Validation:** Pydantic v2
|
||||
|
||||
### Frontend
|
||||
- **Framework:** React 19 + Vite + TypeScript
|
||||
- **Styling:** Tailwind CSS v3
|
||||
- **State:** Zustand (with immer + zundo for undo/redo)
|
||||
- **Routing:** React Router v7
|
||||
- **API Client:** Axios with token interceptors
|
||||
- **Icons:** Lucide React
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
patherly/
|
||||
├── backend/
|
||||
│ ├── app/
|
||||
│ │ ├── main.py # FastAPI entry point
|
||||
│ │ ├── api/
|
||||
│ │ │ ├── endpoints/
|
||||
│ │ │ │ ├── auth.py # Auth: register, login, refresh, logout
|
||||
│ │ │ │ ├── trees.py # Trees CRUD + search
|
||||
│ │ │ │ ├── sessions.py # Sessions + export
|
||||
│ │ │ │ └── invite.py # Invite code management
|
||||
│ │ │ ├── deps.py # Auth dependencies
|
||||
│ │ │ └── router.py
|
||||
│ │ ├── core/
|
||||
│ │ │ ├── config.py # Settings (pydantic-settings)
|
||||
│ │ │ ├── database.py # Async SQLAlchemy
|
||||
│ │ │ ├── security.py # JWT + password hashing
|
||||
│ │ │ ├── logging_config.py # Structured logging
|
||||
│ │ │ └── middleware.py # Request logging
|
||||
│ │ ├── models/ # SQLAlchemy models
|
||||
│ │ │ ├── user.py # is_team_admin field added
|
||||
│ │ │ ├── team.py
|
||||
│ │ │ ├── tree.py # JSONB tree_structure + category_id, tags
|
||||
│ │ │ ├── session.py # JSONB path_taken, decisions
|
||||
│ │ │ ├── attachment.py
|
||||
│ │ │ ├── invite_code.py
|
||||
│ │ │ ├── category.py # TreeCategory model (NEW)
|
||||
│ │ │ ├── tag.py # TreeTag model (NEW)
|
||||
│ │ │ └── folder.py # UserFolder model (NEW)
|
||||
│ │ └── schemas/ # Pydantic schemas
|
||||
│ ├── alembic/ # Database migrations
|
||||
│ ├── scripts/
|
||||
│ │ ├── seed_data.py
|
||||
│ │ └── seed_trees.py # 7 comprehensive trees
|
||||
│ ├── tests/ # pytest integration tests
|
||||
│ ├── docker-compose.yml # PostgreSQL container
|
||||
│ ├── requirements.txt
|
||||
│ └── .env # Environment variables
|
||||
│
|
||||
├── frontend/
|
||||
│ ├── src/
|
||||
│ │ ├── main.tsx
|
||||
│ │ ├── App.tsx
|
||||
│ │ ├── router.tsx
|
||||
│ │ ├── api/ # Axios API client
|
||||
│ │ │ ├── client.ts # Axios instance with interceptors
|
||||
│ │ │ ├── auth.ts
|
||||
│ │ │ ├── trees.ts
|
||||
│ │ │ └── sessions.ts
|
||||
│ │ ├── store/
|
||||
│ │ │ ├── authStore.ts # Zustand auth state
|
||||
│ │ │ ├── themeStore.ts # Dark/light theme
|
||||
│ │ │ └── treeEditorStore.ts # Tree editor state (immer + zundo)
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── common/ # Modal, ErrorBoundary, ThemeToggle
|
||||
│ │ │ ├── layout/ # AppLayout, ProtectedRoute
|
||||
│ │ │ ├── tree-editor/ # Tree editor components
|
||||
│ │ │ ├── tree-preview/ # Visual tree preview
|
||||
│ │ │ └── ui/ # MarkdownContent
|
||||
│ │ ├── pages/
|
||||
│ │ │ ├── LoginPage.tsx
|
||||
│ │ │ ├── RegisterPage.tsx
|
||||
│ │ │ ├── TreeLibraryPage.tsx
|
||||
│ │ │ ├── TreeNavigationPage.tsx # Core feature
|
||||
│ │ │ ├── TreeEditorPage.tsx
|
||||
│ │ │ ├── SessionHistoryPage.tsx
|
||||
│ │ │ └── SessionDetailPage.tsx
|
||||
│ │ ├── types/ # TypeScript interfaces
|
||||
│ │ └── lib/utils.ts # cn() utility for Tailwind
|
||||
│ ├── package.json
|
||||
│ ├── tailwind.config.js
|
||||
│ └── vite.config.ts
|
||||
│
|
||||
├── CLAUDE.md # This file
|
||||
├── CURRENT-STATE.md # Quick status reference
|
||||
├── LESSONS-LEARNED.md # Bugs and fixes (READ THIS!)
|
||||
├── PROGRESS.md # Detailed progress log
|
||||
├── 01-PROJECT-OVERVIEW.md # Vision and goals
|
||||
├── 02-TECHNICAL-ARCHITECTURE.md # System design, API specs
|
||||
├── 03-DEVELOPMENT-ROADMAP.md # Phases and timeline
|
||||
├── 04-FEATURE-SPECIFICATIONS.md # Feature details
|
||||
├── 05-QUESTIONS-AND-ACTION-ITEMS.md
|
||||
└── PHASE-2.5-PERSONAL-BRANCHING.md # Future feature spec
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Start Development Environment
|
||||
|
||||
```powershell
|
||||
# Terminal 1: Start PostgreSQL
|
||||
docker start patherly_postgres
|
||||
|
||||
# Terminal 2: Backend
|
||||
cd C:\Dev\Projects\patherly\patherly\backend
|
||||
.\venv\Scripts\Activate
|
||||
uvicorn app.main:app --reload
|
||||
|
||||
# Terminal 3: Frontend
|
||||
cd C:\Dev\Projects\patherly\patherly\frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### URLs
|
||||
- Frontend: http://localhost:5173
|
||||
- Backend API: http://localhost:8000
|
||||
- API Docs: http://localhost:8000/api/docs
|
||||
|
||||
### Run Tests
|
||||
```powershell
|
||||
cd C:\Dev\Projects\patherly\patherly\backend
|
||||
.\venv\Scripts\Activate
|
||||
pytest
|
||||
```
|
||||
|
||||
### Run Seed Scripts
|
||||
```powershell
|
||||
cd C:\Dev\Projects\patherly\patherly\backend
|
||||
.\venv\Scripts\Activate
|
||||
pip install httpx # Required for seed scripts
|
||||
python -m scripts.seed_trees
|
||||
```
|
||||
|
||||
### Database Operations
|
||||
```powershell
|
||||
# Run migrations
|
||||
cd backend
|
||||
alembic upgrade head
|
||||
|
||||
# Create new migration
|
||||
alembic revision --autogenerate -m "Description"
|
||||
|
||||
# Access PostgreSQL (no local psql needed)
|
||||
docker exec -it patherly_postgres psql -U postgres -d patherly
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critical Lessons Learned
|
||||
|
||||
**ALWAYS read [LESSONS-LEARNED.md](LESSONS-LEARNED.md) before making changes!**
|
||||
|
||||
### DateTime Handling (Critical)
|
||||
```python
|
||||
# CORRECT - Always use timezone-aware datetimes
|
||||
from datetime import datetime, timezone
|
||||
from sqlalchemy import DateTime
|
||||
|
||||
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
|
||||
|
||||
# WRONG - Never use this
|
||||
datetime.utcnow() # Deprecated, returns naive datetime
|
||||
```
|
||||
|
||||
### React State: Don't Store Object Snapshots
|
||||
```tsx
|
||||
// WRONG - Snapshot won't update when store changes
|
||||
const [editingNode, setEditingNode] = useState<TreeStructure | null>(null)
|
||||
|
||||
// CORRECT - Store ID only, fetch current object each render
|
||||
const [editingNodeId, setEditingNodeId] = useState<string | null>(null)
|
||||
const editingNode = editingNodeId ? findNode(editingNodeId) : null
|
||||
```
|
||||
|
||||
### Modal Draft State: Don't Overwrite Store-Managed Fields
|
||||
```tsx
|
||||
// WRONG - Overwrites children with stale snapshot
|
||||
const handleSave = () => {
|
||||
updateNode(node.id, draft) // draft.children is stale!
|
||||
}
|
||||
|
||||
// CORRECT - Exclude store-managed fields
|
||||
const handleSave = () => {
|
||||
const { children, ...draftWithoutChildren } = draft
|
||||
updateNode(node.id, draftWithoutChildren)
|
||||
}
|
||||
```
|
||||
|
||||
### Database Name
|
||||
- Database name is `patherly` (not `decision_tree`)
|
||||
- Update `.env` if you see the old name
|
||||
|
||||
### Virtual Environment
|
||||
- Always check for `(venv)` prefix before running pip
|
||||
- Don't use `--break-system-packages` when venv is active
|
||||
|
||||
### PostgreSQL NULL Casting for UUID Columns
|
||||
```sql
|
||||
-- WRONG - PostgreSQL infers NULL as text type
|
||||
INSERT INTO tree_tags (name, slug, team_id)
|
||||
SELECT 'tag', 'slug', NULL as team_id -- Error: column is uuid but expression is text
|
||||
|
||||
-- CORRECT - Explicitly cast NULL to uuid
|
||||
INSERT INTO tree_tags (name, slug, team_id)
|
||||
SELECT 'tag', 'slug', NULL::uuid as team_id -- Works!
|
||||
```
|
||||
Always use `NULL::uuid` when inserting NULL values into UUID columns in raw SQL.
|
||||
|
||||
### SQLAlchemy Async: Avoid Lazy Loading on New Objects
|
||||
```python
|
||||
# WRONG - Triggers lazy load which fails in async context
|
||||
new_tree = Tree(...)
|
||||
db.add(new_tree)
|
||||
await db.flush()
|
||||
new_tree.tags.append(tag) # MissingGreenlet error!
|
||||
|
||||
# CORRECT - Use direct SQL for junction tables
|
||||
from app.models.tag import tree_tag_assignments
|
||||
await db.execute(
|
||||
tree_tag_assignments.insert().values(
|
||||
tree_id=new_tree.id,
|
||||
tag_id=tag.id
|
||||
)
|
||||
)
|
||||
```
|
||||
Accessing relationships on newly created objects triggers lazy loading, which fails in async SQLAlchemy. Use direct SQL inserts for junction tables instead.
|
||||
|
||||
### React Router: Clear Dirty State Before Navigation
|
||||
```tsx
|
||||
// WRONG - Navigation triggers before dirty flag is cleared
|
||||
const newTree = await treesApi.create(data)
|
||||
navigate(`/trees/${newTree.id}/edit`) // Blocker fires here!
|
||||
markSaved() // Too late
|
||||
|
||||
// CORRECT - Clear dirty state first
|
||||
const newTree = await treesApi.create(data)
|
||||
markSaved() // Clear isDirty first
|
||||
navigate(`/trees/${newTree.id}/edit`) // Blocker won't fire
|
||||
```
|
||||
When using `useBlocker` for unsaved changes, always clear the dirty flag before programmatic navigation.
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints Reference
|
||||
|
||||
### Authentication
|
||||
```
|
||||
POST /api/v1/auth/register - Register (requires invite code by default)
|
||||
POST /api/v1/auth/login - Login (form data)
|
||||
POST /api/v1/auth/login/json - Login (JSON body)
|
||||
POST /api/v1/auth/refresh - Refresh access token
|
||||
GET /api/v1/auth/me - Get current user
|
||||
POST /api/v1/auth/logout - Logout
|
||||
```
|
||||
|
||||
### Trees
|
||||
```
|
||||
GET /api/v1/trees - List trees (filters: category_id, tags, folder_id)
|
||||
POST /api/v1/trees - Create tree (supports tags, category_id)
|
||||
GET /api/v1/trees/categories - Get legacy string categories
|
||||
GET /api/v1/trees/search - Full-text search
|
||||
GET /api/v1/trees/{id} - Get tree (includes tags, category_info)
|
||||
PUT /api/v1/trees/{id} - Update tree
|
||||
DELETE /api/v1/trees/{id} - Soft delete
|
||||
```
|
||||
|
||||
### Categories (NEW)
|
||||
```
|
||||
GET /api/v1/categories - List categories (global + user's team)
|
||||
POST /api/v1/categories - Create category (team/global admin)
|
||||
GET /api/v1/categories/{id} - Get category
|
||||
PUT /api/v1/categories/{id} - Update category
|
||||
DELETE /api/v1/categories/{id} - Soft delete category
|
||||
```
|
||||
|
||||
### Tags (NEW)
|
||||
```
|
||||
GET /api/v1/tags - List tags (global + user's team)
|
||||
GET /api/v1/tags/search - Autocomplete search
|
||||
POST /api/v1/tags - Create tag
|
||||
GET /api/v1/tags/{id} - Get tag
|
||||
GET /api/v1/tags/trees/{id} - Get tree's tags
|
||||
POST /api/v1/tags/trees/{id} - Add tags to tree
|
||||
PUT /api/v1/tags/trees/{id} - Replace tree's tags
|
||||
DELETE /api/v1/tags/trees/{id}/{slug} - Remove tag from tree
|
||||
```
|
||||
|
||||
### Folders (NEW)
|
||||
```
|
||||
GET /api/v1/folders - List user's folders (includes parent_id)
|
||||
POST /api/v1/folders - Create folder (supports parent_id for subfolders)
|
||||
GET /api/v1/folders/{id} - Get folder
|
||||
PUT /api/v1/folders/{id} - Update folder (supports moving via parent_id)
|
||||
DELETE /api/v1/folders/{id} - Delete folder (cascades to subfolders)
|
||||
POST /api/v1/folders/reorder - Reorder folders
|
||||
POST /api/v1/folders/{id}/trees - Add tree to folder
|
||||
GET /api/v1/folders/{id}/trees - Get folder's tree IDs
|
||||
DELETE /api/v1/folders/{id}/trees/{tree_id} - Remove tree from folder
|
||||
```
|
||||
|
||||
**Folder hierarchy constraints:**
|
||||
- Max nesting depth: 3 levels (root → child → grandchild)
|
||||
- Same folder name allowed under different parents
|
||||
- Moving folders validates cycle prevention
|
||||
|
||||
### Sessions
|
||||
```
|
||||
GET /api/v1/sessions - List user's sessions
|
||||
POST /api/v1/sessions - Start session
|
||||
GET /api/v1/sessions/{id} - Get session
|
||||
PUT /api/v1/sessions/{id} - Update session
|
||||
POST /api/v1/sessions/{id}/complete - Complete session
|
||||
POST /api/v1/sessions/{id}/export - Export (md/txt/html)
|
||||
```
|
||||
|
||||
### Invite Codes
|
||||
```
|
||||
GET /api/v1/invite-codes - List codes (admin)
|
||||
POST /api/v1/invite-codes - Create code (admin)
|
||||
GET /api/v1/invite-codes/validate/{code} - Validate code
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Models
|
||||
|
||||
### Tree Structure (JSONB)
|
||||
```typescript
|
||||
interface TreeStructure {
|
||||
id: string
|
||||
type: 'decision' | 'action' | 'solution'
|
||||
|
||||
// Decision nodes
|
||||
question?: string
|
||||
help_text?: string
|
||||
options?: Array<{
|
||||
id: string
|
||||
label: string
|
||||
next_node_id?: string
|
||||
}>
|
||||
|
||||
// Action nodes
|
||||
title?: string
|
||||
description?: string
|
||||
commands?: string[]
|
||||
next_node_id?: string
|
||||
|
||||
// Solution nodes
|
||||
title?: string
|
||||
description?: string
|
||||
steps?: string[]
|
||||
|
||||
// All nodes can have children
|
||||
children?: TreeStructure[]
|
||||
}
|
||||
```
|
||||
|
||||
### Session Decisions (JSONB)
|
||||
```typescript
|
||||
interface Decision {
|
||||
node_id: string
|
||||
question?: string
|
||||
answer: string
|
||||
notes?: string
|
||||
timestamp: string // ISO string, not datetime object
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend Patterns
|
||||
|
||||
### State Management
|
||||
- **Auth:** `useAuthStore` - Zustand with localStorage persistence
|
||||
- **Theme:** `useThemeStore` - Dark/light/system preference
|
||||
- **Tree Editor:** `useTreeEditorStore` - Zustand + immer + zundo (undo/redo)
|
||||
|
||||
### Component Guidelines
|
||||
- Use `cn()` from `@/lib/utils` for Tailwind class merging
|
||||
- Use Lucide icons (no `title` prop - wrap in `<span>` instead)
|
||||
- Modals: Use fixed header/footer with scrollable body
|
||||
- Forms: Show field-level validation errors
|
||||
|
||||
### API Client Pattern
|
||||
```typescript
|
||||
import api from '@/api/client'
|
||||
|
||||
// Token refresh handled automatically by interceptor
|
||||
const response = await api.get('/api/v1/trees')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a New API Endpoint
|
||||
|
||||
1. Create route in `backend/app/api/endpoints/`
|
||||
2. Add to router in `backend/app/api/router.py`
|
||||
3. Create/update Pydantic schemas in `backend/app/schemas/`
|
||||
4. Add tests in `backend/tests/`
|
||||
5. Update API client in `frontend/src/api/`
|
||||
|
||||
### Adding a New Page
|
||||
|
||||
1. Create page component in `frontend/src/pages/`
|
||||
2. Add route in `frontend/src/router.tsx`
|
||||
3. Add navigation link in `AppLayout.tsx` if needed
|
||||
|
||||
### Modifying Database Schema
|
||||
|
||||
1. Update model in `backend/app/models/`
|
||||
2. Create migration: `alembic revision --autogenerate -m "description"`
|
||||
3. Review generated migration file
|
||||
4. Apply: `alembic upgrade head`
|
||||
|
||||
---
|
||||
|
||||
## Coding Standards
|
||||
|
||||
### Python (Backend)
|
||||
- Use type hints everywhere
|
||||
- Use async/await for database operations
|
||||
- Use Pydantic for validation
|
||||
- Log with correlation IDs for tracing
|
||||
- Always use `DateTime(timezone=True)` for timestamps
|
||||
|
||||
### TypeScript (Frontend)
|
||||
- Enable strict mode (when ready)
|
||||
- Use TypeScript interfaces for all data structures
|
||||
- Prefer `const` over `let`
|
||||
- Use functional components with hooks
|
||||
- Extract reusable logic into custom hooks
|
||||
|
||||
### Git
|
||||
- Commit message format: `type: description`
|
||||
- Types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`
|
||||
- Always include `Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>`
|
||||
|
||||
---
|
||||
|
||||
## Future Roadmap
|
||||
|
||||
### Phase 2.5 (Planned)
|
||||
- Personal tree branching (add custom steps during sessions)
|
||||
- Step library with categories, tags, and ratings
|
||||
- Tree forking and sharing
|
||||
|
||||
### Phase 3 (Planned)
|
||||
- File attachments (screenshots, logs)
|
||||
- Offline mode (Service Workers + IndexedDB)
|
||||
- Client context system
|
||||
- Analytics dashboard
|
||||
|
||||
### Phase 4 (Planned)
|
||||
- API & integrations (ConnectWise, Kaseya)
|
||||
- PowerShell automation execution
|
||||
- Enterprise features (SSO, white-labeling)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Backend won't start
|
||||
1. Check Docker: `docker ps` - is `patherly_postgres` running?
|
||||
2. Check `.env` - is DATABASE_URL correct (`patherly` not `decision_tree`)?
|
||||
3. Check venv: is `(venv)` prefix showing?
|
||||
|
||||
### Frontend compile errors
|
||||
1. Check `frontend/src/lib/utils.ts` exists (provides `cn()` function)
|
||||
2. Run `npm install` to ensure dependencies are installed
|
||||
|
||||
### Tests failing
|
||||
1. Create test database: `docker exec -it patherly_postgres psql -U postgres -c "CREATE DATABASE patherly_test;"`
|
||||
2. Install dev deps: `pip install -r requirements-dev.txt`
|
||||
3. Ensure pytest-asyncio version: `pip install pytest-asyncio==0.24.0`
|
||||
|
||||
### API 500 errors
|
||||
1. Check server logs for datetime errors (timezone issue)
|
||||
2. Ensure all datetimes use `datetime.now(timezone.utc)`
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| What | Where |
|
||||
|------|-------|
|
||||
| API Docs | http://localhost:8000/api/docs |
|
||||
| Current Status | [CURRENT-STATE.md](CURRENT-STATE.md) |
|
||||
| Bug Fixes | [LESSONS-LEARNED.md](LESSONS-LEARNED.md) |
|
||||
| Feature Specs | [04-FEATURE-SPECIFICATIONS.md](04-FEATURE-SPECIFICATIONS.md) |
|
||||
| Phase 2.5 Spec | [PHASE-2.5-PERSONAL-BRANCHING.md](PHASE-2.5-PERSONAL-BRANCHING.md) |
|
||||
|
||||
---
|
||||
|
||||
## Contact
|
||||
|
||||
**Primary User:** Michael Chihlas
|
||||
**Communication:** GitHub Issues / Direct chat
|
||||
Reference in New Issue
Block a user