-
Notifications
You must be signed in to change notification settings - Fork 20
Proposal: GitHub Issues as a Sync Backend (Strategy Pattern) #56
Copy link
Copy link
Open
Description
Summary
Referencing #39 — the existing td-sync server provides excellent event-based sync, but requires hosting infrastructure. This proposal introduces a strategy pattern on the sync transport so that GitHub Issues can serve as an alternative shared persistence layer. No separate server needed — team members sync td tasks via a GitHub repo's issue tracker.
How It Works
The existing sync architecture already has clean separation:
Local SQLite → action_log → GetPendingEvents() → [Event] → Push → Server
Server → Pull → [Event] → ApplyEvents() → Local SQLite
The key insight is that GetPendingEvents() and ApplyEvents() are backend-agnostic — they work with []Event. Only the transport (push/pull) is HTTP-specific. This proposal extracts a SyncBackend interface:
type SyncBackend interface {
Push(events []Event) (PushResult, error)
Pull(afterSeq int64) (PullResult, error)
Status() (SyncStatus, error)
}Two implementations:
HTTPBackend— wraps the existing td-sync HTTP client (current behavior, zero regression)GitHubBackend— translates Events to/from GitHub Issues API calls
GitHub Issues Mapping
| td concept | GitHub representation |
|---|---|
| Issue (task) | GitHub Issue |
| Status (open/in_progress/in_review/closed) | Labels: td:open, td:in-progress, td:in-review; or GitHub closed state |
| Priority (p0–p3) | Labels: td:p0 … td:p3 |
| Type (task/bug/feature/epic) | Labels: td:task, td:bug, td:feature, td:epic |
| Dependencies | Sub-issues or issue body task list |
| Logs/handoffs | Issue comments (structured JSON in a <details> block) |
| Sync sequence | Issue/comment updated_at timestamps + local watermark |
| td ID | Embedded in issue body metadata (HTML comment or YAML front matter) |
User Experience
# Configure GitHub as sync backend
td config set sync.backend github
td config set sync.github.repo owner/repo
# Or via the guided flow
td sync init
# → "Choose sync backend: (1) HTTP server (2) GitHub Issues"
# Then sync works the same as today
td sync --push
td sync --pull
td sync --statusImplementation Phases
- Extract
SyncBackendinterface — define the interface, wrap the existing HTTP client asHTTPBackend, updatecmd/sync.goandcmd/autosync.goto use the interface - GitHub backend — implement
GitHubBackendwith bidirectional Event ↔ GitHub Issue mapping, auth viaghCLI token /GITHUB_TOKEN - Config & init flow — add
sync.backendconfig field, extendtd sync initwith GitHub option - Edge cases — conflict resolution (timestamp-based), rate limit handling, initial seed/import
- Documentation — setup guide, mapping reference, limitations
Why This Approach
- Minimal disruption: Only the transport layer changes.
GetPendingEvents(),ApplyEvents(), action_log, conflict detection — all reused as-is. - Zero-infra collaboration: Teams already on GitHub can sync td tasks without hosting a td-sync server.
- Incremental: HTTPBackend wraps existing code first (no regression risk), then GitHubBackend is additive.
- Extensible: The
SyncBackendinterface could support other backends in the future (e.g., GitLab, Linear, plain git).
Open Questions
- Should the GitHub backend support bidirectional sync (changes made directly in GitHub UI reflected back in td)? Or is td the source of truth with GitHub as read-only mirror?
- For dependencies, prefer sub-issues (GitHub native) or task lists in issue body (more portable)?
- Should there be a
td:managedlabel to distinguish td-synced issues from manually created ones? - Rate limit strategy: batch via GraphQL on pull, or stick with REST for simplicity?
Happy to contribute an implementation if there's interest!
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels