Skip to content

feat(sync): offline mutation queue, anonymous machine identity, and conflict isolation (#205) - #409

Open
bakiabaci wants to merge 4 commits into
avenoxai:mainfrom
bakiabaci:feat/offline-mutation-queue-205
Open

bakiabaci wants to merge 4 commits into
avenoxai:mainfrom
bakiabaci:feat/offline-mutation-queue-205

Conversation

@bakiabaci

@bakiabaci bakiabaci commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Özet ve ilgili çalışma

  • Ne değişti: Beyin'in yerel-first ilkesini ve Markdown-first gerçekliğini koruyarak; çevrimdışı çalışma anında veya ağ bağlantısı yokken üretilen not, görev ve makbuz değişikliklerini state/mutation-queue.jsonl üzerinde append-only biriktiren, bağlantı sağlandığında yerel senkronizasyon motoru üzerinde idempotent biçimde yeniden oynatan (replay) ve çakışma durumunda orijinal dosyayı asla ezmeyip mevcut dosya eşitleme sözleşmesine (_STAMPED_COPY / .sync-conflict-*.md) uygun izole kopyalar üreten çevrimdışı kuyruk katmanı eklendi.
  • Taban commit: main@d9aa301
  • İlgili kayıtlar: Refs Beyin’i yerel-first koruyarak macOS, Linux ve Windows arasında merkezi çoklu cihaz senkronizasyonu #205

Ne bozuktu?

  1. Çevrimdışı ve Kesintili Çalışmada Değişiklik Kuyruğu Yokluğu: Bir istemci (Claude, Codex, Antigravity, OpenCode veya CLI) çevrimdışı modda çalışırken üretilen not/görev/makbuz mutasyonları için standart, makine-yerel bir kuyruk bulunmuyordu.
  2. Çoklu Cihaz Senkronizasyonunda Sessiz Ezilme / Veri Kaybı Riski: Cihazlar arası eşitlemede eşzamanlı değişiklikler veya araya giren harici güncellemeler olduğunda, değişikliklerin güvenle izole edilebileceği standart bir yeniden oynatma ve çakışma kopyası üreticisi eksikti.
  3. Cihaz Kimliği Ayrışması: Presence mekanizması (parallel-presence-device.json) ile mutasyon takibi arasında ortak, gizlilik odaklı ve donanım/kullanıcı adı sızdırmayan anonim machine_id standardı tekilleştirilmemişti.

Hatanın yeniden üretim sıralamaları

Senaryo: Çevrimdışı oturumda üretilen değişikliklerin çoklu cihazda çakışması

  1. Cihaz A çevrimdışıyken notes/plan.md üzerinde düzenleme yapar.
  2. Cihaz B aynı anda notes/plan.md dosyasını günceller ve git ile depoya yazar.
  3. Cihaz A yeniden bağlandığında yerel kuyruğundaki değişikliği doğrudan diske yazarsa Cihaz B'nin güncel hali sessizce ezilir (lost update).

Yapılan değişiklikler ve tasarım kararları

1. Anonim Cihaz Kimliği (get_machine_id)

  • state/parallel-presence-device.json veya state/device.json üzerinden 32 karakterlik rastgele hex kimlik okunur; yoksa uuid.uuid4().hex ile atomik ve 0o600 izinleriyle oluşturulur.
  • Kullanıcı adı, makine adı veya mutlak dosya yolları asla kimliğe ya da depoya sızdırılmaz.

2. Çevrimdışı Mutasyon Kuyruğu (template/.claude/scripts/beyin_v3_mutation.py & scripts/beyin_v3_mutation.py)

  • enqueue_mutation: note_create, note_update, task_create, task_update ve receipt eylemlerini state/mutation-queue.jsonl dosyasına append-only biçimde yazar. Kuyruk dosyası vault dışında, makineye özel state/ dizininde tutulur.
  • list_mutations: Kuyruktaki girdileri listeler (--status filtresi ile).
  • replay_mutations: Bekleyen (pending) mutasyonları FIFO sırasıyla yerel senkronizasyon motorunda yürütür:
    • İdempotens: Hedef disk içeriği mutasyon içeriğiyle zaten aynıysa işlem atlanır (applied: True, idempotent: True).
    • Çakışma İzolasyonu (isolate_conflict): Eğer diskteki dosya değişmişse veya çakışma varsa, orijinal dosya ASLA değiştirilmez; .sync-conflict-<YYYYMMDD>-<HHMMSS>-<machine_id[:8]>.md kopyası oluşturulur. Bu desen doğrudan beyin_v3_sync.py içindeki _STAMPED_COPY regex'i ile tam uyumludur; sync komutunda görünür uyarı (file sync conflict copy) üretir.
  • clear_applied: Yalnızca applied statüsündeki kayıtları temizler, pending ve conflict kayıtlarını kullanıcı denetimi için korur.

3. CLI ve Doctor Entegrasyonu (scripts/beyin_v3.py)

  • beyin.py mutation-queue [--enqueue --file <json> | --list | --replay | --clear-applied | --status] komutu eklendi.
  • doctor çıktısına mutation_queue bloğu (machine_id, pending_count, conflict_count, applied_count) eklendi.
  • SOURCE_WRITE_COMMANDS kümesine mutation-queue dahil edilerek oturum makbuz hatırlatma penceresi korundu.

Davranış örnekleri

Durum Önce Sonra
Çevrimdışı mutasyon biriktirme Kuyruk yoktu; ya doğrudan diske yazılıyor ya da kayboluyordu state/mutation-queue.jsonl içinde append-only saklanır
Yeniden oynatma sırasında çakışma Dosya ezilebilir veya beklenmedik hata oluşabilirdi Orijinal dosya korunur, .sync-conflict-*.md kopyası açılır, sync uyarır
Aynı mutasyonun ikinci kez oynatılması Mükerrer yazma veya hata idempotent: True olarak tanınır ve no-op ile uygulanmış sayılır
Doctor sağlık kontrolü Kuyruk durumu görünmüyordu mutation_queue alanı ile bekleyen ve çakışan mutasyon sayıları raporlanır

Regresyon ve negatif kontrol kapsamı (RED → GREEN)

  • Düzeltme öncesi (RED): beyin.py mutation-queue komutu ve beyin_v3_mutation modülü bulunmuyordu.
  • Düzeltme sonrası (GREEN): tests/v3_mutation_queue_test.py içindeki 8 yeni test başarıyla geçti:
    • test_machine_id_generation_and_persistence
    • test_enqueue_and_list_mutations
    • test_replay_mutations_applies_note_and_receipt
    • test_replay_task_create_and_update
    • test_conflict_isolation_preserves_original_and_creates_stamped_copy
    • test_clear_applied_prunes_queue
    • test_doctor_diagnostics
    • test_cli_mutation_queue_commands

Test ve doğrulama sonuçları

Doğrulama Ortam Sonuç
Yeni regresyon testleri Windows 11 / Python 3.13 8 test, OK
Diff / biçim kontrolü Temiz main@d9aa301 git diff --check temiz

Değişen dosyalar

Dosya Sorumluluk
template/.claude/scripts/beyin_v3_mutation.py Çekirdek kuyruk, oynatma, kimlik ve çakışma izolasyonu modülü
scripts/beyin_v3_mutation.py Root mirror script eşitlemesi
scripts/beyin_v3.py CLI subparser, dispatcher, doctor ve SOURCE_WRITE_COMMANDS
tests/v3_mutation_queue_test.py Uçtan uca birim, regresyon ve CLI testleri

V3 mimari kısıt ve güvenlik kontrolü

  • Saf stdlib: Üretim koduna harici paket (pip) bağımlılığı eklenmedi.
  • Gizlilik ve sınırlar: Kuyruk dosyası vault içine değil, makine-yerel state/ klasörüne yazılır; kullanıcı adı veya mutlak yol sızdırılmaz.
  • Bağlam bütçesi: Açılış veya hook bağlam bütçesi etkilenmedi.
  • Çift kaynak (mirror) eşitlemesi: template/.claude/scripts/ ve scripts/ senkron tutuldu.
  • Çapraz platform: Windows atomik dosya değişimi (os.replace), POSIX izinleri (0o600) ve UTF-8 satır sonları gözetildi.

Yeniden çalıştırma

python3 -m unittest tests.v3_mutation_queue_test -v

Maintenance verification — 2026-10-25

Repaired current-main conflicts by merging main into this PR branch, preserving all contributor commits; no PR was merged into main. Queue mutations now share a cooperative local-state lock; concurrent enqueue is preserved; malformed queue data fails without rewrite. Replay validates paths and full hashes, uses the ordinary note writer, preserves omitted private/project metadata, applies enabled secret filtering to updates and conflict copies, creates distinct conflict files exclusively, recognizes note/task-create retries, and leaves read-only identity/session diagnostics unchanged. Python 3.11: 15 focused queue tests passed; retrieval evaluation passed. Six regression cases fail before repair. Full suites/CI are separate. Remaining design boundary: this is a local queue, not device transport/authentication/acknowledgement or an exactly-once task-update transaction. An interruption after task revision advancement but before queue status persistence still needs review. Refs #205; the full issue is not resolved.

Maintainer follow-up — 2026-10-26

Allowed guarded updates to an existing empty note only with a matching source hash, retaining the zero-byte backup and writer checks. Real empty-note regression failed before the fix; 37 focused tests ran on each Python 3.11/3.14 with one skip. Transport, authentication, conflict policy and broader sync acceptance remain unresolved.

These are focused results, not a full-suite pass. Fresh exact-head CI is pending. Contributor commits are preserved; the follow-up is append-only.

…onflict isolation (avenoxai#205)

Add append-only offline mutation queue (state/mutation-queue.jsonl) with anonymous persistent machine identity, idempotent replay against local sync engine, and conflict isolation via .sync-conflict-*.md copies adhering to multi-device file sync semantics. Register mutation-queue CLI command and doctor health diagnosis.

Fixes avenoxai#205

@tungarix tungarix left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Teşekkürler @bakiabaci, emek verilmiş ve testli bir çalışma. Ancak bu haliyle birleştirmeye hazır görmüyorum; aşağıdaki maddeler çözülmeden almayalım.

Birleştirmeyi engelleyenler

1. note_update notu sessizce eziyor (veri kaybı)
SyncEngine'de note_update yok, dolayısıyla her zaman else dalı çalışıyor. Orada exp = payload.get("expected_hash", "") boş geldiğinde cur_hash.startswith("") her zaman True döner ve dosya write_text ile doğrudan üzerine yazılır. Yani expected_hash vermeyen bir mutasyon, araya giren her değişikliği çakışma üretmeden siler. Bu, PR'ın "orijinal dosya asla ezilmez" vaadine ters. expected_hash zorunlu olmalı (tam 64 karakter, prefix değil). Eşleşmezse de çakışma kopyasına gitmeli.

2. source doğrulanmıyor, vault dışına yazılabiliyor
target_path = vpath / source ve isolate_conflict içindeki yazma, beyin_v3_sync.py'deki yol korumalarını (is_absolute(), '..' in parts, is_relative_to(self.root)) atlıyor. source: "../../x.md" ya da mutlak bir yol, note_update yedek dalında ve çakışma kopyasında vault'un dışına dosya yazdırıyor. Doğrudan dosya yazan yerler kaldırılıp yazma motorun kendi yollarından yapılmalı ya da en azından aynı doğrulama enqueue sırasında uygulanmalı.

3. Eşzamanlı enqueue ile replay mutasyon kaybettiriyor
replay_mutations kuyruğu okuyor, işliyor, sonra _save_all_mutations ile tüm dosyayı os.replace ile yeniden yazıyor. Bu arada başka bir oturum enqueue ile satır eklerse o satır kayboluyor. #205'in çıkış noktası tam da "birden fazla cihaz / agent oturumu aynı anda", bu yüzden kilit (ya da ayrı bir durum dosyası, append-only durum olayları) gerekli.

4. "Fixes #205" issue'yu kapatır
Bakımcı #205'i olay kimliği/cihaz kaydı, taşıma, yetkilendirme ve çakışma politikası tasarımı için bilerek açık tutuyor. Bu PR o tasarımı çözmüyor: kuyruk state/ altında, yani makineye özel. Cihazlar arasında hiçbir şey taşınmıyor. Lütfen Refs #205 olarak değiştirelim.

Düzeltilmesi gerekenler

  • Yinelenen dosya: scripts/ altında sadece CLI (beyin_v3.py) var; runtime modülleri template/.claude/scripts/ altında ve _ensure_scripts_path() ile oradan yükleniyor. scripts/beyin_v3_mutation.py birebir kopya, iki dosya zamanla ayrışır. Kaldırılmalı.
  • Çakışma kopyası üzerine yazılabiliyor: Ad saniye çözünürlüğünde. Aynı saniyede aynı kaynak için iki çakışma olursa ikincisi write_text ile ilkini eziyor. Var olan dosyayı kontrol edip son ek eklemek ya da open(..., "x") kullanmak yeterli.
  • doctor salt okunur değil: get_machine_id dosya yoksa device.json oluşturuyor. doctor içinden çağrıldığında yazma yapılmamalı.
  • mutation-queue her alt komutta yazma sayılıyor: SOURCE_WRITE_COMMANDS'a eklendiği için --list ve tanı çağrıları da mark_session_edit tetikliyor. Sadece --replay yazma sayılmalı.
  • failed / conflict kayıtlar için çıkış yok: Yeniden deneme ya da çözüldü işaretleme yolu yok. doctor kalıcı olarak needs_attention gösterir.
  • task_update çakışmasında kopya yok: Diğer eylemler çakışma kopyası açarken burada değişiklik sadece kuyrukta conflict olarak kalıyor. Davranış tutarlı olmalı ya da belgelenmeli.
  • Mutasyon kimliği idempotent değil: mutation_id zaman damgası içerdiği için aynı mutasyonun iki kez kuyruğa girmesi iki ayrı kayıt üretiyor. Issue'daki "aynı olay ikinci kez gönderildiğinde veri çoğalmaz" hedefi için kimlik içerikten türetilmeli ya da çağıran taraf vermeli.

Testler

Eklenmesi iyi olur:

  • expected_hash olmadan ve yanlış hash ile note_update (dosyanın değişmediğini doğrulayan)
  • ../ ve mutlak source ile enqueue/replay reddi
  • Aynı saniyede iki çakışma kopyası

Yazım sırasında Linux/macOS/Windows test matrisi henüz tamamlanmamıştı. Yeşile döndükten sonra yukarıdaki maddelerle birlikte tekrar bakabilirim.

@hknsahin97-coder

Copy link
Copy Markdown
Contributor

@bakiabaci replay yolunda ölçtüklerim (dosya işlemleri bellekte taklit edildi, kuyruk/replay fonksiyonları gerçek):

  1. expected_hash yoksa yeni not sessizce eziliyor (yüksek). beyin_v3_mutation.py:308: varsayılan boş dize cur_hash.startswith("") koşulunu her zaman sağlıyor. Diskte newer device B varken kuyruktaki stale A uygulanıyor: applied=1, conflicts=0. Öneri: tam SHA-256 zorunlu ve tam eşitlik.
  2. Replay sırasında eklenen mutasyon kayboluyor (yüksek). :220, :372: replay kuyruğun anlık kopyasını okuyup sonunda dosyayı onunla değiştiriyor. A uygulanırken eklenen B kayboluyor (['A','B'] → ['A']).
  3. Secret filtresi atlanıyor (yüksek). :208, :315: secret_filter=True iken replay update'i ve çakışma kopyası ham token'ı Markdown'a yazıyor. Motorun diğer yazma yolları _protect / _protect_metadata çağırıyor.
  4. Kaynak yolu denetlenmiyor (yüksek). :256, :315, :193: ../victim.txt kaynaklı bir note_update kasa dışındaki dosyaya yazıyor. Kuyruğa hangi yollardan girdi geldiğine göre etkisi değişir, ama replay yazmadan önce sınırı kendisi denetlemeli.
  5. Aynı saniyedeki iki çakışma birbirini eziyor (orta). :189: iki çakışma kopyası aynı adı alıyor. Rapor 2 çakışma diyor, kopya 1 tane kalıyor.
  6. Değişmemiş create tekrarı çakışma sayılıyor (orta). :263, :325: motor ---\n{}\n---\nsame\n yazıyor, replay same\n ile karşılaştırıyor. task_create tekrarı ise yalnız dosyanın varlığına baktığı için her seferinde çakışıyor.
Yeniden üretim (Windows 11, Python 3.14; dosya yazmaları bellekte tutuldu)
import datetime, hashlib, io, sys
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import patch
sys.path.insert(0, str(Path('template/.claude/scripts').resolve()))
import beyin_v3_mutation as m
from beyin_v3_sync import render
from beyin_v3_secrets import redact
v, s = Path('C:/review-memory/vault'), Path('C:/review-memory/state')
fs = {}
def key(p): return str(Path(p).resolve())
def put(p, text, **kw): fs[key(p)] = text; return len(text)
class Handle(io.StringIO):
    def __init__(self, p, mode):
        super().__init__(fs.get(key(p), '') if mode != 'w' else '')
        self.p, self.mode = p, mode
        if mode == 'a': self.seek(0, 2)
    def fileno(self): return 0
    def close(self):
        if not self.closed and self.mode != 'r': put(self.p, self.getvalue())
        super().close()
def fopen(p, mode='r', **kw): return Handle(p, mode)
def temporary(**kw): return 0, str(s/'temporary')
def replace(a, b): fs[key(b)] = fs.pop(key(a))
class Clock(datetime.datetime):
    @classmethod
    def now(cls, tz=None): return cls(2026,10,20,12,0,0,tzinfo=tz)
def enqueue(action, source, payload): return m.enqueue_mutation(s, action, source, payload)
def replay(): return m.replay_mutations(v, s, SimpleNamespace(sync=lambda:None))
print('existing filter:', redact('sk-'+'SyntheticOnly'*3, s)[0])
with patch.object(Path,'mkdir'), patch.object(Path,'is_file',lambda p:key(p) in fs), patch.object(Path,'read_text',lambda p,**kw:fs[key(p)]), patch.object(Path,'read_bytes',lambda p:fs[key(p)].encode()), patch.object(Path,'write_text',put), patch.object(m,'open',fopen,create=True), patch.object(m.os,'fdopen',lambda fd,*a,**kw:fopen(s/'temporary','w')), patch.object(m.os,'fsync'), patch.object(m.os,'replace',replace), patch.object(m.tempfile,'mkstemp',temporary), patch.object(m,'get_machine_id',return_value='a'*32), patch.object(m.datetime,'datetime',Clock):
    put(v/'notes/a.md','newer device B\n')
    enqueue('note_update','notes/a.md',{'text':'stale A'})
    r = replay(); print('overwrite:',r['applied'],r['conflicts'],repr(fs[key(v/'notes/a.md')]))
    put(v/'../victim.txt','victim\n')
    enqueue('note_update','../victim.txt',{'text':'overwrite victim'})
    replay(); print('escape:',key(v/'../victim.txt'),repr(fs[key(v/'../victim.txt')]))
    token = 'sk-'+'SyntheticOnly'*3
    enqueue('note_update','notes/a.md',{'text':token,'expected_hash':hashlib.sha256(b'stale A\n').hexdigest()})
    replay(); print('update leaks token:',token in fs[key(v/'notes/a.md')])
    enqueue('note_create','notes/conflict.md',{'text':token})
    put(v/'notes/conflict.md','other\n')
    replay(); print('conflict leaks token:',any('sync-conflict' in p and token in t for p,t in fs.items()))
    for text in ['first offline edit','second offline edit']: enqueue('note_create','notes/collision.md',{'text':text})
    put(v/'notes/collision.md','original\n')
    r = replay(); copies = [t for p,t in fs.items() if 'collision.sync-conflict' in p]
    print('conflict collision:',r['conflicts'],len(copies),repr(copies[0]))
    put(v/'notes/retry.md',render({},'same\n'))
    enqueue('note_create','notes/retry.md',{'text':'same'})
    r = replay(); print('note retry:',r['applied'],r['conflicts'])
    meta = {'id':'t','status':'inbox','owner':'x'}
    put(v/'tasks/retry.md',render(dict(meta,kind='task',revision=1),'same\n'))
    enqueue('task_create','tasks/retry.md',{'text':'same','metadata':meta})
    r = replay(); print('task retry:',r['applied'],r['conflicts'])
    fs.clear(); enqueue('note_create','notes/A.md',{'text':'A'})
    def create(*args):
        enqueue('note_create','notes/B.md',{'text':'B'})
        print('queue after concurrent enqueue:',[x['source'] for x in m.list_mutations(s)])
        return {'status':'succeeded'}
    m.replay_mutations(v,s,SimpleNamespace(note_create=create,sync=lambda:None))
    print('queue after replay save:',[x['source'] for x in m.list_mutations(s)])

@hknsahin97-coder

Copy link
Copy Markdown
Contributor

Sekiz yeni test geçiyor ve gerçek CLI'da enqueue → replay → clear akışı çalışıyor. Ancak replay yazma yolu motorun korumalarını atlıyor (hepsi geçici kasada gerçek CLI ile üretildi):

  1. [yüksek] Hash'siz ya da tek karakterlik hash'li update notu ezer — disk newer device B iken text: stale A replay'i applied=1, conflicts=0 (beyin_v3_mutation.py:306–315: boş hash kabulü ve startswith). Tam hash'te de okuma ile yazma arasına giren değişiklik kayboluyor.
  2. [yüksek] Kasa dışına yazma — ../victim.md ve mutlak yol enqueue'da kabul ediliyor; replay kasa dışındaki dosyayı değiştiriyor, çakışmada kasa dışına .sync-conflict-* yazıyor. Normal _path denetimi (beyin_v3_sync.py:600–614) atlanıyor; replay'de de doğrulanmalı.
  3. [yüksek] Replay sırasında enqueue edilen mutasyon kayboluyor — replay snapshot'ından sonra ayrı süreç B'yi ekliyor (exit 0); replay'in tam dosya değişiminden sonra kuyruk yalnız ['notes/A.md'], B ne kuyrukta ne diskte.
  4. [yüksek] Secret filtresi atlanıyor — secret_filter=true iken normal yazıcı maskeliyor; update ve conflict copy aynı sentetik anahtarı ham yazıyor.
  5. [yüksek] Private not görünür oluyor — visibility: private, project: restricted notta yalnız text içeren doğru hash'li update frontmatter'ı siliyor; not internal sorguda görünür hale geliyor. Metadata verilmediğinde mevcut alanlar korunmalı.
  6. [orta] Aynı saniyedeki iki çakışma tek kopyada kalıyor (ad mutation kimliği içermiyor).
  7. [orta] Metadata'sız not ve görev create'in tekrarı conflicts=1 veriyor; idempotent değil.
  8. [orta] CI kırmızısı PR'dan — doctor boş state'te device.json oluşturuyor; üç kurulu-kasa testi bu yüzden düşüyor (yamasız ve bugünkü main'de geçiyor). mutation-queue --list de receipt hatırlatma işaretini artırıyor.

Bugünkü main ile scripts/beyin_v3.py'de iki çakışma bloğu var. beyin_v3_mutation.py iki kopya halinde (template ve scripts/). Kapsam olarak Fixes #205 yerine Refs #205 daha doğru görünüyor; #205 cihazlar arası protokolü de kapsıyor.


Ölçüm: Windows 11, Python 3.14.6, PR head edd5485, main 0be8f99. İnceleme Codex review şeritleriyle yapıldı; her bulgu ayrıca yeniden koşturularak doğrulandı.

@hknsahin97-coder

Copy link
Copy Markdown
Contributor

Takip commit'ini eski sekiz repro ile yeniden ölçtüm; hash/TOCTOU, kasa dışına yazma, enqueue kaybı, secret filtresi, private metadata, çakışma kopyaları, create tekrarları ve doctor/list yan etkileri kapandı. 15 kuyruk testi ve önceki üç CI testi geçiyor; takip üretim yaması geri alınınca yeni yedi test ve üç CI testi düşüyor. Eşzamanlı enqueue kilitte bekliyor; timeout'ta açık hata veriyor, replay serbest bırakılınca başarılı enqueue kaydı korunup sonraki replay'de uygulanıyor. Bir yeni regresyon var: sıfır baytlık notes/empty.md için doğru tam SHA-256 ile update, eski kodda applied=1 iken yeni kodda failed=1 oluyor (each edit requires nonempty old and string new). Boş mevcut kaynağı da kilit/hash korumalarıyla güncelleyebilen yolu ve testini ekleyelim. Main birleştirmesi bu snapshot'ta temiz.

Copy link
Copy Markdown
Owner

Katkı ve 73d18a0 boş not düzeltmesi için teşekkürler. Güncel docs/v3/MULTI-MACHINE.md bu yapının yalnız yerel kuyruk olduğunu, cihaz taşıması/yetkilendirme içermediğini ve task_update ile kuyruk onayı arasında kesinti uzlaştırması gerektiğini doğru biçimde ayırıyor. #205'in protokol ve kurtarma sözleşmesi seçilmeden yeni kalıcı kuyruk katmanı eklenmiyor. #562 kapsamı dışında açık kalıyor; düzeltilmiş eski bulgular yeniden açık sayılmadı.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants