# Project Hierarchy Skill A Python skill for fetching and managing project hierarchies from OpenProject, with local caching and search capabilities. ## Overview The **project_hierarchy** skill provides tools to: - Fetch projects from OpenProject API with error handling and recovery - Build and visualize project hierarchies from parent-child relationships - Search and validate projects by identifier or name - Generate breadcrumb paths showing full project lineage - Cache project data locally with configurable TTL ## Use Cases 1. **Project Validation**: Validate that project names/IDs in cost reports match OpenProject 2. **Hierarchy Understanding**: View parent-child relationships between projects 3. **Breadcrumb Generation**: Show full project path (e.g., "Controller → Amphimove → Submodule") 4. **Project Search**: Find projects by partial name or identifier match 5. **Report Enhancement**: Add project context to weekly or cost reports ## Architecture ``` project_hierarchy/ ├── project_manager.py # Core ProjectManager class (11 methods) ├── references/ │ └── projects.json # Cache file (auto-populated) ├── test_project_manager.py # Test script └── SKILL.md # This file ``` ### Core Module: `project_manager.py` Main class: **`ProjectManager`** #### Initialization ```python from project_manager import ProjectManager # Uses default OpenProject URL and local cache manager = ProjectManager() # Or with custom config manager = ProjectManager( api_url="http://ixd.openproject.techmation.com.tw/api/v3/projects", cache_file="references/projects.json", cache_timeout=3600 # 1 hour ) ``` #### Key Methods | Method | Purpose | Returns | |--------|---------|---------| | `fetch_projects(force_refresh=False)` | Fetch from API and cache | `dict` of projects or `None` if failed | | `get_hierarchy_tree()` | Get tree structure of all projects | `dict` with tree nodes | | `get_project(project_id)` | Get single project data | `dict` project info or `None` | | `get_children(project_id)` | Get child projects | `list` of child project identifiers | | `get_parent(project_id)` | Get parent project | `str` parent identifier or `None` | | `get_full_path(project_id)` | Get breadcrumb path | `list` of project identifiers from root | | `get_breadcrumb(project_id)` | Get readable breadcrumb | `str` like "root → child → project" | | `search_projects(query)` | Find projects by name/id | `list` of matching project identifiers | | `validate_project(project_id)` | Check if project exists | `bool` | | `print_hierarchy()` | Print ASCII tree view | `None` (prints to stdout) | ## Usage Examples ### 1. Fetch Projects and Show Hierarchy ```python from project_hierarchy.project_manager import ProjectManager manager = ProjectManager() # Fetch fresh data from OpenProject API projects = manager.fetch_projects(force_refresh=True) print(f"Loaded {len(projects)} projects") # Display hierarchy manager.print_hierarchy() ``` Output: ``` Projects by Hierarchy: Root projects: └─ controller (ID: controller) ├─ amphimove (ID: amphimove) │ └─ submodule (ID: submodule_1) └─ interface (ID: interface) ``` ### 2. Validate Project Names in Reports ```python # When processing a cost report project_name = "amphimove" if manager.validate_project(project_name): print(f"✓ Project '{project_name}' found in OpenProject") else: print(f"✗ Project '{project_name}' not found - check spelling") ``` ### 3. Generate Breadcrumbs for Display ```python # Show full path in report header breadcrumb = manager.get_breadcrumb("submodule_1") print(f"Project: {breadcrumb}") # Output: "Project: controller > amphimove > submodule_1" ``` ### 4. Search for Projects ```python # Find all projects matching "master" results = manager.search_projects("master") for project_id in results: print(f" - {project_id}") ``` ### 5. Get Project Metadata ```python # Access raw project data project = manager.get_project("amphimove") if project: print(f"Name: {project['name']}") print(f"Parent: {project.get('parent')}") print(f"ID: {project['id']}") ``` ## Integration with Other Skills ### With `week_report_gen` Validate projects before generating reports: ```python from project_hierarchy.project_manager import ProjectManager from week_report_gen.generate_report import format_for_weekly_report manager = ProjectManager() # Validate project if not manager.validate_project(cost_data['project']): print(f"Warning: Project '{cost_data['project']}' not found") # Generate report report = format_for_weekly_report(cost_data, ...) ``` ## Data Format ### projects.json Structure ```json { "projects": { "controller": { "id": "123456", "identifier": "controller", "name": "Controller Project", "parent": null }, "amphimove": { "id": "234567", "identifier": "amphimove", "name": "Amphimove Module", "parent": {"identifier": "controller"} } }, "hierarchy": { "controller": ["amphimove"], "amphimove": ["submodule_1"] }, "last_update": "2024-01-15T10:30:00Z" } ``` ## Configuration ### Environment Variables ```bash # Override OpenProject API URL export OPENPROJECT_API_URL="http://ixd.openproject.techmation.com.tw/api/v3/projects" # Cache location (relative to skill directory) export PROJECT_CACHE_FILE="references/projects.json" # Cache timeout in seconds (default: 3600 = 1 hour) export PROJECT_CACHE_TIMEOUT="3600" ``` ### Programmatic Configuration ```python manager = ProjectManager( api_url="http://custom-url/api/v3/projects", cache_file="custom/cache/projects.json", cache_timeout=7200 # 2 hours ) ``` ## Testing Run the test script to verify functionality: ```bash cd d:\bensung\report_skill_expm\.claude\skills\project_hierarchy python test_project_manager.py ``` Expected output: ``` ============================================================ PROJECT MANAGER - TEST ============================================================ ✓ ProjectManager initialized Testing: Fetch projects from OpenProject ------------------------------------------------------------ ✓ Successfully fetched X projects First 5 projects: 1. controller → Controller Project (parent: None) 2. amphimove → Amphimove Module (parent: controller) ... Testing: Get project hierarchy ------------------------------------------------------------ Projects by Hierarchy: Root projects: └─ controller (ID: controller) ├─ amphimove (ID: amphimove) ... ============================================================ ✓ All tests completed! ============================================================ ``` ## Error Handling The ProjectManager handles common failures gracefully: - **API Unreachable**: Uses cached data if available, returns empty dict if no cache - **Invalid Project ID**: Returns `None` with no exception - **Malformed Cache**: Rebuilds from API on next fetch - **Network Errors**: Logged and cached data used as fallback Example: ```python try: projects = manager.fetch_projects(force_refresh=True) except Exception as e: # Use cached data instead projects = manager.get_cached_projects() if not projects: print("No data available - check OpenProject connection") ``` ## Performance Characteristics - **First fetch**: ~500ms - 2s (depends on API and project count) - **Cached lookups**: <1ms - **Hierarchy search**: O(n) where n = project count - **Breadcrumb generation**: O(depth of tree) - **Cache file size**: ~50KB for typical project set (100+ projects) ## Limitations & Notes 1. **Read-Only**: ProjectManager only reads from OpenProject (no create/update) 2. **Parent Relationships**: Only immediate parent is tracked (not full ancestry via hierarchy graph) 3. **Update Frequency**: Default 1-hour cache - adjust `cache_timeout` for real-time needs 4. **Project Identifier**: Searches are case-sensitive for identifiers, case-insensitive for names 5. **API Access**: Requires network access to OpenProject instance ## Future Enhancements - [ ] Add filtering by project status/type - [ ] Support hierarchical queries (all descendants, not just children) - [ ] Export hierarchy as JSON/CSV/SVG - [ ] Add project metadata (status, budget, owner) - [ ] MCP server for sharing with other AI systems - [ ] Real-time sync mode for active monitoring ## Related Skills - **list_user**: User name mapping and team membership - **week_report_gen**: Weekly project reporting with project validation