--- description: Sync OpenProject work packages with current feature specs and tasks — creates milestones, phases, and child tasks as needed. --- ## User Input ```text $ARGUMENTS ``` You **MUST** consider the user input before proceeding (if not empty). ## Outline 1. **Setup**: - **Resolve remote URL**: Run `git remote get-url origin` to get the remote URL. All commit references in this skill MUST use `/commit/` format. Never use bare hashes. - Run `.specify/scripts/powershell/check-prerequisites.ps1 -Json` from repo root and parse FEATURE_DIR, BRANCH, and AVAILABLE_DOCS list. All paths must be absolute. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot"). - **If the script fails** (no feature branch, no specs directory, or prerequisites not met): proceed to step 2a (ad-hoc mode). 2. **Determine development stage**: Check which design artifacts exist in FEATURE_DIR: - `spec.md` exists → at least "specify" stage - `plan.md` exists → at least "plan" stage - `tasks.md` exists → at least "tasks" stage - Tasks with `[X]` checkboxes → "implement" stage (in progress) - **No artifacts at all** → "none" stage (proceed to step 2a) **2a. Ad-hoc mode** (no SpecKit artifacts available): - This handles cases where: - The branch is not a SpecKit feature branch (e.g., `main`, `fix/something`, `hotfix/urgent`) - No `specs/` directory exists for this branch - The user wants to log work to an existing WP without full SpecKit setup - Ask the user: "No SpecKit feature detected for this branch. Which OpenProject work package should I update?" - Accept one of: - A WP ID (e.g., `#10423` or `10423`) - A search term to find the WP (use `mcp__openproject__list_work_packages` with project ID 229 and present matching results) - "new" to create a new work package - "skip" to abort the OP update - If the user provides a WP ID or selects from search results: - Get the commits to be logged: `git log --oneline origin/HEAD..HEAD` (or from user input) - Add a comment to the selected WP with commit links (`/commit/`) and summary - Report what was logged and skip steps 3–8 - If the user says "new" or no search results match: - Ask for a subject (suggest one based on the branch name or recent commit messages) - Ask for a type (Task, Feature, Bug, etc.) — list available types via `mcp__openproject__list_types` if needed - Optionally ask for description, priority, and assignee - Create the WP via `mcp__openproject__create_work_package` with project ID 229 - Then log commits to the newly created WP (same as WP ID flow above) - Report the new WP ID and what was logged, skip steps 3–8 - If the user says "skip": abort and return without error 3. **Load context**: - Read `spec.md` to extract feature title and user stories - If `tasks.md` exists: Read it to extract phases, task counts, OP WP IDs (from `— OP #NNNNN` in phase headers), and task details - Read `CLAUDE.md` for the OpenProject Work Package IDs table and existing mappings 4. **Find or create the Milestone work package**: - Extract the feature number and name from the branch name (e.g., `001-ai-etl-platform`) - Search OpenProject for an existing Milestone WP matching this feature: - Use `mcp__openproject__list_work_packages` with project ID 229 and filter by type "Milestone" - Look for a WP whose subject contains the feature number or name - **If found**: Display the milestone WP (ID, subject, status) and confirm with user - **If NOT found**: Offer to create one: - Propose title: `{feature-number} - {Feature Name from spec.md}` (e.g., "001 - Core ETL + Visual Designer (V1)") - Propose description from spec.md summary - Ask user for confirmation before creating via `mcp__openproject__create_work_package` - Store the milestone WP ID for subsequent steps 5. **Stage: "tasks" — Sync Phases as Work Packages**: - Skip this step if `tasks.md` does not exist - Parse all phase headers from tasks.md: `## Phase N: Description — OP #NNNNN` - For each phase: - **If OP WP ID is present in the header**: Verify the WP exists via `mcp__openproject__get_work_package` - If it exists: Compare the subject and update if the description has changed (use `mcp__openproject__update_work_package`) - If it does NOT exist (stale ID): Flag it and offer to create a new WP - **If NO OP WP ID in the header**: Create a new Phase WP: - Type: "Phase" (or "Task" if Phase type unavailable — check `mcp__openproject__list_types` first) - Subject: `Phase N: Description` (e.g., "Phase 3: US-1 — Manage Users and Roles") - Description: Include the phase purpose, task count, checkpoint criteria, and user story goal - After creation, update the tasks.md phase header to include `— OP #NewID` - **Create milestone relations**: For each phase WP, create a `requires` relation from the phase to the milestone (if not already linked): - Use `mcp__openproject__list_relations` on the phase WP to check existing relations - If no `requires` relation to the milestone exists, create one via `mcp__openproject__create_relation` - **Create inter-phase dependencies**: Parse the dependency graph from tasks.md (look for "Depends on: Phase N" notes and the dependency graph section): - For each dependency, create a `follows` relation (phase X follows phase Y) - Check existing relations first to avoid duplicates - Report summary: phases found, created, updated, relations created 6. **Stage: "implement" — Sync Tasks as Child Work Packages**: - Skip this step if NOT in "implement" stage (no `[X]` tasks) unless the user explicitly requests task sync - For each phase in tasks.md: - Get the phase WP ID from the header - Use `mcp__openproject__list_work_packages` to find existing child WPs under this phase (filter by parent if supported, or list all project WPs and filter by subject prefix) - Parse all tasks in the phase: `- [ ] T### [P?] [US?] Description` - For each task: - **If a matching child WP exists** (match by task ID in subject, e.g., "T042"): - Compare status: if task is `[X]` in tasks.md but WP is not closed → update WP status - Compare subject: if description changed → update WP subject - **If NO matching child WP exists**: Create one: - Type: "Task" - Subject: `T### — Description` (e.g., "T042 — Implement refresh token denylist in backend/etl/.../TokenDenylistService.java") - Set parent to the phase WP ID (use direct API PATCH with `_links.parent.href` since MCP update_work_package does not support parent — see CLAUDE.md constraints) - **Batch creation**: Process tasks in batches to avoid rate limiting. Create up to 10 WPs at a time, then pause briefly. - Update task completion status: - For tasks marked `[X]` in tasks.md: Update the corresponding WP status to "Closed" (or appropriate status) - For tasks marked `[ ]`: Ensure WP is in "New" or "In progress" status - Report summary: tasks found, created, updated, status synced 7. **Update CLAUDE.md** (if new WP IDs were created): - Update the OpenProject Work Package IDs table in CLAUDE.md with any new phase WP IDs - Update task counts if they changed - Add any new relation IDs 8. **Update tasks.md** (if new phase WP IDs were assigned): - Update phase headers with newly assigned OP WP IDs: `## Phase N: Description — OP #NewID` 9. **Report**: Output a summary table: ```text | Action | Count | Details | |--------------|-------|----------------------------------| | Milestone | 1 | #XXXXX (found/created) | | Phases | N | M created, K updated, J existing | | Tasks | N | M created, K updated | | Relations | N | M requires, K follows | | Files Updated| N | tasks.md, CLAUDE.md | ``` - List any errors or items that need manual attention - Suggest next steps (e.g., "Run /speckit.implement to start implementation") ## Operating Rules 1. **Never delete work packages** — only create or update. If a WP seems orphaned, flag it for manual review. 2. **Always check before creating** — search for existing WPs before creating new ones to avoid duplicates. 3. **Preserve existing OP WP IDs** — if a phase header already has an OP ID, trust it unless the WP doesn't exist. 4. **Respect MCP limitations**: - Relations are CRD only (no update) — to change a relation type, delete and recreate - Parent-child cannot be set via `update_work_package` — use direct API PATCH with `_links.parent.href` - Milestones cannot have children — use `requires` relations instead 5. **Batch operations** — when creating many WPs, process in batches of 10 to avoid overwhelming the API. 6. **Confirm destructive-ish actions** — ask user before bulk-creating WPs (e.g., "About to create 23 phase WPs. Proceed?"). 7. **Log activity** — after creating or updating WPs, add a comment with context (e.g., "Synced from tasks.md phase header").