Skip to main content

Profile-Based Sync

Profile-Based Sync is SpecWeave's architecture for syncing increments to unlimited external repositories (GitHub, JIRA, Azure DevOps) with intelligent rate limiting, time range filtering, and project-specific configuration. Each sync profile defines how to connect to an external system, with support for multiple profiles per provider.


The Problem with Single-Project Sync

Traditional sync systems assume one project = one external repository:

This breaks down with:

  • ❌ Multi-client work (Client A, Client B, Client C repos)
  • ❌ Multi-repo architecture (Frontend, Backend, Mobile repos)
  • ❌ Team-based organization (Team 1 repo, Team 2 repo)
  • ❌ Microservices (20+ service repos)
  • ❌ Cross-cutting features (spans multiple repos)

Profile-Based Sync: The Solution

Support unlimited repositories through sync profiles:

Key Benefits:

  • ✅ Unlimited profiles per provider (3+, 5+, 10+ repos)
  • ✅ Different increments sync to different repos
  • ✅ Team-based organization (Frontend → repo-A, Backend → repo-B)
  • ✅ Multi-client support (Client-A, Client-B, Client-C)

3-Layer Architecture

Profile-based sync uses a three-layer architecture for clean separation of concerns:

Layer 1: Credentials (.env)

Purpose: Store sensitive API tokens

Location: .env (gitignored)

# .env
GITHUB_TOKEN=ghp_xxxxxxxxxxxx
JIRA_API_TOKEN=ATATTxxxxxx
AZURE_DEVOPS_PAT=xxxxxxxxxxxx

Rules:

  • ✅ One token per provider type
  • ✅ Never committed to git
  • ✅ Shared across all profiles of same provider

Layer 2: Sync Profiles (config.json)

Purpose: Define connection details per repository

Location: .specweave/config.json

{
"sync": {
"profiles": {
"specweave-dev": {
"provider": "github",
"displayName": "SpecWeave Development",
"config": {
"owner": "anton-abyzov",
"repo": "specweave"
},
"timeRange": {
"default": "1M",
"max": "6M"
},
"rateLimits": {
"maxItemsPerSync": 500,
"warnThreshold": 100
}
},
"client-mobile": {
"provider": "github",
"displayName": "Client Mobile App",
"config": {
"owner": "client-org",
"repo": "mobile-app"
},
"timeRange": {
"default": "1M",
"max": "3M"
}
},
"internal-jira": {
"provider": "jira",
"displayName": "Internal JIRA",
"config": {
"domain": "company.atlassian.net",
"project": "PROJ"
}
}
}
}
}

Benefits:

  • ✅ Reusable (multiple increments → one profile)
  • ✅ Version controlled (committed to git)
  • ✅ No secrets (tokens in .env, not config)
  • ✅ Team-shareable (everyone uses same profiles)

Layer 3: Per-Increment Metadata (metadata.json)

Purpose: Track which profile + issue for each increment

Location: .specweave/increments/0008-user-authentication/metadata.json

{
"increment": "0008-user-authentication",
"status": "implementation",
"created": "2025-11-01T10:00:00Z",
"updated": "2025-11-10T15:30:00Z",
"sync": {
"profile": "specweave-dev",
"issueNumber": 30,
"issueUrl": "https://github.com/anton-abyzov/specweave/issues/30",
"lastSync": "2025-11-10T15:30:00Z"
}
}

Benefits:

  • ✅ Increment-specific (each increment can use different profile)
  • ✅ Persistent (survives profile changes)
  • ✅ Auditable (when was last sync?)

Creating Sync Profiles

Interactive Creation

/specweave:sync-profile create

# Prompts:
# 1. Provider? (github/jira/ado)
# 2. Profile ID? (e.g., "client-mobile")
# 3. Display name? (e.g., "Client Mobile App")
# 4. Owner? (e.g., "client-org")
# 5. Repo? (e.g., "mobile-app")
# 6. Default time range? (1W/1M/3M/6M/ALL)

# Output:
# ✅ Profile created: client-mobile
# 📝 Saved to: .specweave/config.json

Manual Creation

Edit .specweave/config.json:

{
"sync": {
"profiles": {
"my-new-profile": {
"provider": "github",
"displayName": "My New Repository",
"config": {
"owner": "my-org",
"repo": "my-repo"
},
"timeRange": {
"default": "1M",
"max": "6M"
},
"rateLimits": {
"maxItemsPerSync": 500,
"warnThreshold": 100
}
}
}
}
}

Profile Configuration Fields

FieldRequiredDescriptionExample
provider✅ YesProvider type"github", "jira", "ado"
displayName✅ YesHuman-readable name"SpecWeave Development"
config✅ YesProvider-specific config{"owner": "...", "repo": "..."}
timeRange.default⚠️ OptionalDefault time range"1M"
timeRange.max⚠️ OptionalMaximum allowed"6M"
rateLimits.maxItemsPerSync⚠️ OptionalMax items per sync500
rateLimits.warnThreshold⚠️ OptionalWarn if over100

Provider-Specific Config:

// GitHub
"config": {
"owner": "anton-abyzov",
"repo": "specweave"
}

// JIRA
"config": {
"domain": "company.atlassian.net",
"project": "PROJ"
}

// Azure DevOps
"config": {
"organization": "myorg",
"project": "backend-services"
}

Time Range Filtering

Problem: Syncing ALL data takes 25+ minutes and hits rate limits.

Solution: Time range presets filter data by creation date:

Time Range Performance

PresetDurationItemsAPI CallsDurationImpact
1W1 week~507530 secLow ✅
1M1 month~2003002 minMedium ✅
3M3 months~6009005 minMedium ⚠️
6M6 months~1,2001,80010 minHigh ⚠️
ALLAll time~5,000+7,500+30+ minCritical ❌

Recommendation: Default to 1M (1 month) for optimal balance (200 items, 2 min, safe).

Using Time Ranges

Interactive:

/specweave-github:sync 0008

# Prompt:
# ⏰ Select time range:
# 1️⃣ 1 week (~50 items, 30 sec) - Quick
# 2️⃣ 1 month (~200 items, 2 min) - Recommended ✅
# 3️⃣ 3 months (~600 items, 5 min) - Comprehensive
# 4️⃣ 6 months (~1,200 items, 10 min) - Large
# 5️⃣ All time (~5,000+ items, 30+ min) - Critical ⚠️
#
# Choice? [2]:

Command-Line:

# Use default (from profile)
/specweave-github:sync 0008

# Override with specific range
/specweave-github:sync 0008 --time-range 1M
/specweave-github:sync 0008 --time-range 3M

# Use all time (dangerous!)
/specweave-github:sync 0008 --time-range ALL

Dry Run:

# Preview sync without executing
/specweave-github:sync 0008 --dry-run

# Output:
# 📊 Sync Preview (DRY RUN)
# Profile: specweave-dev
# Time Range: 1M (1 month)
# Estimated:
# - Items: ~200
# - API Calls: ~300
# - Duration: ~2 minutes
# - Impact: MEDIUM
#
# ✅ Safe to proceed

Rate Limiting Protection

SpecWeave protects against API rate limit exhaustion with pre-flight validation:

Rate Limit Impact Levels

ImpactAPI CallsStatusAction
LOW<250✅ SafeProceed
MEDIUM250-1,000⚠️ WarningConfirm
HIGH1,000-2,500⚠️ RiskyStrong warning
CRITICAL2,500+❌ BlockReduce time range

Example: Critical Impact Blocked

/specweave-github:sync 0008 --time-range ALL

# Output:
❌ This sync may FAIL due to:

Blockers:
• CRITICAL rate limit impact: 7,500 API calls exceeds safe threshold
• Not enough rate limit remaining (need 7,500, only 4,850 remaining)

Recommendations:
1. Reduce time range to 1 month (~300 API calls, SAFE)
2. Wait for rate limit reset (25 minutes)
3. Split sync across multiple time periods

# Blocked (must use smaller time range)

Provider Rate Limits

ProviderLimitResetNotes
GitHub5,000/hourHourlyAuthenticated API
JIRA100/minPer minuteCloud API
Azure DevOps200/5minPer 5 minutesREST API

Multi-Project Organization

Profiles work seamlessly with project contexts for team-based organization:

{
"sync": {
"projects": {
"specweave-core": {
"id": "specweave-core",
"name": "SpecWeave Core",
"description": "Core framework development",
"keywords": ["framework", "cli", "plugin"],
"team": "Core Team",
"defaultSyncProfile": "specweave-dev",
"specsFolder": ".specweave/docs/internal/specs/specweave-core"
},
"mobile-app": {
"id": "mobile-app",
"name": "Mobile Application",
"description": "React Native mobile app",
"keywords": ["mobile", "react-native", "ios", "android"],
"team": "Mobile Team",
"defaultSyncProfile": "client-mobile",
"specsFolder": ".specweave/docs/internal/specs/mobile-app"
}
}
}
}

Smart Project Detection:

Increment: "Add React Native dark mode for mobile app"

Detects project "mobile-app" (keywords: mobile, react-native)

Uses profile "client-mobile" automatically

Syncs to client-org/mobile-app repo

Detection Scoring:

  • Project name match: +10 points
  • Team name match: +5 points
  • Keyword match: +3 points per keyword
  • Auto-select if confidence > 0.7

Sync Workflow

Complete Workflow Example

# 1. Create profile (once)
/specweave:sync-profile create
# → Profile: client-mobile created

# 2. Create increment
/specweave:increment "Add dark mode toggle"
# → Increment 0009-dark-mode created

# 3. Link increment to profile (optional - can auto-detect)
# Edit: .specweave/increments/0009-dark-mode/metadata.json
# Set: "sync": {"profile": "client-mobile"}

# 4. Sync increment
/specweave-github:sync 0009
# → Prompt: Select profile (auto-detected: client-mobile)
# → Prompt: Select time range (default: 1M)
# → Pre-flight validation (300 API calls, LOW impact)
# → Execute sync
# → Create GitHub issue #45
# → Update metadata.json

# 5. Complete tasks (auto-sync via hooks)
# [x] T-001: Implement dark mode toggle
# → Hook fires: post-task-completion.sh
# → Sync to GitHub issue #45
# → Update checkbox: [x] T-001

# 6. Close increment
/specweave:done 0009
# → Hook fires: post-increment-done
# → Close GitHub issue #45
# → Final living docs sync

Profile Management Commands

List Profiles

/specweave:sync-profile list

# Output:
📋 Sync Profiles (3 total)

✅ specweave-dev (GitHub)
Repository: anton-abyzov/specweave
Time Range: 1M (default), 6M (max)
Rate Limit: 500 items/sync

✅ client-mobile (GitHub)
Repository: client-org/mobile-app
Time Range: 1M (default), 3M (max)
Rate Limit: 300 items/sync

✅ internal-jira (JIRA)
Domain: company.atlassian.net
Project: PROJ

Get Profile Details

/specweave:sync-profile get specweave-dev

# Output:
📋 Profile: specweave-dev

Provider: GitHub
Display Name: SpecWeave Development
Owner: anton-abyzov
Repository: specweave

Time Range:
Default: 1M (1 month)
Maximum: 6M (6 months)

Rate Limits:
Max Items/Sync: 500
Warn Threshold: 100

Status: ✅ Active
Last Used: 2025-11-10 15:30:00

Update Profile

/specweave:sync-profile update specweave-dev

# Prompts:
# 1. Change display name? (SpecWeave Development)
# 2. Change time range? (1M)
# 3. Change rate limits? (500)

# Output:
# ✅ Profile updated: specweave-dev

Delete Profile

/specweave:sync-profile delete internal-jira

# Prompt:
# ⚠️ This will delete profile "internal-jira"
# ⚠️ 3 increments currently use this profile:
# - 0005-backend-api
# - 0007-authentication
# - 0010-payment-gateway
#
# ❓ Continue? (y/N)

# If confirmed:
# ✅ Profile deleted: internal-jira
# ⚠️ 3 increments now have no sync profile

Migration from V1 (Single Project)

SpecWeave provides automatic migration from old single-project config to profile-based:

specweave migrate-to-profiles

# Output:
🔄 Migrating to Profile-Based Sync...

✅ Found existing GitHub config:
Repository: anton-abyzov/specweave

✅ Created GitHub profile: default-github
Repository: anton-abyzov/specweave

✅ Created default project context
Name: specweave
Default profile: default-github

📊 Migration Summary:
Profiles created: 1
Projects created: 1
Increments migrated: 8

✅ Migration complete!

Before (V1):

{
"sync": {
"enabled": true,
"provider": "github",
"owner": "anton-abyzov",
"repo": "specweave"
}
}

After (V2 - Profile-Based):

{
"sync": {
"enabled": true,
"activeProfile": "default-github",
"profiles": {
"default-github": {
"provider": "github",
"displayName": "SpecWeave Repository",
"config": {
"owner": "anton-abyzov",
"repo": "specweave"
},
"timeRange": {
"default": "1M",
"max": "6M"
}
}
}
}
}

Anti-Patterns

1. Hardcoding Credentials in Profiles

// ❌ Bad: Credentials in config.json
{
"sync": {
"profiles": {
"bad-profile": {
"provider": "github",
"config": {
"owner": "anton-abyzov",
"repo": "specweave",
"token": "ghp_xxxxxxxxxxx" // ❌ NEVER DO THIS!
}
}
}
}
}

// ✅ Good: Credentials in .env
// .env (gitignored)
GITHUB_TOKEN=ghp_xxxxxxxxxxx

// config.json (version controlled)
{
"sync": {
"profiles": {
"good-profile": {
"provider": "github",
"config": {
"owner": "anton-abyzov",
"repo": "specweave"
// No token here!
}
}
}
}
}

2. Using ALL Time Range by Default

# ❌ Bad: Always sync all time
/specweave-github:sync 0008 --time-range ALL
# Result: 30+ minutes, 7,500 API calls, high rate limit risk

# ✅ Good: Use 1M (1 month) by default
/specweave-github:sync 0008 --time-range 1M
# Result: 2 minutes, 300 API calls, safe

3. Creating Too Many Profiles

// ❌ Bad: One profile per increment
{
"sync": {
"profiles": {
"increment-0001": {...},
"increment-0002": {...},
"increment-0003": {...},
// 50+ profiles for same repo!
}
}
}

// ✅ Good: One profile per repository
{
"sync": {
"profiles": {
"specweave-dev": {...} // Used by ALL increments for this repo
}
}
}


Summary

Profile-Based Sync enables unlimited external repositories through:

3-Layer Architecture:

  1. Credentials (.env) - API tokens (gitignored)
  2. Profiles (config.json) - Connection details (version controlled)
  3. Metadata (metadata.json) - Per-increment tracking

Time Range Filtering:

  • 1M (1 month) - Recommended default (~200 items, 2 min)
  • 3M/6M - Larger ranges (5-10 min)
  • ALL - Use sparingly (30+ min, rate limit risk)

Rate Limiting Protection:

  • Pre-flight validation (LOW/MEDIUM/HIGH/CRITICAL)
  • Automatic blocking for CRITICAL impact
  • Provider-specific limits (GitHub: 5K/hour, JIRA: 100/min, ADO: 200/5min)

Key Commands:

  • /specweave:sync-profile create - Create new profile
  • /specweave:sync-profile list - List all profiles
  • /specweave-github:sync 0008 - Sync increment to GitHub

Result: Work with unlimited repositories while maintaining safety and performance.