amondnet / amondnet/spec-kit-sdk
feat(sync): Implement UUID-first identification system for cross-platform synchronization
- Lingua principale
- TypeScript
- Stelle
- 6
- Fork
- 1
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
# 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
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Valutazione
Questa issue non è ancora stata valutata.