Files
gh-duongdev-ccpm/commands/complete:finalize.md
2025-11-29 18:24:24 +08:00

9.2 KiB
Raw Permalink Blame History

description, allowed-tools, argument-hint
description allowed-tools argument-hint
Finalize completed task - sync with Jira, create PR, clean up
Bash
LinearMCP
AtlassianMCP
SlackMCP
<linear-issue-id>

Finalizing Task: $1

💡 Hint: Try the New Natural Command

For a simpler workflow, consider using:

/ccpm:done [issue-id]

Benefits:

  • Auto-detects issue from git branch if not provided
  • Includes pre-flight safety checks (uncommitted changes, branch pushed, etc.)
  • Part of the 6-command natural workflow
  • See: Quick Start Guide

This command still works perfectly! The hint is just a suggestion.


🚨 CRITICAL: Safety Rules

READ FIRST: $CCPM_COMMANDS_DIR/SAFETY_RULES.md

WILL ASK FOR CONFIRMATION before posting to Jira, Slack, or creating PR!

Workflow

Step 1: Verify Task is Complete

Use Linear MCP to get issue: $1

A) Check Status

Verify status is "Done" or "Verification" (passed).

If status is "In Progress" or "Backlog":

  • Display: ⚠️ Task status is "$status". Run /ccpm:verification:verify $1 first.
  • Exit

B) Parse and Verify Checklist Completion

Look for checklist in description using markers:

<!-- ccpm-checklist-start -->
- [ ] Task 1
- [x] Task 2
<!-- ccpm-checklist-end -->

Or find "## Implementation Checklist" header.

Calculate completion:

  • Total items: Count all - [ ] and - [x] lines
  • Checked items: Count - [x] lines only
  • Percentage: (checked / total) × 100

If completion < 100%:

Display incomplete items:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⛔ Cannot Finalize: Checklist Incomplete
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Progress: X% (Y/Z completed)

❌ Remaining Items:
 - [ ] Task 3: Description
 - [ ] Task 5: Description

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔧 Actions Required
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1. Complete remaining items
2. Update checklist: /ccpm:utils:update-checklist $1
3. Then run finalize again: /ccpm:complete:finalize $1

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

BLOCK finalization and exit.

If completion = 100%:

Display:

✅ Checklist complete! (100% - Z/Z items)

Continue to Step 2.

C) Check for "blocked" label

If "blocked" label exists:

  • Display: ⚠️ Task has "blocked" label. Resolve blockers before finalizing.
  • Exit

If all verifications pass:

  • Continue to Step 2

Step 2: Generate Completion Summary

Create summary from Linear description and checklist:

## Implementation Summary for $1

### What Was Implemented
[Extract from checklist items marked complete]

### Files Modified
[Extract file paths mentioned in description/comments]

### Tests Added
[Extract test information]

### Related Links
- Linear: [link]
- Jira: [link]
- PRs: [links if exist]

Step 3: Interactive Finalization Choices

Use AskUserQuestion:

{
  questions: [
    {
      question: "Do you want to create a Pull Request?",
      header: "Create PR",
      multiSelect: false,
      options: [
        {label: "Yes, Create PR", description: "Generate PR with description"},
        {label: "No, Skip PR", description: "I'll create it manually later"}
      ]
    },
    {
      question: "Do you want to update Jira status?",
      header: "Sync Jira",
      multiSelect: false,
      options: [
        {label: "Yes, Update Jira", description: "Mark Jira ticket as Done"},
        {label: "No, Skip Jira", description: "I'll update manually"}
      ]
    },
    {
      question: "Do you want to notify team in Slack?",
      header: "Notify Team",
      multiSelect: false,
      options: [
        {label: "Yes, Notify Slack", description: "Post completion message"},
        {label: "No, Skip Slack", description: "No notification needed"}
      ]
    }
  ]
}

Step 4: Execute Chosen Actions

If Create PR chosen:

  • Generate PR title from Linear title
  • Generate PR description from implementation summary
  • Suggest command: gh pr create --title "..." --body "..."
  • Show command for user approval

If Update Jira chosen:

  • ASK FOR CONFIRMATION with preview:
    🚨 CONFIRMATION REQUIRED
    
    I will update Jira ticket [JIRA-ID] to status "Done" with comment:
    ---
    Completed in Linear: [WORK-123]
    [Implementation summary]
    ---
    
    Proceed? (yes/no)
    
  • If yes → Use Atlassian MCP to update

If Notify Slack chosen:

  • ASK FOR CONFIRMATION with preview:
    🚨 CONFIRMATION REQUIRED
    
    I will post to #[channel]:
    ---
    ✅ [Linear title] is complete!
    [Brief summary]
    Linear: [link]
    ---
    
    Proceed? (yes/no)
    
  • If yes → Use Slack MCP to post

Step 5: Update Linear Status and Labels

READ: commands/_shared-linear-helpers.md

Use Linear MCP to mark task as complete:

try {
  // Get team ID from issue
  const teamId = issue.team.id;

  // Get valid "Done" state ID
  const doneStateId = await getValidStateId(teamId, "Done");

  // Get or create "done" label
  const doneLabel = await getOrCreateLabel(teamId, "done", {
    color: "#4cb782",
    description: "CCPM: Task completed successfully"
  });

  // Get current labels
  const currentLabels = issue.labels || [];
  const currentLabelIds = currentLabels.map(l => l.id);

  // Find labels to remove
  const implementationLabel = currentLabels.find(l =>
    l.name.toLowerCase() === "implementation"
  );
  const verificationLabel = currentLabels.find(l =>
    l.name.toLowerCase() === "verification"
  );
  const blockedLabel = currentLabels.find(l =>
    l.name.toLowerCase() === "blocked"
  );

  // Build new label list: remove workflow labels, add done
  let newLabelIds = currentLabelIds.filter(id =>
    id !== implementationLabel?.id &&
    id !== verificationLabel?.id &&
    id !== blockedLabel?.id
  );

  // Add done label if not already present
  if (!currentLabels.some(l => l.name.toLowerCase() === "done")) {
    newLabelIds.push(doneLabel.id);
  }

  // Update issue with Done status and final labels
  await mcp__agent-mcp-gateway__execute_tool({
    server: "linear",
    tool: "update_issue",
    args: {
      id: issue.id,
      stateId: doneStateId,
      labelIds: newLabelIds
    }
  });

  console.log("✅ Linear issue finalized:");
  console.log("   Status: Done");
  console.log("   Labels: done (removed implementation, verification, blocked)");

} catch (error) {
  console.error("⚠️ Failed to update Linear issue:", error.message);
  console.warn("⚠️ Task is complete but status may not be updated in Linear.");
  console.log("   You can manually update status to Done if needed.");
}

Add completion timestamp comment:

const finalComment = `## 🎉 Task Completed and Finalized

**Completion Time**: ${new Date().toISOString()}

### Actions Taken:
${prCreated ? '✅ Pull Request created' : '⏭️ PR creation skipped'}
${jiraUpdated ? '✅ Jira status updated to Done' : '⏭️ Jira update skipped'}
${slackNotified ? '✅ Team notified in Slack' : '⏭️ Slack notification skipped'}

### Final Status:
- Linear: Done ✅
- All workflow labels cleaned up
- Task marked as complete

---

**This task is now closed and archived.** 🎊
`;

try {
  await mcp__agent-mcp-gateway__execute_tool({
    server: "linear",
    tool: "create_comment",
    args: {
      issueId: issue.id,
      body: finalComment
    }
  });

  console.log("✅ Completion comment added to Linear");
} catch (error) {
  console.error("⚠️ Failed to add comment:", error.message);
  // Not critical, continue
}

Step 6: Show Final Summary

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎉 Task Finalized: $1
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ Linear: Updated to Done
[✅/⏭️ ] Pull Request: [Created/Skipped]
[✅/⏭️ ] Jira: [Updated/Skipped]
[✅/⏭️ ] Slack: [Notified/Skipped]

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💡 What's Next?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Use AskUserQuestion for next action:

{
  questions: [{
    question: "Task complete! What would you like to do next?",
    header: "Next Action",
    multiSelect: false,
    options: [
      {label: "Create New Task", description: "Start a new task"},
      {label: "View Project Report", description: "See project progress"},
      {label: "Pick Another Task", description: "Work on existing task"},
      {label: "Done for Now", description: "Exit"}
    ]
  }]
}

Notes

  • Always asks for confirmation before external writes
  • Generates helpful PR descriptions
  • Keeps team informed (if desired)
  • Suggests next productive action