---
roadcrew_template_name: "sync-release-status.md"
roadcrew_template_type: "command"
execution_mode: "auto-execute"
roadcrew_template_version: "v1.0"
roadcrew_last_updated: "2025-10-25"
roadcrew_min_version: "1.5.0"
roadcrew_license: "See LICENSE file in .roadcrew folder"
roadcrew_copyright: "Copyright (c) 2025 North Star Holdings, LLC"
spdx_license_identifier: "LicenseRef-RoadcrewLicense-1.0"
---

# Sync Release Status

Synchronize current-release.md checkboxes with actual GitHub issue status.

## Usage

```
/sync-release-status [--current|--minor] [--dry-run]
```

**Flags:**
- `--current` - Sync current-release.md (default)
- `--minor` - Sync minor-release.md
- `--dry-run` - Show what would change without writing files

## What This Command Does

1. Reads release file (current-release.md or minor-release.md)
2. Extracts all GitHub issue numbers from **GitHub Issue**: #N lines
3. Queries GitHub API to check each issue's status (open/closed)
4. Updates checkboxes in release file:
   - `- [ ]` → `- [x]` for closed issues
   - `- [x]` → `- [ ]` for reopened issues
5. Updates Release Criteria checkboxes at the top
6. Writes updated content back to file
7. Displays sync report

## Steps

### 1. Parse Release File

Read the release file and extract:
- Release version
- All epic sections (`### EPIC N:`)
- All issue sections (`#### Issue N.M:`)
- GitHub issue numbers from `**GitHub Issue**: #N` lines
- Current checkbox states

**Data structure:**
```typescript
interface ReleaseIssue {
  type: 'epic' | 'issue';
  number: string;          // Epic number (e.g., "1") or Issue number (e.g., "1.1")
  title: string;
  githubIssue?: number;    // GitHub issue number
  checked: boolean;        // Current checkbox state
  lineNumber: number;      // Line in file for updating
}
```

**Parsing example:**
```markdown
### EPIC 1: Classification System Infrastructure
**GitHub Issue**: #903
**Description**: ...

Issues:
- [x] Issue 1.1: Update templates - **GitHub Issue**: #906
- [ ] Issue 1.2: Remove emoji indicators - **GitHub Issue**: #907
```

Extracts:
```javascript
{
  type: 'epic',
  number: '1',
  title: 'Classification System Infrastructure',
  githubIssue: 903,
  checked: false,  // Epic heading doesn't have checkbox
  lineNumber: 122
}
{
  type: 'issue',
  number: '1.1',
  title: 'Update templates',
  githubIssue: 906,
  checked: true,
  lineNumber: 135
}
{
  type: 'issue',
  number: '1.2',
  title: 'Remove emoji indicators',
  githubIssue: 907,
  checked: false,
  lineNumber: 136
}
```

### 2. Query GitHub for Issue Status

For each GitHub issue number found:

```bash
gh api repos/{owner}/{repo}/issues/{issue_number} --jq '.state'
```

Or using Octokit:
```typescript
const { Octokit } = require('@octokit/rest');
const octokit = new Octokit({ auth: process.env.GH_TOKEN || process.env.GITHUB_TOKEN });

async function getIssueStatus(issueNumber: number): Promise<'open' | 'closed'> {
  try {
    const { data } = await octokit.issues.get({
      owner: 'tailwind-ai',
      repo: 'roadcrew',
      issue_number: issueNumber
    });
    return data.state;
  } catch (error) {
    console.warn(`⚠️  Issue #${issueNumber} not found`);
    return 'open';  // Default to open if not found
  }
}
```

**Rate limiting:**
- Batch queries in groups of 10
- Add 100ms delay between batches
- Respect GitHub API rate limits (5000/hour authenticated)

### 3. Determine Checkbox Updates

Compare GitHub status with current checkbox state:

```typescript
interface Update {
  issueNumber: number;
  title: string;
  currentState: boolean;  // Current checkbox
  githubState: 'open' | 'closed';
  newState: boolean;      // New checkbox
  action: 'check' | 'uncheck' | 'no-change';
  lineNumber: number;
}

function determineUpdates(
  issues: ReleaseIssue[],
  githubStatuses: Map<number, 'open' | 'closed'>
): Update[] {
  const updates: Update[] = [];
  
  for (const issue of issues) {
    if (!issue.githubIssue) continue;
    
    const githubState = githubStatuses.get(issue.githubIssue) || 'open';
    const shouldBeChecked = githubState === 'closed';
    
    if (shouldBeChecked !== issue.checked) {
      updates.push({
        issueNumber: issue.githubIssue,
        title: issue.title,
        currentState: issue.checked,
        githubState,
        newState: shouldBeChecked,
        action: shouldBeChecked ? 'check' : 'uncheck',
        lineNumber: issue.lineNumber
      });
    }
  }
  
  return updates;
}
```

### 4. Update Release File

Apply updates to the file content:

```typescript
function applyUpdates(
  fileContent: string,
  updates: Update[]
): string {
  const lines = fileContent.split('\n');
  
  for (const update of updates) {
    const lineIndex = update.lineNumber - 1;
    const line = lines[lineIndex];
    
    if (update.action === 'check') {
      // Change - [ ] to - [x]
      lines[lineIndex] = line.replace(/- \[ \]/, '- [x]');
    } else if (update.action === 'uncheck') {
      // Change - [x] to - [ ]
      lines[lineIndex] = line.replace(/- \[x\]/, '- [ ]');
    }
  }
  
  return lines.join('\n');
}
```

### 5. Update Release Criteria

Check if all issues are complete and update top-level criteria:

```typescript
function updateReleaseCriteria(
  fileContent: string,
  allIssues: ReleaseIssue[],
  githubStatuses: Map<number, 'open' | 'closed'>
): string {
  // Find Release Criteria section
  const criteriaRegex = /\*\*Release Criteria\*\*:(.*?)(?=\n\n---|\n\n##)/s;
  const match = fileContent.match(criteriaRegex);
  
  if (!match) return fileContent;
  
  // Calculate completion
  const totalIssues = allIssues.filter(i => i.githubIssue).length;
  const completedIssues = allIssues.filter(i => {
    if (!i.githubIssue) return false;
    return githubStatuses.get(i.githubIssue) === 'closed';
  }).length;
  
  const allComplete = completedIssues === totalIssues;
  
  // Update criteria checkboxes based on completion
  let updatedCriteria = match[1];
  if (allComplete) {
    // Check all criteria
    updatedCriteria = updatedCriteria.replace(/- \[ \]/g, '- [x]');
  }
  
  return fileContent.replace(criteriaRegex, 
    `**Release Criteria**:${updatedCriteria}$2`
  );
}
```

### 6. Display Sync Report

Show detailed report of what was synced:

```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 RELEASE STATUS SYNC REPORT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Release: v1.1.0 - Optimal Workflow: Classification + TOC
File: memory-bank/releases/current-release.md

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GITHUB ISSUES FOUND
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Epics: 7
Child Issues: 35
Total Issues: 42

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GITHUB STATUS CHECK
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ Open: 5 issues
✅ Closed: 37 issues

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
UPDATES APPLIED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Checked (closed in GitHub):
✓ Issue 1.1: Update issue templates (#906)
✓ Issue 1.2: Remove emoji indicators (#907)
✓ Issue 2.1: Add resource configuration (#910)
... (34 more)

Unchecked (reopened in GitHub):
✗ Issue 3.2: Implement assignment algorithm (#916)

No Changes: 5 issues

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SUMMARY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ Synced: 37 issues
⚠️  Pending: 5 issues still open
📝 Updated: memory-bank/releases/current-release.md

Progress: 88% complete (37/42 issues)

Release Criteria: 7/9 ✓

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

### 7. Write Updated File

If not in `--dry-run` mode:

```typescript
import fs from 'fs';

function writeUpdatedRelease(
  filePath: string,
  updatedContent: string
): void {
  fs.writeFileSync(filePath, updatedContent, 'utf8');
  console.log(`\n✅ Updated: ${filePath}`);
}
```

In `--dry-run` mode:
```
🔍 DRY RUN - No files modified

Would update:
  • memory-bank/releases/current-release.md
  • 37 checkboxes marked as complete
  • 1 checkbox marked as incomplete

Run without --dry-run to apply changes.
```

## Error Handling

**If GitHub issue not found:**
```
⚠️  Issue #123 not found - keeping current checkbox state
```

**If no GitHub issues found in file:**
```
❌ No GitHub issue numbers found in current-release.md

This usually means /scope-release hasn't been run yet, or
issue numbers weren't written back to the file.

Solutions:
  1. Run /scope-release --current to create issues
  2. Manually add **GitHub Issue**: #N lines to epics/issues
  3. Check that scope-release has write-back functionality enabled
```

**If release file doesn't exist:**
```
❌ File not found: memory-bank/releases/current-release.md

Run /advance-release to create current-release.md first.
```

**If GitHub auth fails:**
```
❌ GitHub authentication required

See .cursor/rules/03-github.mdc for authentication setup instructions.
```

## Integration with Other Commands

**Workflow:**
```bash
# 1. Create issues
/scope-release --current

# 2. Work on issues (close them in GitHub)
# ...

# 3. Sync status back to docs
/sync-release-status --current

# 4. Review progress
# current-release.md now shows accurate completion

# 5. When all complete, finalize release
/complete-release 1.1.0
```

**Automation opportunity:**
```bash
# Run before meetings to get latest status
/sync-release-status --current

# Or add to git pre-commit hook
# to always have accurate status
```

## Example Usage

### Example 1: Standard sync
```bash
User: /sync-release-status --current

AI: 📊 Syncing release status from GitHub...

[Queries 42 issues from GitHub]

✅ Synced 42 issues
   37 completed
   5 still open
   
Updated: memory-bank/releases/current-release.md
Progress: 88% complete
```

### Example 2: Dry-run mode
```bash
User: /sync-release-status --dry-run

AI: 🔍 DRY RUN MODE - Checking status...

Would update 12 checkboxes:
  ✓ Issue 1.1: Update templates (#906) [open → closed]
  ✓ Issue 1.2: Remove emojis (#907) [open → closed]
  ... (10 more)

No files modified. Run without --dry-run to apply.
```

### Example 3: Minor release
```bash
User: /sync-release-status --minor

AI: 📊 Syncing minor-release.md from GitHub...

✅ All 8 issues complete!
   
Updated: memory-bank/releases/minor-release.md
Progress: 100% complete

Ready to run /complete-release for minor release.
```