Mert Özen Her Satırda Daha İleri
Yapay Zeka GitHub Copilot — #03

Copilot Chat ve Context: Ask, Edit, Agent ve Plan Akışları, #-referansları, Workspace Index'i ve Context'i Yönetmek

Mert Özen 15 Kas 2026 10 dk 4 görüntülenme
Copilot Chat ve Context: Ask, Edit, Agent ve Plan Akışları, #-referansları, Workspace Index'i ve Context'i Yönetmek

Copilot Chat'e bütün repoyu değil, cevabın olduğu dosyaları #-referanslarıyla verip yanlışlanabilir bir soru sormak gerekir: Bookstore'da context'in yarısı tek bir package-lock.json çıktı, iptal sorusunun cevabı ise beş bin token'lık dilimdeydi ve cevap 'iptal akışı yok'. Ask, Plan ve Agent; workspace index, search.exclude ve compaction.

Sürüm notu: Bu yazıdaki kodlar .NET 10 ve Git ile Bookstore reposunda denenmiştir. Chat modları, #-referansları ve workspace index bilgisi 15 Kasım 2026 itibarıyla Visual Studio 2026 (18.12), Visual Studio Code (VS Code) 1.146 ve Copilot CLI 1.0.112 dokümanlarından alınmıştır; bu yazı için Copilot Chat oturumu açılmamış, Copilot cevabı gösterilmemiştir.

Önce Tahmin Et

Product Owner Selin, sitedeki serilerin ortak örnek uygulaması Bookstore'un (bir online kitapçı) kurumsal müşterileri için bir soru getiriyor: "Bir okul siparişini iptal ederse ayırdığımız stok geri dönüyor mu?" Emre editörde Order.cs açıkken Copilot Chat'e yazıyor: "Ordering module'ünde iptal akışı nasıl çalışıyor?"

Order.cs'te şu enum duruyor:

public enum OrderStatus
{
    Placed,
    PaymentPending,
    Paid,
    Shipped,
    Delivered,
    Cancelled
}

Tahminin ne? Bookstore'da bir iptal akışı var mı? Chat'in cevabı neye dayanacak: açık dosyaya mı, bütün repoya mı, modelin genel bilgisine mi? Bu soruya verilecek kötü bir cevap neye benzer? Cevabı, Copilot'a sormadan önce kendimiz bulacağız; çünkü doğru context'i vermenin ilk adımı, cevabın nerede olduğunu bilmek.

Modlar: Ask, Plan, Agent ve Edit'e Ne Oldu

Chat penceresinin üstündeki seçici, aynı sohbetin hangi yetkilerle çalışacağını belirliyor. 15 Kasım 2026 itibarıyla durum:

AkışVS Code (Copilot harness)Visual Studio 2026Copilot CLI
Soru sorma, kod okumaAsk: yalnız salt okuma tool'ları, dosya değiştirmezAsk: sen Apply demeden kod değişmezVarsayılan ask/execute modu
Önce planPlan, /plan ve ardından görev tanımıylaPlan agent'ı: salt okuma tool'larıyla plan yazar, Implement plan ile agent'a devrederPlan mode, Shift+Tab ile
Çok adımlı işAgent; ayrıca Autopilot moduAgent; 18.12'de Interactive ve AutopilotAynı oturum, --autopilot ile
EditDeprecated, Agent öneriliyorCopilot Edits'in yerini agent mode aldıYok

Pratikte bir soruyu Ask'te sormak, cevabın dosyalara dokunmayacağını garanti ediyor; bu yazının konusu olan "anlamak" işi için doğru mod bu. Plan ise kod yazmadan önce bir uygulama planı üretiyor: Visual Studio'nun Plan agent'ı planı .copilot/plans/ altına taslak olarak yazıyor ve onu düzelttikten sonra Implement plan ile agent mode'a devrediyor. Keşfet, planla, uygula, doğrula akışının kendisini AI Destekli Geliştirme serisinin üçüncü yazısında anlatmıştık; burada yalnız Copilot'taki karşılığını görüyoruz. Agent ile çok adımlı iş beşinci yazının konusu.

VS Code'daki bir değişikliği de bilmek gerekiyor: @workspace gibi @ ile çağrılan chat participant'lar deprecated ve Copilot harness'ında desteklenmiyor. Eski blog yazılarındaki "@workspace'e sor" tavsiyesinin bugünkü karşılığı, agent'ın kendi arama tool'larını kullanması ya da senin #-referansı vermen.

Context Nereden Geliyor

Her chat isteğinde modele giden şey senin yazdığın cümleden çok daha büyük. VS Code dokümanı bunu katmanlar hâlinde anlatıyor: yerleşik sistem talimatları, custom instructions ve custom agent gibi özelleştirmeler, senin mesajın, o ana kadarki konuşma, editörden gelen örtük (implicit) context, senin #-referanslarıyla eklediğin açık (explicit) context ve agent'ın çalıştırdığı tool'ların çıktıları. Model yalnız bu pencerenin içindekini görür; pencerede olmayan bir bilgiyi ancak bir tool ile arayıp ekleyebilir.

Örtük context'in davranışı yüzeye göre değişiyor. VS Code'un Chat görünümünde aktif dosya ya da seçili metin isteğe eklenebiliyor; Agents window'da ise örtük editör context'i varsayılan olarak kapalı. Visual Studio 18.12'deki yeni Chat deneyimi aktif dosyayı, imleci ya da seçimi ve görünen satır aralığını gönderebiliyor; bunu ayarlardan kapatmak ya da tool çağrılarından önce yenilenmesini istemek mümkün. Dokümanın uyarısı önemli: editörde açık olan bir dosya, dosyanın tamamının context'e girdiği anlamına gelmez. Bir kaynak gerçekten önemliyse onu açıkça ekle.

#-referansları ile Context Vermek

VS Code'da # yazınca açılan seçicide iki tür şey var. Context item'ları bilgiyi doğrudan ekler: # ardından bir dosya, klasör ya da sembol adı, ve seçili metin için #selection. Tool'lar ise bir iş yaptırır: #codebase ile anlamsal arama, metin arama, sembol kullanımlarını bulma, Problems panelindeki hataları okuma, source control değişikliklerini listeleme, son terminal komutunun çıktısını okuma, bir web sayfasını getirme (#fetch) ve başka bir GitHub reposunda arama (#githubRepo). Dosyaları Explorer'dan sürükleyip bırakmak ve Add Context düğmesi de aynı işi görüyor; bir issue ya da pull request URL'ini prompt'a yapıştırınca VS Code onu ek olarak ekliyor.

Visual Studio'da da prompt'a # ile solution'daki method, class ve dosyaları ekliyorsun; 18.12 ile Solution Explorer'dan ya da Windows Explorer'dan dosyaları sürükleyip prompt'a eklemek de mümkün. Copilot CLI'da ise context'in ne kadar dolduğunu /context komutu token dökümüyle gösteriyor.

Bir ayrım önemli: #codebase bütün repoyu context'e koymaz, bir arama çalıştırır ve bulduğu parçaları ekler. Dokümana göre agent zaten gerektiğinde anlamsal aramayı kendisi yapıyor; #codebase'i yazmak bunu o prompt için zorlamak demek.

Workspace Index ve Aramanın Kalitesi

Anlamsal arama bir index'e dayanıyor. Repo GitHub.com'da ya da GitHub Enterprise Cloud'daysa index'i GitHub tutuyor ve repo başına bir kez kuruluyor; Azure DevOps repoları için de index otomatik kuruluyor. Bu ikisi dışındaki klasörlerde Copilot "external ingest" ile index'lenebilir dosyaları GitHub'a yükleyip aranabilir yapabiliyor; bunun için organization'ın "Semantic indexing for non-GitHub repositories" policy'sinin açık olması gerekiyor. Business ve Enterprise'da bu policy ayarlanmamışsa özellik kapalı kalıyor. Index'in durumunu VS Code'un Status Bar'ındaki Copilot menüsünde görebilir, "Build Codebase Semantic Index" komutuyla yeniden kurabilirsin. Index yoksa agent metin arama, dosya arama ve dil desteğiyle yine çalışıyor ama sonuçlar daha zayıf olabilir.

Büyük bir solution'da arama kalitesini en çok bozan şey gereksiz dosyalar. Dokümanın vurguladığı nokta şu: agent metin araması yaptığında dönen her eşleşme, dosyayı hiç açmasa bile konuşmanın context'ine giriyor. Bookstore'da bunun boyutunu görmek için repoya küçük bir script ekledik; token sayısını yaklaşık olarak karakter sayısının dörtte biri diye hesaplıyor:

#:property PublishAot=false
// git'in takip ettiği dosyaların yaklaşık context maliyeti: token başına yaklaşık 4 karakter.
// Çalıştırma: dotnet run eng/context-size.cs -- [yol öneki ...]
using System.Diagnostics;
using System.Globalization;

CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;

string[] prefixes = args.Length > 0 ? args : [""];
ProcessStartInfo git = new("git", "ls-files") { RedirectStandardOutput = true };
using Process process = Process.Start(git)!;
string[] tracked = (await process.StandardOutput.ReadToEndAsync())
    .Split('\n', StringSplitOptions.RemoveEmptyEntries);
await process.WaitForExitAsync();

List<(string Path, int Tokens)> files =
[
    .. tracked
        .Where(p => prefixes.Any(prefix => p.StartsWith(prefix, StringComparison.Ordinal)))
        .Select(p => (p, File.ReadAllText(p).Length / 4))
        .OrderByDescending(f => f.Item2)
];

Console.WriteLine($"{files.Count} files, ~{files.Sum(f => f.Tokens):N0} tokens");
foreach ((string path, int tokens) in files.Take(5))
{
    Console.WriteLine($"{tokens,10:N0}  {path}");
}
$ dotnet run eng/context-size.cs
81 files, ~119,604 tokens
    60,089  web/bookstore-web/package-lock.json
     9,345  src/Bookstore.Api/Data/Migrations/20261114234258_AddInstitutions.Designer.cs
     9,320  src/Bookstore.Api/Data/Migrations/BookstoreContextModelSnapshot.cs
     8,177  src/Bookstore.Api/Data/Migrations/20261114005447_InitialCreate.Designer.cs
     5,073  src/Bookstore.Api/Data/Migrations/20261114005447_InitialCreate.cs

$ dotnet run eng/context-size.cs -- src/Bookstore.Api/Ordering/ src/Bookstore.Api/Inventory/ tests/Bookstore.Api.Tests/OrderingTests.cs
11 files, ~5,561 tokens
     1,588  src/Bookstore.Api/Ordering/OrderingModule.cs
     1,011  tests/Bookstore.Api.Tests/OrderingTests.cs
       873  src/Bookstore.Api/Ordering/OrderService.cs
       572  src/Bookstore.Api/Ordering/OrderingConfiguration.cs
       486  src/Bookstore.Api/Inventory/InventoryService.cs

Küçük bir repoda bile tablo açık: yaklaşık 120 bin token'ın yarısı tek bir package-lock.json, en büyük beş dosya toplamın yüzde 77'si ve hepsi araçla üretilmiş dosyalar. İptal sorusunun cevabı için gereken Ordering ve Inventory dilimi ise yaklaşık 5.600 token. "Bütün repoyu context'e ver" yaklaşımı, cevabın olduğu yirmide bir parçayı gürültünün içine gömüyor.

Bunu azaltmanın yolu exclusion ayarları. .gitignore ve files.exclude hem metin aramasından hem anlamsal index'ten dosyayı çıkarıyor; search.exclude ise dosyayı Explorer'da bırakıp yalnız metin aramasından ve grep'ten çıkarıyor. Migration dosyaları ve lock dosyası projede görünmeli, ama bir aramanın sonuçlarını doldurmamalı; bu yüzden Bookstore'un workspace ayarına şunu ekledik:

"search.exclude": {
  "**/package-lock.json": true,
  "**/Migrations/*.Designer.cs": true
}

BookstoreContextModelSnapshot.cs'i bilerek dışarıda bırakmadık: modelin son hâlini gösteren tek dosya o ve migration'la ilgili sorularda agent'ın onu bulabilmesi gerekiyor. Bir uyarı daha: dokümana göre editörde açık olan ya da içinden metin seçtiğin bir dosya için .gitignore devre dışı kalıyor; ignore edilmiş bir .env'i açık bırakmak onu context'e sokabiliyor.

Bookstore: İptal Sorusunu Doğru Sormak

Önce Tahmin Et'e dönelim. Cevabı Copilot'a sormadan önce kendimiz arayalım; agent'ın yapacağı ilk aramalardan biri de buna benzeyecek:

$ git grep -c "Cancel" -- src tests web
src/Bookstore.Api/Catalog/CatalogModule.cs:3
src/Bookstore.Api/Catalog/CatalogService.cs:4
src/Bookstore.Api/Institutional/InstitutionalModule.cs:1
src/Bookstore.Api/Inventory/InventoryService.cs:4
src/Bookstore.Api/Ordering/Order.cs:1
src/Bookstore.Api/Ordering/OrderService.cs:2
src/Bookstore.Api/Ordering/OrderingModule.cs:7
tests/Bookstore.Api.Tests/CatalogTests.cs:3
tests/Bookstore.Api.Tests/InstitutionalTests.cs:1
tests/Bookstore.Api.Tests/OrderingTests.cs:1

$ git grep -nw "Cancelled" -- src tests web
src/Bookstore.Api/Ordering/Order.cs:10:    Cancelled

$ git grep -n "OrderStatus\." -- src
src/Bookstore.Api/Ordering/Order.cs:18:    public OrderStatus Status { get; set; } = OrderStatus.Placed;
src/Bookstore.Api/Ordering/OrderService.cs:51:            Status = OrderStatus.Placed

İlk arama on dosyada 27 satır döndürdü ve neredeyse hepsi CancellationToken: iptal kelimesi .NET'te başka bir anlamda her async method'da geçiyor. Kelimeyi tam eşleştirince tek sonuç kalıyor: enum değeri. Durum alanına atanan tek değer Placed. OrderingModule'de iptal endpoint'i yok, IInventoryService'te ayrılmış stoğu geri bırakan bir method yok. Doğru cevap şu: Bookstore'da bugün sipariş iptal akışı yok; Cancelled yalnız tanımlı bir durum.

Bu, chat için zor bir soru. "Nasıl çalışıyor?" diye sorulan bir soru, cevabın var olduğunu varsayıyor; yalnız Order.cs'i gören bir model için Cancelled değeri bir iptal akışını ima ediyor ve genel bilgisiyle "tipik" bir iptal akışını anlatma riski var. Bunu Copilot ile denemedik; ama soruyu bu riski azaltacak şekilde kurmak elimizde. Ask modunda, ilgili dosyaları açıkça vererek ve "yok" cevabına izin vererek:

Ask mode.
#OrderingModule.cs #OrderService.cs #InventoryService.cs #OrderingTests.cs

Can an order be cancelled in Bookstore today?
If yes: which endpoint, which status transitions, and how the reserved stock is released.
If no: say so, and list what is missing.
Cite file and line for every claim. Do not describe code that is not in these files.

Bu prompt'ta üç şey var. Context dar ve doğru: cevabın olduğu dört dosya, yaklaşık beş bin token. Soru yanlışlanabilir: "nasıl çalışıyor" yerine "var mı, yoksa ne eksik". Ve her iddianın bir dosya ve satıra bağlanması isteniyor; cevabı okurken bunu yukarıdaki git grep çıktısıyla karşılaştırmak birkaç saniye sürer. Cevap "akış yok; eksikler: endpoint, durum geçişi kuralı, stok bırakma" olursa Selin'in sorusunun da cevabı ortaya çıkıyor: bu bir özellik isteği. Sonraki adım Plan: /plan ile iptal akışı için bir plan çıkarmak, planı review etmek ve ancak sonra agent'a uygulatmak.

Uzun Oturum: Context Dolunca

Her modelin bir context penceresi var ve uzun bir oturumda mesajlar, tool çıktıları ve dosya içerikleri bu pencereyi dolduruyor. VS Code, konuşma sınıra yaklaşınca eski kısımları otomatik olarak bir özete sıkıştırıyor (compaction); /compact ile bunu elle de yapabiliyorsun. Copilot CLI aynı işi konuşma token sınırının yüzde 95'ine yaklaşınca arka planda yapıyor. Sıkıştırmanın bedeli, önceki mesajlardaki ayrıntıların kısalması ya da kaybolması.

Bu yüzden bir işi bitirince yeni bir sohbet açmak çoğu zaman sıkıştırmadan iyi. VS Code'da aynı oturum içinde yeni bir chat açmak, workspace'i ve kod değişikliklerini koruyup konuşma geçmişini sıfırlıyor; ilgisiz bir iş için ise yeni oturum öneriliyor. Visual Studio 18.12'de birden fazla Chat oturumunu ayrı sekmelerde açık tutmak mümkün. Kalıcı olması gereken bilgi, örneğin "testler dotnet test ile çalışır", sohbette değil custom instructions'ta durmalı; bir sonraki yazının konusu bu. İlk yazıdaki hesabı da hatırla: her adım bütün konuşmayı yeniden gönderdiği için şişmiş bir oturum hem cevap kalitesini hem kredi tüketimini kötüleştiriyor.

Üretimde Dikkat

Chat'in cevabı dokümantasyon değil. Bir açıklamayı wiki'ye ya da pull request açıklamasına koymadan önce iddialarını kodla doğrula; bu yazıdaki "dosya ve satır göster" kuralı bunu ucuzlatıyor.

Private repo'larda anlamsal arama için Copilot ek izin isteyebiliyor; VS Code bunu açılışta soruyor. GitHub dışındaki repolarda external ingest, dosyaları index için GitHub'a yüklemek demek; kurum politikası bunu bilerek açmalı ya da kapalı tutmalı. Veri yerleşimli (data residency) GitHub Enterprise Cloud ortamlarında ve GitHub Enterprise Server'da external ingest yok.

Content exclusion ile dışarıda bırakılan dosyalar chat'te de kullanılmıyor, ama bu bir dosya sistemi güvenlik sınırı değil; ayrıntısı onuncu yazıda.

Sık Düşülen Tuzaklar

Bütün repoyu context'e vermek. Bookstore'da bunun yarısı tek bir lock dosyası çıktı; cevap gürültüde kayboluyor ve krediler boşa gidiyor.

"Nasıl çalışıyor" diye sormak, var olmayan bir şey için de. Önce "var mı" diye sor ve "yok" cevabına izin ver.

Açık dosyanın tamamının context'te olduğunu varsaymak. Önemli kaynağı # ile açıkça ekle.

Eski tavsiyeleri izlemek: @workspace Copilot harness'ında yok, Edit modu deprecated.

Chat cevabını doğrulamadan dokümantasyon gibi kullanmak. Kod değiştikçe cevap eskir, wiki'deki cümle ise kalır.

Biten işin konuşmasını bir sonraki işe taşımak. Yeni sohbet ucuz; şişmiş context pahalı.

Küçük Bir Deneme

★☆☆ Kendi projende eng/context-size.cs'i çalıştır. En büyük beş dosya toplamın yüzde kaçı? Bunlardan hangileri araçla üretilmiş?

★★☆ Bookstore'a şu soruyu iki şekilde sor: önce yalnız Order.cs açıkken "Ordering module'ünde iptal akışı nasıl çalışıyor?", sonra bu yazıdaki Ask prompt'uyla. İki cevaptaki her iddiayı git grep çıktısıyla karşılaştır ve doğru, yanlış, doğrulanamaz diye işaretle.

★★★ Plan modunda iptal akışı için bir plan çıkart: endpoint, hangi durumlardan iptale izin verildiği, stok bırakma ve testler. Planı Bookstore'un modül kuralına (bir module başka bir module'ün tablosunu okumaz) göre review et ve uymayan adımları düzelt.

Bu yazıda context'i her soruda yeniden kurduk. Bir sonraki yazıda kalıcı olanı kalıcı yere taşıyoruz: copilot-instructions.md, applyTo ile path'e bağlı talimatlar, AGENTS.md ve tekrar eden işler için prompt dosyaları.