0:00 — একটি বিল্ড সম্পন্ন হয়। এজেন্ট বলে এটা শেষ, যেটা কোড লেখা সম্পর্কে একটা দাবি, কোড কাজ করছে কি না সে সম্পর্কে নয়। AI বিল্ডারের প্রতিটি ব্যবহারকারী অন্তত একবার হলেও এই দুই দাবির মধ্যেকার ফারাক অনুভব করেছেন: প্রিভিউ খোলে, তৃতীয় বাটনে ক্লিক করা হয়, কিছুই ঘটে না। আমি দেখেছি ঠিক সেই মুহূর্তে একটা ডেমো রুম নিস্তব্ধ হয়ে যেতে। তাই কোনো মানুষ বিল্ড দেখার আগে, এটা প্রায় ছয় মিনিটের একটি চেইনের মধ্য দিয়ে যায় যা নিজের সাথেই তর্ক করে। আমরা যে বিল্ডটি ভেঙে পড়তে এবং তারপর ঠিক হতে দেখেছি, তার মাধ্যমে দেখানো হলো এটা আসলে কেমন দেখায়।
0:02 — কোড রিভিউ শুরু হয়। যে এজেন্ট কোড লিখেছে সে নিজের হোমওয়ার্ক আবার পড়ছে তা নয় — একটা আলাদা এজেন্ট, ভিন্ন প্রম্পট, বিল্ড পাস করা নিয়ে কোনো স্বার্থ নেই। এই আলাদাকরণটা যতটা গুরুত্বপূর্ণ মনে হয় তার চেয়েও বেশি গুরুত্বপূর্ণ। যে এজেন্ট দুপুর ২টা ১৪ মিনিটে সিদ্ধান্ত নিয়েছিল যে এরর হ্যান্ডলিং ছাড়া একটা fetch কল ঠিক আছে, নিজের কাজ চেক করতে বললে দুপুর ২টা ১৫ মিনিটেও সে তাই মনে করবে। "কী ভাঙা আছে খুঁজে বের করো, ফাইল উল্লেখ করো" বলা একজন নতুন রিভিউয়ার ঠিক সেই খিটখিটে সিনিয়র ইঞ্জিনিয়ারের মতো আচরণ করে, যাকে আপনি আসলেই এই দায়িত্বে চান। একটি পূর্ববর্তী বিল্ডে এটি একটি কার্ট টোটাল ধরে ফেলেছিল যা নিঃশব্দে কখনো আপডেট হচ্ছিল না — `updateTotal`, `Cart.jsx`-এ সংজ্ঞায়িত ছিল কিন্তু quantity-change হ্যান্ডলারের সাথে কখনো যুক্ত করা হয়নি, তাই ফাংশনটি ছিল কিন্তু কখনো চলেনি। এটা ঠিক সেই ক্যাটাগরির সমস্যা যার জন্য কোড রিভিউ প্রয়োজন — এমন জিনিস যা একটা কম্পাইলার পাত্তাই দেয় না।
0:04 — সিকিউরিটি অডিট। শুনতে যতটা মনে হয় তার চেয়ে সংকীর্ণ, ইচ্ছাকৃতভাবেই — এটা কোনো পেনটেস্ট নয়, এটা হলো সেই কয়েকটি ভুলের একটি প্যাটার্ন অনুসন্ধান যা আসলেই AI-জেনারেটেড কোডে দেখা যায়। স্ট্রিং-কনক্যাটেনেটেড SQL। ক্লায়েন্ট-সাইড-অনলি ভ্যালিডেশনকে যেন এটাই পুরো ব্যাপার তেমন ভরসা করা। আর বিশেষ আইটেম: একটা হার্ডকোডেড API কী, কারণ ফিচার লেখা এজেন্টের সামনে কোনো এনভায়রনমেন্ট-ভ্যারিয়েবল কনভেনশন ছিল না, তাই যা কাজ করেছিল সেটাই ব্যবহার করেছে। এটা আমরা এত বেশি দেখি যে আর সেটা আশ্চর্যের কিছু মনেই হয় না।
0:07 — লিংক এবং SEO। আকর্ষণীয় নয়, আর এটা এমন জিনিস ধরে ফেলে যা কোনো গ্রাহক না দেখা পর্যন্ত কেউ লক্ষ্যই করে না: একটা নেভ লিংক নির্দেশ করছে /pricing অথচ পেজটি আসলে তৈরি হয়েছিল /price-এ, একটা sitemap এন্ট্রি একটা পেজের জন্য যা 404 দেয়, একটা মেটা ডেসক্রিপশন যা এখনো টেমপ্লেট প্লেসহোল্ডার টেক্সট ধরে রেখেছে। এর কোনোটাই বিল্ড ভাঙে না। কিন্তু এসব নিঃশব্দে আমাদের বেশিরভাগ ব্যবহারকারী যে জিনিসটার জন্য সাইট তৈরি করেছিলেন সেটার ক্ষতি করে — খুঁজে পাওয়া, ক্লিক পাওয়া।
0:09 — অ্যাক্সেসিবিলিটি। এটা একটা স্বয়ংক্রিয় axe-core পাস, সম্পূর্ণ ম্যানুয়াল অডিট নয়, এবং এই বিনিময়ে কী পাওয়া যায় সে বিষয়ে সৎ থাকা দরকার। axe-core কনট্রাস্ট রেশিও, অনুপস্থিত অল্ট টেক্সট, লেবেলবিহীন ফর্ম ইনপুট, ট্যাব-অর্ডার ফাঁদ ধরে ফেলে — যান্ত্রিক স্তরটি, একটা পূর্ণাঙ্গ WCAG রিভিউ যা চিহ্নিত করবে তার প্রায় ৩০-৪০%। কিন্তু এটা এমন কোনো স্ক্রিন রিডার অভিজ্ঞতা ধরবে না যা প্রযুক্তিগতভাবে কমপ্লায়েন্ট কিন্তু ব্যবহার করা প্রকৃতপক্ষে বিভ্রান্তিকর। আমরা শুধু-স্বয়ংক্রিয় পদ্ধতি বেছে নিয়েছি কারণ এটা সেকেন্ডের মধ্যেই চলে এবং এখান দিয়ে যা শিপ হয় তার বেশিরভাগই মার্কেটিং সাইট আর ছোট টুল, এমন কোনো অ্যাপ্লিকেশন নয় যেখানে আংশিক অডিট কারো জন্য বাস্তব ঝুঁকি।
0:11 — কনফরমেন্স। এই স্তরটি জিজ্ঞাসা করে না "এটা কি ভালো," বরং জিজ্ঞাসা করে "এটা কি যা প্রতিশ্রুতি দেওয়া হয়েছিল তার সাথে মেলে।" প্ল্যানে চারটি পেজের কথা বলা ছিল, বিল্ড শিপ হয়েছে তিনটি পেজ নিয়ে — কনফরমেন্স এটা ধরে ফেলে। প্ল্যানে একটা কার্যকর কন্টাক্ট ফর্মের প্রতিশ্রুতি ছিল, যা শিপ হয়েছে তাতে কোনো সাবমিট অ্যাকশনই নেই — একই স্তর, একই ধরা। এটাই সবচেয়ে সরাসরি ব্যবহারকারীর কাছে জবাবদিহি করার চেক, কারণ এটা ব্যবহারকারীর বলা উদ্দেশ্যের বিপরীতে মাপা হয়, কোনো বিমূর্ত মান ধারণার বিপরীতে নয়।
0:13 — ব্রাউজারের মধ্যে চেক, এবং এখানেই আমাদের বিল্ড আসলে ভেঙে পড়েছিল। এই স্তরকে নকল করা সবচেয়ে কঠিন কারণ এটা কোড পড়ে না, এটা একটা আসল ব্রাউজার চালায় — ক্লিক করে, টাইপ করে, অপেক্ষা করে, চেক করে DOM যেভাবে পরিবর্তন হওয়ার কথা ঠিক সেভাবে হয়েছে কি না। প্রশ্নবিদ্ধ বিল্ডটি ছিল একটি আইডল গেম, আর গেমগুলো এখানে একটা অতিরিক্ত পাস পায় কারণ একটা গেম পিক্সেল-পারফেক্ট রেন্ডার করেও খেলার অযোগ্য হতে পারে — স্কোর ডিসপ্লে একেবারে নিখুঁত দেখাতে পারে অথচ স্কোরিং লজিকের সাথে সম্পূর্ণ বিচ্ছিন্ন থাকতে পারে। ভেরিফায়ার এটা খেলেছিল। স্কোর ঠিকভাবে আপডেট হয়েছিল। অডিও কোনো শব্দ করেনি।
তিনটি রাউন্ড, তারপর একটি এসকালেশন
ফাইন্ডিংটি আমাদের কাছে বাগ রিপোর্ট হিসেবে আসেনি — এটা সরাসরি একটা ফিক্স পাসে চলে গিয়েছিল, এবং চেইনটি পুনরায় যাচাই করেছিল, বিল্ডের ভেতরে সর্বোচ্চ তিনটি রাউন্ড পর্যন্ত। রাউন্ড এক: ফিক্সটি মিক্সার ইনিশিয়ালাইজেশন স্পর্শ করেছিল, যা ইতিমধ্যেই ঠিক ছিল, তাই অডিও নিঃশব্দই থেকে গিয়েছিল। রাউন্ড দুই: একটা ভিন্ন ফিক্স একটা লোডিং-স্টেট এজ কেস সমাধান করেছিল যা কাছাকাছি মনে হচ্ছিল, এবং — এটা যত ঘন ঘন হওয়া উচিত তার চেয়ে বেশি ঘটে — মূল সমস্যাটি সমাধান না করেই একটা নতুন ছোট সমস্যার জন্ম দিয়েছিল। রাউন্ড তিন: তখনও নিঃশব্দ, এবং এই পর্যায়ে সাধারণত আপনি হয় সত্যিই কঠিন কিছু দেখছেন, না হয় একটা মিথ্যা অ্যালার্ম, আর এটা ছিল কঠিন ধরনের।
তাই প্ল্যাটফর্মটি নিজে থেকেই এসকালেট করেছিল। এটা টিকে থাকা ফাইন্ডিংয়ের উপর সম্পূর্ণভাবে কেন্দ্রীভূত একটা ফলো-আপ ফিক্স রান কিউতে যুক্ত করেছিল, যা বিল্ডের নিজের উপর নয় বরং বিল্ডের একটি ক্লোনে কাজ করছিল — অর্থাৎ এসকালেশন রানটি ব্যর্থ হলেও আমাদের কাছে ইতিমধ্যে থাকা কার্যকর ভার্সনের কোনো ক্ষতি হতো না। সেই রানটি আসল কারণ খুঁজে পেয়েছিল: একটা আগের ডিবাগ পাসের সময় সেট করা মিউট ফ্ল্যাগ যা কখনো ফেরত পাল্টানো হয়নি, যা আগের দুটি ফিক্স যে দুটি ফাইলে কাজ করেছিল তার থেকে সম্পূর্ণ আলাদা একটা ফাইলে বসে ছিল। ফ্ল্যাগটি সরানো হলো, পুনরায় যাচাই করা হলো, পাস হলো। এই বিল্ডটি ইতিমধ্যে কাজ না করা পর্যন্ত কেউ এটার দিকে তাকায়নি।
| ক্রম | স্তর | যা ধরা পড়ে |
|---|---|---|
| 1 | কোড রিভিউ | ভাঙা লজিক, মৃত হ্যান্ডলার, স্টেট বাগ |
| 2 | সিকিউরিটি অডিট | ইনজেকশন সারফেস, ফাঁস হওয়া সিক্রেট, অনিরাপদ প্যাটার্ন |
| 3 | লিংক ও SEO | ভাঙা লিংক, অনুপস্থিত মেটাডেটা, sitemap/robots.txt সঠিকতা |
| 4 | অ্যাক্সেসিবিলিটি | স্বয়ংক্রিয় axe-core: কনট্রাস্ট, লেবেল, কীবোর্ড নেভিগেশন |
| 5 | কনফরম্যান্স | প্ল্যানে যা প্রতিশ্রুতি দেওয়া হয়েছিল বিল্ডে তা আছে কি না |
| 6 | ব্রাউজারের মধ্যে চেক | বিল্ডটি সত্যিকারভাবে চালায় — ক্লিক করে, টাইপ করে, প্রতিক্রিয়া দেখে |
পরেরবার যা এড়িয়ে যাব
সেই আইডল গেমটি চলার কয়েক মাস আগে, আমরা পুরো সিস্টেমের একটা নরম ভার্সন চেষ্টা করেছিলাম — ভেরিফায়ারদের যেকোনো উদ্বেগ যেভাবে খুশি সেভাবে উত্থাপনের অনুমতি ছিল। এটা এমন ফাইন্ডিং তৈরি করেছিল যেমন "এটাকে একটা হেল্পারে বের করে নেওয়ার কথা ভাবুন" এবং "এই ভ্যারিয়েবলের নামটা আরো স্পষ্ট হতে পারত," যা যত্নশীলতা মনে হলেও কিছুই ঠিক করেনি। ফিক্স পাসগুলো পুরো রাউন্ড খরচ করেছিল ভাষা ঝকঝকে করতে, আসলে যা ভাঙা ছিল সেটা ঠিক না করে। আমরা নিয়মটা কড়া করেছিলাম: একটা ফাইলের নাম বলো, একটা ব্যর্থতা বর্ণনা করো, নয়তো কিছু বোলো না। ভেরিফায়ারের আউটপুট প্রায় অর্ধেক কমে গিয়েছিল এবং যা বাকি ছিল তার প্রায় সবই কার্যকর ছিল। আমি যদি এটা শূন্য থেকে আবার তৈরি করতাম তাহলে নরম ভার্সনটা সম্পূর্ণ বাদ দিয়ে সরাসরি প্রমাণের নিয়মে চলে যেতাম — এই শিক্ষাটা আমাদের দামি উপায়ে শিখতে হয়নি, তবু আমরা তাই করেছিলাম।
নিয়মটির একটা আসল খরচ আছে, এবং আমি সেটা লুকাব না: "এই API ডিজাইন ছয় মাসের মধ্যে কাউকে কামড়াবে" এর মতো একটা অস্পষ্ট কিন্তু সত্যি উদ্বেগ এখন বাতিল হয়ে যায়, কারণ একজন ভেরিফায়ার সেটাকে একটা নির্দিষ্ট ব্যর্থতায় আটকাতে পারে না। আমরা এই বিনিময়টা মেনে নিয়েছি। একটা চেইন যেটা আর্কিটেকচার রিভিউও করে সেটা প্রতিটি একক বিল্ডে চালানোর জন্য যথেষ্ট দ্রুত নয়, আর এটা স্বয়ংক্রিয়ভাবে চালানোর পুরো বিষয়টাই গতি সম্পর্কে, কোনো মানুষকে সেটা করতে বলার বদলে।
কেউ যদি জিজ্ঞাসা করে, আমি চতুর্থ রাউন্ড যোগ করাও এড়িয়ে যাব। আমরা রাউন্ড সংখ্যাটা আসল বিল্ডের বিপরীতে টিউন করেছিলাম, আর রাউন্ড তিনের পরে প্রান্তিক মূল্য কঠোরভাবে কমে যায় — রাউন্ড এক বেশিরভাগ ফিক্স-যোগ্য ফাইন্ডিং সমাধান করে, রাউন্ড দুই মূলত রাউন্ড এক যে সমস্যা তৈরি করেছিল তা পরিষ্কার করে, আর রাউন্ড তিনের মধ্যে যা বাকি থাকে তা হয় সত্যিই কঠিন, নয়তো আসলে কখনো ভাঙাই ছিল না। একটা চতুর্থ রাউন্ড মূলত একই ফলাফলের জন্য দীর্ঘতর অপেক্ষার সময় কিনে দেয়।
এর কোনোটাই বিনামূল্যে নয়, আর কোনোটাই অভ্রান্ত নয়। ছয়টি স্তর এবং তার সাথে যত রাউন্ড ফিক্স লাগে তা প্রতিটি বিল্ডে আসল সময় যোগ করে — এক মিনিটের কম সময়ে শেষ হওয়া আর কয়েক মিনিটে শেষ হওয়ার মধ্যেকার পার্থক্য। আমরা মনে করি নিজের গ্রাহকদের সামনে যা কিছু আপনি রাখতে যাচ্ছেন তার জন্য এটাই সঠিক বিনিময়, কিন্তু "দ্রুত" এবং "যাচাইকৃত" বিপরীত দিকে টানে, আর আমরা যাচাইকৃতকে বেছে নিয়েছি। ভেরিফায়াররাও LLM, তাই তারা মাঝে মাঝে এমন কিছু চিহ্নিত করে যা আসলে ভাঙা নয়, বা এমন কিছু মিস করে যা ভাঙা। প্রমাণের নিয়ম এবং মাল্টি-রাউন্ড লুপ এর বিরুদ্ধে সুরক্ষা, গ্যারান্টি নয়।
শেষে আপনি যা পান তা একটা রেকর্ড: কোন স্তরগুলো চলেছে, তারা কী খুঁজে পেয়েছে, কী ঠিক করা হয়েছে, এবং আপনার নিজের বিচারের জন্য কী বাকি রয়েছে। সেই রেকর্ডটি কোডের চেয়ে আসল পণ্যের কাছাকাছি — এটাই সেই পার্থক্য যা একটা বিল্ডকে দেখতে সম্পূর্ণ মনে হওয়ার কারণে বিশ্বাস করা এবং কিছু আক্রমণাত্মকভাবে এটা ভাঙার চেষ্টা করে ব্যর্থ হওয়ার কারণে বিশ্বাস করার মধ্যে থাকে।



