Langkau ke kandungan

Multipemain — identiti, keahlian dan kehadiran

Control Center berfungsi untuk seorang pengendali, tetapi model di bawahnya bersifat pelbagai pelaku sejak awal. Manusia dan ejen menghantar mesej dalam ruang yang sama, menyunting tiket yang sama dan muncul dalam senarai ahli yang sama. Menjadikan perkara itu selamat dan mudah difahami berpulang kepada tiga keputusan: siapa yang dikira sebagai pelaku, apa yang mengawal akses dan keadaan mana yang dikongsi secara tahan lama berbanding hanya disiarkan secara langsung.

Prinsipal: pengguna dan ejen ialah pelaku setara

Bahagian bertajuk “Prinsipal: pengguna dan ejen ialah pelaku setara”

Segala yang merekodkan “siapa melakukan ini” — mesej, tiket, semakan, pelan, log larian, entri audit — diselesaikan melalui Prinsipal, kesatuan termeterai bagi UserPrincipal dan AgentPrincipal dengan bentuk wayar yang padat (user:<id> / agent:<id>). Atribusi tidak pernah meruntuhkan N manusia (atau N ejen) menjadi satu akaun sentinel, jadi semakan yang ditinggalkan oleh ejen dan semakan yang ditinggalkan oleh manusia boleh dibezakan di mana-mana ia muncul.

Oleh sebab prinsipal ialah unit identiti, ia juga unit pembendungan:

  • Had kadar dikenakan bagi setiap prinsipal, bukan setiap sesi. Pengawal limpahan pada panggilan alat jauh membajetkan mengikut pengguna, bukan mengikut sambungan: semua peranti seorang ahli menarik daripada satu tetingkap gelongsor yang dikongsi (120 panggilan seminit, yang mana paling banyak 30 boleh mengubah data), jadi membuka tiga peranti tidak menggandakan elaun sesiapa dan seorang ahli yang bising tidak boleh membuat yang lain kebuluran.
  • Pembatalan tindakan dikenakan bagi setiap prinsipal. Jurnal tindakan setiap klien merekodkan hanya mutasi yang dilakukan oleh prinsipal miliknya. Anda boleh ⌘Z suntingan tiket anda sendiri; anda tidak boleh membatalkan tindakan rakan sepasukan — apabila anda melihatnya, lorong tahan lama sudah menyelesaikannya (lihat di bawah).

Keahlian ialah sempadan akses — bukan kunci pasangan

Bahagian bertajuk “Keahlian ialah sempadan akses — bukan kunci pasangan”

Dua kelayakan berasingan menjawab dua soalan berasingan. Kunci pasangan (lihat Kawalan jauh dan mudah alih) mengesahkan peranti kepada pelayan. Keahlian memberi kebenaran kepada pengguna peranti itu untuk bertindak di dalam ruang kerja. Peranti yang telah digandingkan tidak boleh membaca mahupun mengubah sesuatu ruang kerja jika penggunanya tidak memegang keahlian di dalamnya.

Keahlian ialah satu baris bagi setiap (ruang kerja, pengguna), disimpan dalam fail pangkalan data ruang kerja itu sendiri — jadi “siapa ada dalam ruang kerja ini?” ialah bacaan berskop yang biasa, manakala soalan songsangnya, “ruang kerja mana yang saya sertai?”, semestinya merentasi fail dan merupakan salah satu daripada sedikit fan-out merentas ruang kerja yang dibenarkan. Inilah yang dijalankan oleh pemilih ruang kerja sebelum mana-mana ruang kerja dipilih.

Setiap baris membawa peranan daripada tangga lima tingkat yang tersusun mengikut pangkat:

Peranan Boleh
owner Kawalan penuh, termasuk pemadaman ruang kerja; tepat satu bagi setiap ruang kerja
admin Mengurus ahli, jemputan, tetapan, operasi memusnah
member Baca-tulis harian: mesej, tiket, larian ejen
viewer Baca sahaja merentas ruang kerja; glob pengecualian laluan rahsia menyembunyikan laluan yang sepadan pada permukaan yang membawa kod
guest Paras baca sahaja yang sama seperti pemapar, pada pangkat terendah dalam tangga

Setiap keputusan akses berpulang kepada “adakah peranan pemanggil sekurang-kurangnya X”. Paras minimum itu diterbitkan daripada jenis operasi melainkan operasi itu mengisytiharkan satu secara eksplisit: bacaan memerlukan guest, mutasi memerlukan member, operasi memusnah memerlukan admin. ACL setiap objek di luar geran setiap repositori di bawah sengaja berada di luar skop.

Jemputan ialah cara keahlian diberikan, dari Tetapan → Ruang kerja → Ahli. Seorang pentadbir menjana kod sekali guna (sebagai pautan atau QR) yang luput selepas tujuh hari secara lalai; pelayan menyimpan hanya hash SHA-256 kod itu dan kod itu sendiri ditunjukkan sekali sahaja. Menebusnya memperuntukkan pengguna secara JIT, merekodkan keahlian pada peranan jemputan itu (tidak pernah owner — pemilikan dipindahkan secara eksplisit, tidak pernah diberikan melalui jemputan) dan menyerahkan kepada penggandingan peranti. Kelayakan peranti yang dijana selepas penggandingan juga dihadkan masa kepada 30 hari, jadi penggandingan bukan kunci kekal.

Geran repositori terletak di bawah keahlian. Oleh sebab pelayan memegang checkout penuh, keahlian ruang kerja sahaja tidak boleh sekali-kali melebihi keistimewaan hos kod: setiap permukaan yang membawa kod — fail, diff, semakan PR, carian kod — menyemak geran ahli pada repo itu. Geran adalah bagi setiap (ruang kerja, pengguna, repo) dan berpangkat none → read → review → write, yang mana write bermaksud memandu larian ejen yang menulis ke repo itu. Ketiadaan baris bermaksud none; pemilik dan pentadbir secara tersirat memegang write pada setiap repo terpaut dan tidak membawa baris sama sekali.

Control Center memisahkan keadaan dikongsi kepada dua lorong dengan peraturan ketahanan yang bertentangan, kerana kedua-dua jenis keadaan itu gagal dengan cara yang bertentangan.

Kehadiran — siapa dalam talian, di mana mereka berada, apa yang mereka menaip, apa yang ejen sedang lakukan sekarang — tidak bernilai sebaik sahaja ia lapuk. Jika ia disimpan secara berterusan, setiap sambungan semula perlu mendamaikan “pangkalan data mengatakan Sam sedang menyunting tiket ini” dengan realiti. Jadi kehadiran tidak pernah ditulis ke pangkalan data. Ia hidup dalam hab kehadiran dalam memori pada pelayan: klien menerbitkan dengan presence.update, rakan sebaya melanggan dengan presence.watch dan entri luput secara automatik selepas tiga denyutan yang terlepas (denyutan berjalan setiap 10 saat; hab menyapu setiap 5). Tiada apa untuk didamaikan — hanya untuk dibiarkan luput.

Dua sifat memastikan lorong itu boleh dipercayai:

  • Identiti datang daripada sesi, tidak pernah daripada argumen klien. Pelayan memetakan peranti yang disahkan bagi sambungan itu kepada id pengguna; klien hanya boleh mengemas kini kehadirannya sendiri, jadi tiada sesiapa boleh memalsukan status atau lokus peserta lain. Kemas kini offline yang eksplisit (putus sambungan atau togol halimunan) membuang entri itu serta-merta.
  • Senarai ahli berhab di pelayan. Rakan sebaya tidak pernah bertukar kehadiran secara langsung, jadi setiap peserta melihat senarai ahli yang sama tanpa mengira topologi. Ejen tiada klien, jadi pelayan mensintesis entri mereka daripada keadaan larian langsung — berfikir, berjalan, tersekat pada pintu kelulusan, selesai — dengan satu larian perwakilan tunggal menentukan keadaan dan lokus ejen supaya larian serentak tidak membuat senarai ahli berubah-ubah.

Fan-out berlapis mengikut pengguna: desktop dan web menaiki lapisan penuh (paling banyak satu pelepasan senarai ahli setiap 100 ms), telefon lapisan ringkasan (setiap 500 ms), jadi kemas kini sekerap kursor tidak boleh melumpuhkan PWA.

Lokus seseorang peserta — di mana mereka berada sekarang, hingga ke peringkat artifak — ialah kesatuan termeterai: Space, File (repo + laluan + baris pilihan), Pr, Ticket, PlanNode. Bukan setiap lokus mempunyai destinasi untuk dilompati: tiada laluan pemapar fail, jadi lokus File dipaparkan sebagai label dan bukan destinasi. Lorong ini juga membawa tuntutan lembut (“Sam sedang menyunting tiket ini”, “seorang ejen memegang worktree ini”): keterlihatan konflik, bukan kunci. Jenis lokus yang tidak diketahui dihuraikan kepada null, jadi klien lama tidak memaparkan apa yang ia tidak faham.

Rekod yang mesti kekal — tiket, dokumen Nota ruang yang dikongsi, mesej — mengambil laluan bertentangan: berwibawa, tersusun dan disimpan secara berterusan. Suntingan serentak diselesaikan dengan penulis terakhir menang mengikut urutan penerimaan pelayan, tidak pernah mengikut jam klien. Penyelesaiannya sengaja halus: suntingan tiket adalah mengikut lajur, jadi dua orang yang menyunting medan berbeza pada tiket yang sama kedua-duanya berjaya dan tiada satu pun menimpa yang lain (peralihan aliran kerja sebaliknya mengekalkan penguncian optimistik); dokumen Nota ruang ialah satu lajur, jadi keseluruhan dokumen itu LWW dengan tuntutan lembut pada lorong kehadiran menjadikan suntingan serentak kelihatan dan bukannya dikunci. Ia sengaja bukan CRDT — beban pembuktian terletak pada CRDT dan LWW mengikut urutan penerimaan serta tuntutan yang kelihatan meliputi corak kerjasama sebenar.

“Penulis terakhir” bermaksud urutan penerimaan pelayan, tidak pernah jam klien — komputer riba dengan jam yang tersasar tidak boleh memenangi suntingan yang telah ia kalah. Di belakang lorong tahan lama terletak suapan segerak: pencetus SQLite menambahkan setiap mutasi pada log perubahan setiap ruang kerja di dalam transaksi penulisan, sambil memperuntukkan nombor jujukan monotonik setiap ruang kerja dalam transaksi yang sama dengan mutasi itu sendiri. Satu perkhidmatan pelayan mengekori log itu menjadi bingkai delta berversi mengikut urutan jujukan. Klien berkembang daripada snapshot penuh kepada delta; jurang dalam jujukan menjatuhkan stor itu kembali ke modus snapshot dan bukannya tersalah menggunakan bingkai.

Lorong kehadiran bukan sekadar senarai ahli — ia memacu kata kerja kerjasama:

  • Modus ikut. Klik seorang peserta dan klien anda menaiki lokus mereka, menavigasi semasa mereka menavigasi. Ikut berlangsung “sehingga anda bertindak”: sebaik sahaja anda menavigasi sendiri, ikut terlepas. Sepanduk yang boleh ditutup mengumumkan apabila peserta lain sedang membentangkan (mempersembahkan) ruang yang anda sertai.
  • Kemudi. Mesej kepada ejen yang sedang berjalan dibariskan sebagai kemudi; ejen membacanya semula sebelum menyambung giliran seterusnya, jadi anda boleh menggesa sesuatu larian di pertengahan tanpa mematikannya.
  • Ambil alih. Mengambil kawalan sesuatu perbualan menghentikan sementara setiap larian aktif pada sempadan giliran bersih yang berikutnya (larian Claude Code, yang tiada sempadan selamat, dihentikan) di sebalik snapshot git setiap giliran, jadi pengambilalihan itu boleh dibalikkan. Penanda tahan lama menyekat penghantaran baharu ke dalam ruang itu dan bertahan selepas pelayan dimulakan semula — pelayan tidak pernah menyambung semula secara automatik ke dalam suntingan manusia yang separuh siap. Satu penyunting langsung bagi setiap worktree ialah tuntutan lembut: pengambilalihan kedua kelihatan dan ditolak, bukan digabungkan secara senyap.
  • Serahkan semula. Memulangkan kawalan menyiarkan ringkasan diff berstruktur bagi worktree itu ke ruang, membariskannya sebagai kemudi untuk larian yang dihentikan sementara, menyambung semula larian itu dan mengosongkan penanda.

Kemudi dan pengambilalihan ialah campur tangan selepas kejadian. Dail autonomi ialah tetapan yang sentiasa berkuat kuasa: bagi setiap ruang, bagi setiap ejen, ditetapkan dari pengepala ruang, ia menentukan apa yang berlaku apabila ejen sampai ke tindakan berpintu.

Tahap Nilai wayar Kesan pada panggilan alat berpintu
Cadang sahaja proposeOnly Ditolak terus, dengan sebab yang ejen diberitahu untuk menyampaikannya — ia boleh menerangkan tindakan itu tetapi tidak boleh melakukannya
Bertindak dengan kelulusan actWithApproval Pintu kelulusan gagal-tertutup: satu pengesahan muncul kepada pengendali yang bersambung dan tiada pelulus bermakna ditolak
Bertindak bebas actFreely Diluluskan terlebih dahulu, kecuali apabila peraturan guardrail deny yang keras terpakai — peraturan deny sentiasa menang
(tidak ditetapkan) null Sama seperti bertindak dengan kelulusan: lalai pelayan

Dua perkara berada di luar dail dalam kedua-dua arah. Kata kerja keluaran sesuatu modus dipaku dan tidak pernah boleh ditolak, apa sahaja yang dail katakan — modus orchestrate pernah secara struktur tidak dapat mengeluarkan satu-satunya hasilnya kerana satu praset menolak jenis kesan yang diisytiharkan oleh kata kerja itu. Dan deny yang keras daripada guardrail tindakan tidak boleh diatasi oleh actFreely.

Semua ini bersifat tambahan. Aliran kerja pengendali solo tidak berubah: dengan satu manusia dan tiada ejen, hab kehadiran tiada apa untuk disiarkan, jadi lorong itu memancarkan snapshot awalnya dan kemudian melahu pada trafik sifar; jentera LWW dan segerak ialah laluan penulis tunggal yang sama seperti dahulu; dan kunci pasangan kekal sebagai kelayakan peranti yang memang sentiasa begitu. Keahlian sudah menjadi sempadan akses — dengan satu manusia, terdapat satu baris pemilik tunggal dan tiada hiasan senarai ahli.