amondnet / amondnet/spec-kit-sdk

feat(sync): Implement UUID-first identification system for cross-platform synchronization

Open
#55 0 comments 0 reactions 1 assignee Claimed by @amondnet View on GitHub
good first issue p2 spec type: feature
Dominant language
TypeScript
Stars
6
Forks
1
PR merge metrics
No merged PRs in 30d

Description

# UUID-First Identification System for Sync Plugin

## Background

Currently, the sync plugin uses `github.issue_number` as the primary identifier for matching specs to remote issues. While `spec_id` (UUID) is generated and stored, it's not actively used for synchronization operations. This creates limitations for cross-platform sync and robust issue tracking.

## Current Implementation Analysis

### How it works now:
- **Primary ID**: `github.issue_number` used for push/pull operations
- **UUID Generation**: `spec_id` generated in `updateFrontmatter()` after push operations
- **Matching Logic**: Adapter checks `issue_number` to determine update vs create
- **Limitation**: Platform-specific IDs prevent cross-platform synchronization

### Code References:
- UUID generation: `plugins/sync/src/core/frontmatter.ts:41`
- Push logic: `plugins/sync/src/adapters/github/github.adapter.ts:33-34`
- Sync engine: `plugins/sync/src/core/sync-engine.ts:58-61`

## Problem Statement

1. **Late UUID Generation**: UUID created after push, not available during sync operations
2. **No Cross-Platform Support**: Cannot sync same spec across GitHub, Jira, Asana
3. **Fragile Matching**: Relies solely on platform-specific issue numbers
4. **Race Conditions**: Multiple processes might generate different UUIDs
5. **Missing UUID Usage**: Generated UUIDs are stored but never used for identification

## Proposed Solution

### UUID Priority System
```
Current: github.issue_number > spec_id
Proposed: spec_id > github.issue_number (with fallback)
```

### Implementation Strategy

#### 1. Early UUID Generation
```typescript
// Generate UUID during spec scanning, not after push
async function scanSpec(path: string): Promise {
const spec = await parseSpec(path)

// Ensure UUID exists before any operations
if (!spec.frontmatter.spec_id) {
spec.frontmatter.spec_id = generateSpecId()
await saveSpec(spec) // Persist immediately
}
return spec
}
```

#### 2. UUID-First Matching Logic
```typescript
async function findMatchingIssue(spec: SpecDocument) {
const uuid = spec.frontmatter.spec_id
const issueNumber = spec.frontmatter.github?.issue_number

// Priority 1: UUID search (if exists)
if (uuid) {
const issueByUuid = await searchIssueByUuid(uuid)
if (issueByUuid) return issueByUuid
}

// Priority 2: Issue number (backward compatibility)
if (issueNumber) {
const issue = await getIssue(issueNumber)
if (issue && uuid) {
const remoteUuid = extractUuidFromIssue(issue)
if (remoteUuid && remoteUuid !== uuid) {
throw new Error('UUID mismatch - conflict detected')
}
}
return issue
}

return null // Create new
}
```

#### 3. UUID Metadata Embedding
Store UUID in issue body as hidden metadata:
```markdown

# Feature Specification: User Authentication
...
```

## Edge Cases and Handling

### 1. UUID Collision
- **Risk**: Two specs with same UUID (extremely unlikely)
- **Solution**: Validate uniqueness during generation, regenerate if collision detected

### 2. Migration Scenarios
- **Existing specs without UUID**: Generate and persist during first scan
- **Existing issues without UUID**: Embed UUID metadata during next push
- **Mixed state**: Handle gracefully with fallback to issue_number

### 3. Cross-Platform Conflicts
- **Problem**: Same UUID in different platforms with different issue numbers
- **Solution**: UUID takes precedence, update platform-specific IDs

### 4. Race Conditions
- **Problem**: Simultaneous UUID generation
- **Solution**: File-based locking during UUID assignment

### 5. Backward Compatibility
- **Requirement**: Existing workflows must continue working
- **Solution**: Gradual migration with fallback to issue_number

## Implementation Roadmap

### Phase 1: Foundation (Week 1)
- [ ] Move UUID generation to `SpecScanner.scanSpec()`
- [ ] Add UUID validation in frontmatter schema
- [ ] Create UUID extraction utilities for issue body
- [ ] Add tests for UUID generation timing

### Phase 2: UUID Matching (Week 2)
- [ ] Implement `searchIssueByUuid()` in GitHubClient
- [ ] Update `GitHubAdapter.push()` to use UUID-first matching
- [ ] Add UUID metadata embedding in issue body
- [ ] Handle UUID conflicts with validation

### Phase 3: Migration Support (Week 3)
- [ ] Create migration command for existing specs
- [ ] Add backward compatibility layer
- [ ] Implement conflict resolution strategies
- [ ] Add comprehensive edge case testing

### Phase 4: Cross-Platform Prep (Week 4)
- [ ] Abstract UUID logic from platform-specific code
- [ ] Update base adapter interface
- [ ] Prepare for Jira/Asana adapter integration
- [ ] Performance optimization and caching

## Acceptance Criteria

### Functional Requirements
- [ ] UUID generated during spec scan, before any sync operations
- [ ] Push operations use UUID for matching when available
- [ ] Issue body contains UUID metadata for identification
- [ ] Backward compatibility maintained for issue_number-based sync
- [ ] Migration command successfully updates existing specs

### Edge Case Handling
- [ ] Handle specs without UUID (generate and persist)
- [ ] Handle issues without UUID metadata (embed during next push)
- [ ] Detect and resolve UUID conflicts
- [ ] Graceful fallback when UUID matching fails
- [ ] Race condition protection during UUID generation

### Testing Requirements
- [ ] Unit tests for UUID generation timing
- [ ] Integration tests for UUID-first matching
- [ ] Edge case tests for all identified scenarios
- [ ] Migration testing with existing data
- [ ] Performance tests for UUID operations

## Migration Strategy

### Automatic Migration
1. **Scan Phase**: Identify specs without UUID
2. **Generation Phase**: Generate UUIDs for missing specs
3. **Persistence Phase**: Save updated frontmatter to disk
4. **Validation Phase**: Verify UUID uniqueness
5. **Remote Sync Phase**: Embed UUIDs in existing issues

### Manual Override
- Provide `--force-uuid-regeneration` flag for conflict resolution
- Support `--uuid-validation` for consistency checking
- Allow `--dry-run` for preview of changes

## Technical Debt Reduction

This change addresses several technical debt items:
- Late UUID generation causing timing issues
- Unused UUID fields cluttering frontmatter
- Platform-specific sync limitations
- Missing cross-platform synchronization capabilities

## Related Issues

- Resolves cross-platform sync limitations
- Enables future Jira/Asana integration
- Improves sync reliability and conflict resolution
- Provides foundation for advanced sync features

## Implementation Notes

- Maintain existing API compatibility
- Use progressive enhancement approach
- Include comprehensive logging for debugging
- Consider performance impact of UUID searches
- Plan for future platform adapter expansion

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.