AiTools.ProfileSyncTool 1.3.0.2139

profile-sync-tool

Catalog agent-config servisinden profil çekip consumer'lara (.claude/rules vb.) dağıtan dotnet tool (T#682). apps/sync-ai-configs'ın yerini alır: dosya-okuma + .sync.json/.workspace.json registry yok; kaynak catalog snapshot, render client-side.

Sıfır lib/registry bağımlılığı (Spectre.Console + System.Text.Json + System.Net.Http).

Kavramsal model + akış şeması (agent-facing): KB domain doc projects/ai-tools/profile-sync/consumer-flow.md (topic profile-sync). Bu README kurulum/çalıştırma için developer-canonical; akış/auth modeli/claude-desktop gotcha'ları için domain doc canonical.

Nasıl çalışır

  1. GET /api/agent-config/snapshot → atoms (roles + instruction groups/shards + skills + profiles).
  2. Client-side resolve (ProfileResolver): selector → 4-seviye fallback match → audience-filtreli denormalize. Server ResolveProfileAsync algoritmasının birebir portu; drift parity test ile korunur.
  3. Render (ProfileRenderer + InstructionEmitter): ResolvedProfile → editör formatı (claude-code: .claude/rules/*.md).

Auth — PAT (primary) / session-id (fallback)

Gateway üzerinden iki yöntem (gateway ikisini de kabul eder):

  • PAT (primary): Authorization: Bearer ts_pat_v1_*.
  • session-id (fallback): x-session-id: <GUID> (catalog-loader paterni).

snapshot/resolve allowAuthenticated (admin değil) → read-only yeterli. Tool catalog'a doğrudan değil, gateway'e gider. Env yoksa interaktif prompt: önce yöntem (pat | session-id), sonra değer (gizli).

Kullanım

dotnet tool install --global AiTools.ProfileSyncTool

export PROFILE_SYNC_API_BASE="https://<gateway>/api"
export PROFILE_SYNC_PAT="ts_pat_v1_..."
profile-sync            # interaktif wizard
profile-sync --dry-run  # yazma yok, plan

# Headless (non-interactive) — conductor / script (T#688):
profile-sync prepare --role governance --editors claude-code --target-dir ./repo --api-base https://<gateway>/api --pat ts_pat_v1_...
profile-sync prepare --help   # tum flag'ler + exit kodlari (0 ok / 1 catalog-resolve-ag / 3 kullanim)

prepare alt-komutu interaktif wizard'i BYPASS eder (TTY gerekmez); selector + auth flag'lerden kurulur (auth: flag > env, pat > session). Alt-komut yoksa interaktif mod DEFAULT.

Wizard sırası (data-driven)

modelTier (Faz 1: frontier) → roleworkType?scope|stack? → hedef dizin (boş = CWD) → editör hedefleri (multiselect: cursor / claude-code / trae / codex / claude-desktop). Seçenekler snapshot.Profiles'tan türetilir (var olmayan tuple sunulmaz). T#690: claude-desktop artık editör listesinde (ayrı toggle yok); seçilirse global config + <hedef>/.claude-desktop prompt dizini.

Env / flag Açıklama
PROFILE_SYNC_API_BASE Gateway API kökü (örn. https://host/api). Yoksa prompt.
PROFILE_SYNC_PAT PAT (ts_pat_v1_...). Opsiyonel — primary.
PROFILE_SYNC_SESSION Session id (GUID). Opsiyonel — PAT yoksa fallback.
--dry-run Yazma yok, sadece plan + sayım.
--no-prune Stale silmeyi kapatır. Default: prune AÇIK — yönetilen dizinlerde (rules/skills) bu koşuda üretilmeyen dosyalar silinir (--prune geriye-uyum no-op). Detay: Stale prune.
--help Kullanım.

Auth çözümü: env'de PAT varsa Bearer; yoksa session varsa x-session-id; ikisi de yoksa prompt (yöntem + değer).

Stale prune (T#748)

prepare hedef dizine güncel dosyaları yazar; ancak Catalog'dan silinen/yeniden adlandırılan shard/skill'lerin eski kopyaları hedef dizinde kalırdı ve bu birikinti çelişkili talimat riski yaratıyordu (örn. 00-discipline.md00-task-discipline.md rename'inde ikisi de .claude/rules'ta kalırdı). Prune bunu çözer ve default açıktır (T#761 O1 — rapor-only dönem stale dosyanın aylarca kalabildiğini gösterdi):

  • Kapsam: yalnız bu koşuda emit edilen (aktif --editors) file-editörlerin yönetilen alt-dizinleri — MDC rules dizini (.claude/rules, .cursor/rules, .trae/rules) + skills dizinleri (.../skills). --editors ile seçilmeyen editörün dizini dokunulmaz. Monolithic instruction dosyaları (CLAUDE.md, AGENTS.md) kapsam dışı (her koşu overwrite, birikme yok).
  • Tespit: bu koşuda yazılan/atlanan (idempotent skip dahil) dosya kümesi dışında kalan her dosya = stale.
  • Güvenlik: rapor her zaman; silme default (kapatma --no-prune); --dry-run ile silme simüle edilir; prune tüm emit başarıyla bittikten sonra çalışır (yarım koşuda geçerli dosya silinmez).

Not: .claude/rules ve .claude/skills tümüyle sync-owned kabul edilir — bu dizinlere elle dosya eklemeyin; prune onları stale sayıp siler. claude-desktop (global config + prompt dizini) ve local-compose kapsam dışı.

Render-state manifest + verify (T#761)

Her prepare koşusu hedef dizine .sync-ai-configs/render-state.json yazar: selector (role/work-type/scope/stack/model-tier), editor seti ve yönetilen dizinlere yazılan dosyaların hash'leri (text hash TrimEnd-normalize; MCP config'ler ve claude-desktop global dosyaları kapsam dışı — PAT gömülü/koşudan koşuya değişken içerik manifest'e girmez).

profile-sync verify [--target-dir <path>] [--no-remote] üç yönlü staleness kıyası yapar; selector/editor seti flag değil, manifest'ten okunur:

Eksen Bulgu türleri
manifest ↔ disk missing (silinmiş), modified (elle değişmiş), orphan (yönetilen dizinde manifest-dışı dosya)
manifest editor seti ↔ disk unmanaged-editor-dir (seçilmemiş bilinen-editör dizini duruyor — hiçbir koşu yönetmiyor)
manifest ↔ güncel snapshot content-stale (Catalog'daki içerik değişmiş; re-render kıyası, --no-remote ile atlanır)

Auth yalnız snapshot kıyası için gerekir (--api-base/--pat/--session-id veya env; prepare ile aynı). Exit: 0 temiz · 2 drift bulundu · 1 catalog/ağ hatası · 3 kullanım/manifest hatası — CI/drift-check/conductor pre-dispatch entegrasyonu exit code üzerinden.

Claude Desktop hedefi

File-tabanlı editörlerden (cursor/claude-code/…) ayrıdır: Claude Desktop instruction .md'lerini bir klasörden otomatik okumaz. Bu hedef iki şey üretir:

  1. Global MCP config%APPDATA%/Claude/claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/…, Linux: ~/.config/Claude/…). Mevcut server'lar ve diğer key'ler korunur (merge), yazmadan önce .bak.1..3 yedeği alınır.
  2. Prompt dizini → seçtiğin klasöre {role}-instruction.md + skills/<name>/… (manuel yükleme için).

Neden stdio-bridge (streamable-HTTP değil)?

Claude Desktop config şeması yalnızca stdio doğrular; gateway'in streamable-HTTP URL'ini doğrudan yazarsan sessizce düşürür. Bu yüzden MCP, npx mcp-remote ile sarmalanır. Remote Custom Connector (Settings → Connectors) bir alternatiftir ama (a) dosyaya yazılamaz, UI'dan eklenir, (b) Anthropic cloud'undan bağlanır → private gateway'e erişemez. Bu yüzden tool dosya-emit edilebilen stdio-bridge'i kullanır.

Auth: env-ref + env bloğu

Auth değeri args'a inline gömülmez; Authorization:${PROFILE_SYNC_MCP_AUTH} referansı + server'ın env bloğunda değer yazılır. mcp-remote ${VAR}'ı process env'den çözer (canlı doğrulandı — log: "Replacing $ with environment value"). Değer env bloğundan gelir; Claude Desktop bu bloğu spawn ettiği child process'e geçirir.

Not (canlı e2e dersi): OS environment variable yolu (config'e değer yazmadan setx ile) Claude Desktop'ta çalışmaz — Desktop, setx'lenen OS env'i full re-login olmadan child'a geçirmiyor. Bu yüzden değer env bloğunda taşınır. Rotation = env alanını düzenle veya tool'u yeniden çalıştır.

Kullanım

claude-desktop artık editör listesinden seçilir (T#690 — ayrı toggle yok); prompt dizini sabit: <hedef>/.claude-desktop.

profile-sync --dry-run   # ÖNCE: merge önizlemesini gör (global config'e dokunmaz)
profile-sync             # wizard → editör hedefleri'nde "claude-desktop"u işaretle
# Headless:
profile-sync prepare --role <r> --editors claude-desktop --api-base ... --pat ...

Sonra Claude Desktop'ı yeniden başlatagent-ops + knowledge-base server'ları MCP listesinde görünür. Prompt dizinindeki {role}-instruction.md'yi bir Claude Desktop Project'ine elle ekleyebilirsin.

Uyarı (auth): Global config auth'u env bloğunda gömülü taşır — bu dosyayı paylaşma. Operatör session-id ile auth olduysa MCP runtime'a session gömülür ve expire olunca bağlantı kopar → kalıcı kullanım için PAT önerilir (role-scoped PAT-store: T#684). Config global olduğu için server adları sabittir (agent-ops/knowledge-base); her sync son seçilen rolü yazar (aynı anda tek aktif rol).

local-compose hedefi (T#718 Faz 3)

File-tabanlı editörlerden ve claude-desktop'tan ayrı üçüncü şekil: ambient instruction dosyaları yerine composer-tüketilebilir tek yapısal manifest üretir. Local model prompt kompozisyonu içindir — conductor LocalPromptComposerService bu manifesti okuyup faz-scope'lu prompt'a gömer (ambient CLAUDE.md local tier'da RED; ADR local-frontier-task-boundary §8).

# Headless (conductor'ın çağırdığı şekil; model-tier local zorunlu değil ama beklenen kullanım):
profile-sync prepare --role governance --model-tier local --editors local-compose --target-dir <dir> --api-base ... --pat ...

Çıktı: {targetDir}/.local-compose/context.json — şema (schemaVersion: 1):

{
  "schemaVersion": 1,
  "role": "governance",
  "instruction": "<çözülen profilin monolithic instruction blob'u>",
  "skills": [
    {
      "name": "task-flow-local",
      "description": "...",
      "body": "<SKILL.md gövdesi>",
      "references": [ { "path": "references/x.md", "body": "..." } ]
    }
  ]
}

Sorumluluk sınırı: emitter TÜM çözülen içeriği yazar (audience-filtreli — local profil = local skill seti); faz-scope seçim composer'a aittir (conductor PromptComposer, Whole|PhaseScoped). Probe-gate kararı (record/evidence/t718-p5-composition-gate): frontier gövdesi ÇEKİLMEZ, LLM-distilasyon motoru YOK. docker-unaware: targetDir conductor DataDir cache'i olabilir; pattern-job sandbox'ına mount edilmez. Manifest dosya sözleşmesi tek bağdır — conductor bu paketi kod olarak referans etmez (process + dosya).

Kapsam

frontier + local · çoklu editör (cursor/claude-code/trae/codex/claude-desktop/local-compose) + headless prepare (T#688) · skills dağıtımı (.../skills/<name>/SKILL.md+refs) · mcp config (gateway base'den türetilir, kimlik header gömülü — commit etmeyin) · Claude Desktop (stdio-bridge global MCP + prompt dizini, Mod A/B auth) · hedef dizin opsiyonel (CWD). project-context: yok (drop kararı; catalog shard'ları proje-agnostik). cowork: ertelendi (gerekirse ayrı faz). Faz 3: sync-ai-configs retire + server klasör modeli kaldırma.

Test

dotnet test profile-sync-tool.slnx
# Canlı parity (opt-in): PROFILE_SYNC_API_BASE + PROFILE_SYNC_PAT set edilirse
# client resolve == server /profiles/resolve tüm profillerde doğrulanır.

T#761 render hijyen: prune default ACIK (--no-prune escape; rapor-only donem stale shard'in kalmasina yol acti). Her kosu render-state manifest yazar (.sync-ai-configs/render-state.json, yonetilen dosya hash'leri). Yeni verify alt-komutu: manifest-disk + secilmemis-editor-dizini + guncel-snapshot uc yonlu staleness kiyasi, exit-code'lu (CI/drift-check/conductor pre-dispatch entegrasyonu icin).

This package has no dependencies.

Version Downloads Last updated
1.5.0.1852 1 09/12/2026
1.4.0.2344 3 09/03/2026
1.3.0.2139 9 07/16/2026
1.1.0.57 4 07/06/2026
1.0.0.327 5 07/03/2026