مواد پر جائیں

ملٹی پلیئر — شناخت، رکنیت اور موجودگی

Control Center ایک ہی آپریٹر کے لیے کام کرتا ہے، مگر اُس کے نیچے کا ماڈل شروع ہی سے متعدد اداکاروں والا ہے۔ انسان اور ایجنٹ ایک ہی اسپیسز میں پیغام بھیجتے ہیں، ایک ہی ٹکٹس میں ترمیم کرتے ہیں اور ایک ہی روسٹر پر نظر آتے ہیں۔ اِسے محفوظ اور قابلِ فہم بنانا تین فیصلوں پر اُتر آتا ہے: اداکار کون گنے جاتے ہیں، رسائی کا دروازہ کیا ہے اور کون سی حالت پائیدار طور پر مشترک ہوتی ہے اور کون سی صرف براہِ راست نشر۔

پرنسپل: صارفین اور ایجنٹس ہم مرتبہ اداکار ہیں

سیکشن کا عنوان “پرنسپل: صارفین اور ایجنٹس ہم مرتبہ اداکار ہیں”

”یہ کس نے کیا“ درج کرنے والی ہر چیز — پیغامات، ٹکٹس، ریویوز، پلانز، رن لاگز، آڈٹ اندراجات — ایک پرنسپل سے گزر کر طے ہوتی ہے: UserPrincipal اور AgentPrincipal کا ایک سِیل بند اتحاد، جس کی وائر شکل مختصر ہوتی ہے (user:<id> / agent:<id>)۔ انتساب کبھی N انسانوں (یا N ایجنٹس) کو ایک ہی سینٹینل اکاؤنٹ میں سمو نہیں دیتا، اس لیے کسی ایجنٹ کا چھوڑا ہوا ریویو اور کسی شخص کا چھوڑا ہوا ریویو جہاں بھی سامنے آئیں، الگ پہچانے جاتے ہیں۔

چونکہ پرنسپل شناخت کی اکائی ہے، یہی محدود رکھنے کی اکائی بھی ہے:

  • ریٹ لمٹس فی پرنسپل ہیں، فی سیشن نہیں۔ ریموٹ ٹول کالز پر فلڈ گارڈ بجٹ فی صارف رکھتا ہے، فی کنکشن نہیں: کسی رکن کے تمام ڈیوائس ایک ہی مشترکہ سلائیڈنگ ونڈو سے خرچ کرتے ہیں (ایک منٹ میں 120 کالز، جن میں سے زیادہ سے زیادہ 30 بدلاؤ کرنے والی ہوں)، اس لیے تین ڈیوائس کھولنے سے کسی کا کوٹہ تین گنا نہیں ہوتا اور ایک شور مچانے والا رکن باقیوں کو بھوکا نہیں رکھ سکتا۔
  • اَنڈو فی پرنسپل ہے۔ ہر کلائنٹ کا ایکشن جرنل صرف وہی بدلاؤ درج کرتا ہے جو اُس کے پرنسپل نے کیے۔ آپ اپنی ٹکٹ ترمیم پر ⌘Z دبا سکتے ہیں؛ کسی ساتھی کی واپس نہیں کر سکتے — جب تک وہ آپ کو نظر آئے، پائیدار راستہ اُسے حل کر چکا ہوتا ہے (نیچے دیکھیں)۔

رکنیت رسائی کی حد ہے — پیئرنگ کی نہیں

سیکشن کا عنوان “رکنیت رسائی کی حد ہے — پیئرنگ کی نہیں”

دو الگ اسناد دو الگ سوالوں کے جواب دیتی ہیں۔ پیئرنگ کی (دیکھیں ریموٹ کنٹرول اور موبائل) کسی ڈیوائس کی سرور کے سامنے توثیق کرتی ہے۔ رکنیت اُس ڈیوائس کے صارف کو کسی ورک اسپیس کے اندر عمل کرنے کا اختیار دیتی ہے۔ جو جوڑا ہوا ڈیوائس ایسا صارف رکھتا ہو جس کی کسی ورک اسپیس میں رکنیت نہ ہو، وہ نہ اُسے پڑھ سکتا ہے نہ اُس میں بدلاؤ کر سکتا ہے۔

رکنیت فی (ورک اسپیس، صارف) ایک قطار ہوتی ہے، جو اُس ورک اسپیس کی اپنی ڈیٹا بیس فائل میں محفوظ ہوتی ہے — اس لیے ”اِس ورک اسپیس میں کون ہے؟“ ایک عام اسکوپ شدہ ریڈ ہے، جبکہ اُلٹا سوال، ”میں کن ورک اسپیسز میں ہوں؟“، لازماً فائلوں کے پار جاتا ہے اور اُن چند اجازت یافتہ کراس ورک اسپیس فین آؤٹس میں سے ایک ہے۔ ورک اسپیس پکر کوئی ورک اسپیس چنے جانے سے پہلے یہی چلاتا ہے۔

ہر قطار پانچ سطحوں کی، درجے کے لحاظ سے ترتیب دی گئی سیڑھی سے ایک کردار اُٹھاتی ہے:

کردار کیا کر سکتا ہے
owner مکمل کنٹرول، بشمول ورک اسپیس حذف کرنا؛ فی ورک اسپیس بالکل ایک
admin اراکین، دعوتیں، ترتیبات اور تباہ کن آپریشنز کا نظم
member روزمرہ پڑھائی و لکھائی: پیغامات، ٹکٹس، ایجنٹ رنز
viewer پورے ورک اسپیس میں صرف پڑھنے کی اجازت؛ خفیہ معلومات خارج کرنے والے گلوبز کوڈ والی سطحوں پر مماثل پاتھ چھپا دیتے ہیں
guest ناظر جیسی صرف پڑھنے کی کم سے کم حد، مگر سیڑھی کے سب سے نچلے درجے پر

ہر رسائی کا فیصلہ اِس پر اُتر آتا ہے کہ ”کیا کال کرنے والے کا کردار کم از کم X ہے؟“۔ حد آپریشن کی قسم سے اخذ ہوتی ہے، الا یہ کہ وہ خود کوئی حد واضح طور پر بیان کرے: ایک ریڈ کے لیے guest چاہیے، بدلاؤ کے لیے member، اور تباہ کن آپریشن کے لیے admin۔ نیچے دیے گئے فی ریپو گرانٹس کے علاوہ فی آبجیکٹ ACLs جان بوجھ کر دائرے سے باہر ہیں۔

دعوتیں رکنیت دینے کا ذریعہ ہیں، ترتیبات → ورک اسپیس → اراکین سے۔ کوئی ایڈمن ایک بار استعمال ہونے والا کوڈ (لنک یا QR کے طور پر) بناتا ہے جو بطور ڈیفالٹ سات دن بعد ختم ہو جاتا ہے؛ سرور صرف کوڈ کا SHA-256 ہیش رکھتا ہے اور خود کوڈ بالکل ایک بار دکھایا جاتا ہے۔ اُسے استعمال کرنا صارف کو JIT پروویژن کرتا ہے، رکنیت دعوت کے کردار پر درج کرتا ہے (owner کبھی نہیں — ملکیت واضح طور پر منتقل کی جاتی ہے، دعوت سے کبھی نہیں دی جاتی) اور پھر ڈیوائس پیئرنگ کے حوالے کر دیتا ہے۔ پیئرنگ کے بعد بنائی گئی ڈیوائس اسناد خود 30 دن کی حد میں بندھی ہوتی ہیں، اس لیے ایک پیئرنگ مستقل کلید نہیں ہے۔

فی ریپو گرانٹس رکنیت کے نیچے بیٹھتے ہیں۔ چونکہ سرور مکمل چیک آؤٹس رکھتا ہے، صرف ورک اسپیس کی رکنیت کبھی forge کے اختیارات سے آگے نہیں بڑھنی چاہیے: کوڈ سامنے لانے والی ہر سطح — فائلیں، ڈفز، PR ریویو، کوڈ سرچ — اُس ریپو پر رکن کے گرانٹ کی جانچ کرتی ہے۔ گرانٹس فی (ورک اسپیس، صارف، ریپو) ہوتے ہیں اور none → read → review → write کے درجوں میں ہوتے ہیں، جہاں write کا مطلب ایسے ایجنٹ رنز چلانا ہے جو ریپو میں لکھتے ہیں۔ قطار کا نہ ہونا none کے برابر ہے؛ مالک اور ایڈمن ہر منسلک ریپو پر بالواسطہ write رکھتے ہیں اور کوئی قطار رکھتے ہی نہیں۔

Control Center مشترکہ حالت کو دو راستوں میں بانٹتا ہے جن کے پائیداری کے اصول اُلٹے ہیں، کیونکہ دونوں طرح کی حالت اُلٹے طریقوں سے ناکام ہوتی ہے۔

موجودگی — کون آن لائن ہے، کہاں ہے، کیا ٹائپ کر رہا ہے، کوئی ایجنٹ اس وقت کیا کر رہا ہے — باسی ہوتے ہی بےکار ہو جاتی ہے۔ اگر اُسے محفوظ کیا جاتا، تو ہر دوبارہ جڑنے پر ”ڈیٹا بیس کہتا ہے کہ سیم اِس ٹکٹ میں ترمیم کر رہا ہے“ کو حقیقت سے مِلانا پڑتا۔ اس لیے موجودگی کبھی ڈیٹا بیس میں نہیں لکھی جاتی۔ یہ سرور پر ایک میموری میں رہنے والے موجودگی ہب میں رہتی ہے: کلائنٹس presence.update سے شائع کرتے ہیں، ساتھی presence.watch سے سبسکرائب کرتے ہیں اور اندراجات تین چھوٹی ہوئی ہارٹ بیٹس کے بعد خودکار طور پر ختم ہو جاتے ہیں (ہارٹ بیٹس ہر 10 سیکنڈ بعد چلتی ہیں؛ ہب ہر 5 سیکنڈ بعد صفائی کرتا ہے)۔ مِلانے کو کچھ نہیں — صرف باسی ہونے دینا ہے۔

دو خصوصیات اِس راستے کو قابلِ اعتماد رکھتی ہیں:

  • شناخت سیشن سے آتی ہے، کلائنٹ کے دلائل سے کبھی نہیں۔ سرور کنکشن کے توثیق شدہ ڈیوائس کو ایک صارف id سے جوڑتا ہے؛ کوئی کلائنٹ صرف اپنی ہی موجودگی بدل سکتا ہے، اس لیے کوئی دوسرے شرکت کنندہ کی حالت یا مقام کی جعل سازی نہیں کر سکتا۔ ایک واضح offline اپ ڈیٹ (کنکشن منقطع ہونا یا پوشیدہ ٹوگل) اندراج کو فوراً ہٹا دیتا ہے۔
  • روسٹر سرور کے ہب سے چلتا ہے۔ ساتھی کبھی موجودگی کا تبادلہ براہِ راست نہیں کرتے، اس لیے ٹوپولوجی سے قطع نظر ہر شرکت کنندہ ایک ہی روسٹر دیکھتا ہے۔ ایجنٹس کا کوئی کلائنٹ نہیں ہوتا، چنانچہ سرور اُن کے اندراجات زندہ رن کی حالت سے ترکیب کرتا ہے — سوچ رہا ہے، چل رہا ہے، منظوری کے گیٹ پر رکا ہوا ہے، مکمل — اور ایجنٹ کی حالت اور مقام ایک واحد نمائندہ رن طے کرتا ہے تاکہ بیک وقت چلنے والے رنز روسٹر کو ہلنے نہ دیں۔

فین آؤٹ ہر صارف کے لیے درجوں میں ہوتا ہے: ڈیسک ٹاپ اور ویب مکمل درجہ استعمال کرتے ہیں (زیادہ سے زیادہ 100 ms میں ایک روسٹر اخراج)، فون خلاصے کا درجہ (فی 500 ms)، تاکہ کرسر کی رفتار والے اپ ڈیٹس PWA کو پگھلا نہ دیں۔

شرکت کنندہ کا مقام — وہ اس وقت کہاں ہے، حتیٰ کہ کس شے تک — ایک سِیل بند اتحاد ہے: Space، File (ریپو + پاتھ + اختیاری لائن)، Pr، Ticket، PlanNode۔ ہر مقام کے پاس کہیں چھلانگ لگانے کی جگہ نہیں ہوتی: فائل ویوئر کا کوئی روٹ نہیں، اس لیے File مقام منزل کے بجائے ایک لیبل کے طور پر دکھایا جاتا ہے۔ یہ راستہ نرم دعوے بھی لے کر چلتا ہے (”سیم اِس ٹکٹ میں ترمیم کر رہا ہے“، ”ایک ایجنٹ اِس worktree کو تھامے ہوئے ہے“): ٹکراؤ کی نظر آنا، تالے نہیں۔ نامعلوم مقام اقسام null میں پارس ہو جاتی ہیں، اس لیے ایک پرانا کلائنٹ جو سمجھ نہیں پاتا اُسے بس دکھاتا نہیں۔

جو ریکارڈ باقی رہنا ضروری ہیں — ٹکٹس، اسپیس کا مشترکہ Notes دستاویز، پیغامات — اُلٹا راستہ لیتے ہیں: مستند، ترتیب شدہ اور محفوظ۔ بیک وقت کی گئی ترامیم سرور کے وصولی کی ترتیب میں آخری لکھنے والا جیتتا ہے کے اصول سے طے ہوتی ہیں، کلائنٹ کی گھڑیوں سے کبھی نہیں۔ طے کرنا جان بوجھ کر باریک بین ہے: ٹکٹ کی ترامیم فی کالم ہوتی ہیں، اس لیے ایک ہی ٹکٹ کے مختلف فیلڈز میں ترمیم کرنے والے دو افراد دونوں محفوظ ہو جاتے ہیں اور کوئی بھی دوسرے کو مٹاتا نہیں (ورک فلو کی منتقلیاں اِس کے بجائے آپٹمسٹک لاکنگ رکھتی ہیں)؛ اسپیس کا Notes دستاویز ایک کالم ہے، اس لیے پوری دستاویز LWW ہے اور موجودگی کے راستے پر نرم دعوے بیک وقت کی ترمیم کو مقفل ہونے کے بجائے نظر آنے دیتے ہیں۔ یہ جان بوجھ کر CRDT نہیں ہے — ثبوت کا بوجھ CRDT پر ہے اور وصولی کی ترتیب والا LWW اور نظر آنے والے دعوے حقیقی تعاون کے نمونوں کو پورا کرتے ہیں۔

”آخری لکھنے والا“ کا مطلب سرور کے وصولی کی ترتیب ہے، کلائنٹ کی گھڑی کبھی نہیں — ٹیڑھی گھڑی والا لیپ ٹاپ کوئی ایسی ترمیم نہیں جیت سکتا جو وہ ہار چکا ہو۔ پائیدار راستے کے پیچھے سنک فیڈ بیٹھا ہے: SQLite ٹرگرز ہر بدلاؤ کو فی ورک اسپیس تبدیلی لاگ میں لکھنے والے ٹرانزیکشن کے اندر ہی شامل کرتے ہیں اور خود بدلاؤ والے ٹرانزیکشن میں ہی فی ورک اسپیس یکساں بڑھتا ہوا ترتیبی نمبر مختص کرتے ہیں۔ ایک سرور سروس اُس لاگ کو ترتیب وار ورژن شدہ ڈیلٹا فریمز میں ڈھال کر آگے بڑھتی رہتی ہے۔ کلائنٹ مکمل اسنیپ شاٹس سے ڈیلٹاز تک ترقی کرتے ہیں؛ ترتیب میں کوئی خلا اُس اسٹور کو فریمز غلط لگانے کے بجائے واپس اسنیپ شاٹ موڈ پر گرا دیتا ہے۔

پیروی کریں، اسٹیئر کریں، سنبھالیں، واپس کریں

سیکشن کا عنوان “پیروی کریں، اسٹیئر کریں، سنبھالیں، واپس کریں”

موجودگی کا راستہ صرف ایک روسٹر نہیں — یہ تعاون کے فعل چلاتا ہے:

  • پیروی موڈ۔ کسی شرکت کنندہ پر کلک کریں اور آپ کا کلائنٹ اُس کے مقام کے ساتھ چلتا ہے، جہاں وہ جاتا ہے آپ بھی جاتے ہیں۔ پیروی ”جب تک آپ خود عمل نہ کریں“ ہے: جس لمحے آپ خود اپنی مرضی سے کہیں جاتے ہیں، پیروی چھوٹ جاتی ہے۔ ایک ہٹایا جا سکنے والا بینر بتاتا ہے کہ کوئی دوسرا شرکت کنندہ اُس اسپیس کو اسپاٹ لائٹ (یعنی پیش) کر رہا ہے جس میں آپ موجود ہیں۔
  • اسٹیئر۔ چلتے ہوئے ایجنٹ کو دیا گیا پیغام اسٹیئرنگ کے طور پر قطار میں لگ جاتا ہے؛ ایجنٹ اپنی اگلی باری شروع کرنے سے پہلے اُسے دوبارہ پڑھتا ہے، اس لیے آپ رن کو مارے بغیر اُسے دورانِ پرواز ہلکا سا ہدایت دے سکتے ہیں۔
  • سنبھالیں۔ کسی گفتگو کا کنٹرول سنبھالنے سے ہر فعال رن اپنی اگلی صاف باری کی حد پر رک جاتا ہے (Claude Code کا رن، جس کی کوئی محفوظ حد نہیں، روک دیا جاتا ہے) اور یہ ایک فی باری git اسنیپ شاٹ کے پیچھے ہوتا ہے، اس لیے سنبھالنا واپس پلٹایا جا سکتا ہے۔ ایک پائیدار مارکر اسپیس میں نئے ڈسپیچز روک دیتا ہے اور سرور کے دوبارہ شروع ہونے پر بھی قائم رہتا ہے — سرور کبھی کسی انسان کی ادھوری ترمیم میں خود بخود دوبارہ شروع نہیں ہوتا۔ فی worktree ایک زندہ ایڈیٹر ایک نرم دعویٰ ہے: دوسرا سنبھالنا نظر آتا ہے اور مسترد ہو جاتا ہے، خاموشی سے ضم نہیں ہوتا۔
  • واپس کریں۔ کنٹرول واپس کرنا worktree کا ایک ساختی ڈف خلاصہ اسپیس میں شائع کرتا ہے، رکے ہوئے رنز کے لیے اُسے اسٹیئرنگ کے طور پر قطار میں لگاتا ہے، اُنہیں دوبارہ شروع کرتا ہے اور مارکر صاف کر دیتا ہے۔

اسٹیئرنگ اور سنبھالنا واقعے کے بعد کی مداخلتیں ہیں۔ خود مختاری ڈائل مستقل ترتیب ہے: فی اسپیس، فی ایجنٹ، اسپیس ہیڈر سے مقرر ہوتی ہے اور طے کرتی ہے کہ جب کوئی ایجنٹ کسی گیٹڈ اقدام تک پہنچے تو کیا ہوگا۔

سطح وائر ویلیو گیٹڈ ٹول کال پر اثر
صرف تجویز proposeOnly براہِ راست مسترد، ایک وجہ کے ساتھ جو ایجنٹ کو آگے پہنچانے کا کہا جاتا ہے — وہ اقدام بیان کر سکتا ہے مگر کر نہیں سکتا
منظوری سے عمل actWithApproval ناکامی پر بند ہونے والا منظوری گیٹ: ایک تصدیق جڑے ہوئے آپریٹر کو دکھائی جاتی ہے اور کوئی منظوری دینے والا نہ ہو تو مسترد
آزادانہ عمل actFreely پہلے سے منظور، سوائے وہاں جہاں گارڈریل کا کوئی سخت deny اصول لاگو ہو — انکار کا اصول ہمیشہ جیتتا ہے
(غیر مقرر) null منظوری سے عمل جیسا ہی: سرور کا ڈیفالٹ

دو چیزیں دونوں سمتوں میں ڈائل سے باہر بیٹھتی ہیں۔ کسی موڈ کا اپنا آؤٹ پٹ ورب پن شدہ ہوتا ہے اور اُسے کبھی مسترد نہیں کیا جا سکتا، چاہے ڈائل کچھ بھی کہے — آرکیسٹریٹ موڈ ایک زمانے میں ساختی طور پر اپنا واحد ڈیلیوریبل جاری کرنے سے قاصر تھا کیونکہ ایک پریسیٹ نے اُس اثر کی کلاس سے انکار کر دیا تھا جس کا اعلان وہ ورب کرتا ہے۔ اور ایکشن گارڈریلز کا سخت deny actFreely سے ناقابلِ تبدیلی ہے۔

یہ سب اضافی ہے۔ اکیلے آپریٹر کا ورک فلو ویسا ہی رہتا ہے: ایک انسان اور کوئی ایجنٹ نہ ہو تو موجودگی ہب کے پاس نشر کرنے کو کچھ نہیں ہوتا، اس لیے راستہ اپنا ابتدائی اسنیپ شاٹ جاری کر کے صفر ٹریفک پر بیکار پڑا رہتا ہے؛ LWW اور سنک کا نظام وہی واحد لکھاری والا راستہ ہے جو ہمیشہ سے تھا؛ اور پیئرنگ کی وہی ڈیوائس اسناد رہتی ہے جو ہمیشہ سے تھی۔ رکنیت پہلے ہی رسائی کی حد ہے — ایک انسان کے ساتھ صرف ایک مالک کی قطار ہوتی ہے اور روسٹر کی کوئی اضافی جھلک نہیں۔