Sổ nguồn SRC-0550 tới SRC-0574
Một mảnh của sổ tiếp nhận. Chỉ CHÈN dòng bằng node scripts/src-new.mjs, không ghi đè cả file.
| ID | Ngày nhận | Nguồn | Canonical hóa vào | Trạng thái |
|---|---|---|---|---|
| SRC-550 | 2026-08-23 | Chỉ đạo: khoá học cho trẻ, bố mẹ đăng ký; bố mẹ xem lịch + mô tả trên marlins, con xem lịch + tự đăng ký trên learn; 4 lớp (Toán 1/2, Tiếng Việt 1/2) 14:00-15:20 và 15:30-17:00, 06/09→29/12/2026, cấp 2, cá nhân hoá, mang máy tính riêng; 2 buổi học thử miễn phí, tính tiền từ buổi 3 | REQ-PAR-18, REQ-LRN-22; migration 0074_courses.sql (courses · course_sessions · course_enrollments); module courses + 4 route, enrolled_by_role ghi AI bấm (bố mẹ hay con) — vừa để đối chiếu vừa là tín hiệu cho Parent Model; CoursesPanel.tsx canonical dùng chung, marlins /khoa-hoc + tab, learn /khoa-hoc + nút navbar. 13 test. Buổi sinh thành DÒNG THẬT chứ không tính bằng quy tắc lặp: nghỉ lễ và đổi buổi là chuyện sẽ xảy ra. Chờ chủ dự án: học vào (các) thứ mấy, và mâu thuẫn Ngữ văn-only với Toán+Tiếng Việt | 🔵 |
| SRC-551 | 2026-08-24 | Chỉ đạo: trang chủ cần mô tả + giá của Nemo Dive (3.000.000) và Nemo Swim (3.600.000 cho khoá 12 buổi); Ngữ văn 12 buổi và Toán 12 buổi là hai khoá riêng, mỗi khoá 3.600.000; gói Swim tặng tài khoản Nemo12 trong quá trình học | Khối "Chi phí" trên apps/web + nguồn giá duy nhất apps/web/src/packages.ts. Đây là con số tuyệt đối ĐẦU TIÊN của cả hệ: trước đó compass/gtm/pricing.md cố ý chỉ ghi tỉ lệ tương đối và chừa cột "Số thật" trống, còn bảng courses chỉ có fee_note dạng chữ tự do, không có cột giá. Giá lưu dạng số, hiển thị qua Intl.NumberFormat("vi-VN") — ghi sẵn thành chuỗi thì sớm muộn có chỗ viết "3tr", chỗ viết "3,000,000". Nhãn "/ môn · khoá 12 buổi" là phần không được bỏ: thiếu nó bố mẹ đọc 3.600.000 thành giá trọn hai môn. Khối đặt sau "Ai đi cùng con" vì con số đứng trước phần tạo niềm tin thì đọc ra là chào hàng. Chưa rõ, cần chủ dự án: tài liệu nội bộ mô tả Dive có hai bản (Lite một môn 60-75 phút · Full 3 tiếng) mà chỉ có một giá được đưa, nên trang hiện ghi "Nemo Dive" không kèm biến thể. Kiểm: typecheck + lint sạch, build web, check-no-emdash PASS (bắt được một em dash do chính đợt này thêm vào), đọc lại DOM trên bản build để xác nhận đủ 5 dòng nội dung | 🔵 giá lên trang, biến thể Dive chưa rõ |
| SRC-552 | 2026-08-24 | Chỉ đạo: thêm khoá Marlin Start cho bố mẹ (tìm hiểu cách đồng hành cùng con) lên cả www.nemo12.com và marlins.nemo12.com; học phí 2.000.000 cho 3 buổi offline tại Hà Nội, sáng Chủ nhật hằng tuần, buổi đầu 30/08 | Thêm vào packages.ts (nguồn giá của SRC-551) chứ không dựng dữ liệu mới: thẻ giá nhận thêm hai trường audience và schedule. Lưới Chi phí trên trang chủ 2 → 3 thẻ. Không dùng bảng courses của SRC-530 dù nó có sẵn course_sessions và luồng ghi danh: bảng đó bắt buộc subject_id (math/vietnamese/…) và ghi danh theo learner, trong khi Marlin Start không có môn và người học là bố mẹ — nhét vừa thì phải bịa một subject giả và một learner giả. Khi nào cần ghi danh trực tuyến thì mở courses thêm cột audience cho đàng hoàng. Nhãn "DÀNH CHO BỐ MẸ" đặt TRÊN tên khoá: ba thẻ cạnh nhau, bố mẹ phải nhận ra thẻ nào cho mình trước khi đọc tới giá. Trên marlins, khối này đứng trước danh sách khoá của con ở /khoa-hoc kèm tiêu đề "Khoá học của con" tách bên dưới, để không ai nhầm đây là thêm một lớp nữa cho con. Ba buổi ghi thành ngày thật (30/08 · 06/09 · 13/09/2026, đã kiểm đều là Chủ nhật) chứ không mô tả bằng quy tắc lặp — đổi một buổi vì lễ là chuyện sẽ xảy ra. Chưa có, cần chủ dự án: giờ học cụ thể (mới biết "buổi sáng") và địa điểm chi tiết ở Hà Nội. Kiểm: typecheck + lint sạch, build web·marlins, check-no-emdash PASS, đọc DOM bản build www xác nhận 3 thẻ đúng nội dung, soi bundle marlins xác nhận chuỗi và giá 2e6 | 🔵 lên trang, thiếu giờ và địa điểm |
| SRC-553 | 2026-08-24 | Chỉ đạo: tách Marlin Start ra khỏi Nemo Dive/Nemo Swim vì đó là gói cho bố mẹ còn hai gói kia cho con; và có trang xem chi tiết từng gói | Khối Chi phí tách làm hai cụm có tiêu đề riêng: "Gói cho con" (Dive, Swim) và "Gói cho bố mẹ" (Marlin Start). Trước đó ba gói nằm chung một lưới, phân biệt bằng nhãn chữ "DÀNH CHO BỐ MẸ" — nhưng nhãn chỉ đọc được khi người ta đã dừng lại đọc, còn thứ mắt bắt trước là bố cục; hai cụm thì câu "gói nào cho ai" được trả lời trước khi đọc chữ nào (cùng nguyên tắc hai cửa vào ở hero, WF-19 §2). Thêm trường forWhom (thứ chia trang, khác audience chỉ là nhãn hiển thị) và detail vào packages.ts. Trang riêng /goi/{code} cho cả ba gói, cả thẻ bấm được (DS-001 §5b điều 7, không có link chữ CTA riêng). Nội dung chi tiết lấy từ tài liệu sản phẩm nội bộ compass/content/products/*; phần chưa chốt hiện công khai trong một khối riêng chứ không giấu — bố mẹ đọc trang này để quyết có đăng ký hay không, im lặng về chỗ còn thiếu là để họ tự phát hiện sau khi đã trả tiền. Sửa một lỗi bố cục: đường kẻ "Lịch học" dùng mt-auto nên dính sát dòng trên khi thẻ đứng một mình trong lưới (không bị kéo cao theo thẻ bên cạnh) → đổi sang khoảng cách cố định. Kiểm: typecheck + lint sạch, build web·marlins, check-no-emdash PASS, chụp lại trang chủ và /goi/marlin-start, dựng DOM xác nhận /goi/dive · /goi/swim ra đúng tên và slug sai ra "Không tìm thấy gói này" | ✅ |
| SRC-554 | 2026-08-24 | Chỉ đạo kèm toàn văn nội dung: tái tạo các gói cho bố mẹ theo tài liệu "Marlin Parent Programs" — lộ trình ba tầng Start → Compass → Mind (Start: nhập môn cách Nemo12 nhìn learner/Learner Model/Mastery-Retention-Readiness; Compass: Systems Thinking + Behavioral Engineering Model, nhìn hệ thống thay vì gắn nhãn hành vi; Mind: Learning Science + Pedagogy + IB ATL, hiểu việc học thực sự diễn ra thế nào), trên cả www và marlins | packages.ts thêm tier + tierLine; cụm "Gói cho bố mẹ" thành 3 thẻ theo thứ tự bậc với nhãn "Bước 1/2/3 · {đổi được gì}" đặt trên tên — ba thẻ đọc thành một đường đi, không phải ba lựa chọn ngang nhau — kèm câu dẫn "hiểu con, hiểu hệ thống quanh con, hiểu việc học". Trang riêng /goi/marlin-compass và /goi/marlin-mind dựng từ đúng toàn văn chủ dự án đưa (biên tập lại thành đoạn, không thêm ý). priceVnd thành optional: Compass và Mind chưa có giá nên thẻ ghi "Sắp mở" — không bịa số giữ chỗ (số sai trên trang công khai là lời hứa sai), không để trống (người đọc tưởng miễn phí); khối chưa-chốt trên trang riêng ghi rõ học phí và lịch công bố sau, Compass mở sau Start, Mind mở sau Compass. Marlin Start giữ nguyên giá 2.000.000 và lịch 3 buổi đã chốt ở SRC-552, nội dung chi tiết thay bằng bản mới. Đồng bộ packages.ts sang marlins, Courses.tsx xử lý giá thiếu + nhãn bậc. Kiểm: typecheck + lint sạch, build web·marlins, check-no-emdash PASS, chụp trang chủ, dựng DOM cả 3 trang /goi/marlin-* xác nhận đúng tên và có khối chưa-chốt | 🔵 lên trang, chờ giá + lịch Compass và Mind |
| SRC-555 | 2026-08-24 | Chỉ đạo: slug không nên là tiếng Việt — đổi /goi/{code} thành /programs/{code} (vd programs/marlin-compass), cả www lẫn marlins | Route + 5 link thẻ + tiêu đề tab đổi sang /programs/*. /goi/* không chết: từng chạy từ SRC-553 nên link có thể đã được chia sẻ — nhánh cũ mở đúng trang và replaceState lặng sang URL mới (replace chứ không push để nút back không kẹt). Một chỗ suýt sai đã chặn: bản đầu đặt useEffect trong nhánh điều kiện để đổi URL — vi phạm rules-of-hooks thật (đổi thứ tự hook giữa hai lần render), sửa thành gọi replaceState thẳng trong render, vô hại vì chỉ đụng thanh địa chỉ. Marlins dùng chung packages.ts (đã đồng bộ); trang /khoa-hoc của marlins không có link chi tiết nên không phải sửa route. Kiểm: typecheck + lint sạch, build web·marlins, dựng DOM 4 URL (3 mới + 1 cũ) ra đúng trang, soát nguồn trang chủ thấy đúng 5 href="/programs/*" | ✅ |
| SRC-556 | 2026-08-24 | Chỉ đạo kèm toàn văn "Nemo Programs": các chương trình cho con cũng là lộ trình ba tầng Nemo Dive → Nemo Compass → Nemo 360 (Dive: khám phá mình đang ở đâu bằng nhiều loại evidence, ra Learner Profile + Knowledge Map + Gap Analysis; Compass: từ biết mình ở đâu đến biết nên đi đâu, lộ trình cá nhân hoá cập nhật theo evidence; 360: hệ thống đồng hành trọn hành trình, kết nối mọi mục tiêu/môn/mentor/cơ hội) | Cụm "Gói cho con" thành "Chương trình cho con" ba thẻ theo bậc (Bước 1/2/3 kèm "Hiểu bản thân / Biết mình nên đi đâu / Đồng hành trọn hành trình") + câu dẫn đúng tinh thần tài liệu; trang riêng /programs/nemo-compass và /programs/nemo-360 dựng từ toàn văn (biên tập thành đoạn, không thêm ý); Dive viết lại nội dung theo bản mới, giữ giá 3.000.000 đã chốt ở SRC-551 và vào bậc 1. Compass và 360 chưa có giá → "Sắp mở" (cùng nguyên tắc SRC-554). Nemo Swim không có trong tài liệu ba tầng nhưng KHÔNG xoá: nó là khoá 12 buổi có giá và cam kết "tặng tài khoản" đã công bố (SRC-551) — tách xuống cụm riêng "Khoá học đang mở"; xoá là rút một khoá đang bán khỏi trang, còn nhét vào lộ trình là sai tài liệu chương trình. Đồng bộ marlins. Kiểm: typecheck + lint sạch, build web·marlins, check-no-emdash PASS (bắt một em dash lọt từ văn bản gốc), dựng DOM 2 trang mới, chụp đủ ba cụm | 🔵 lên trang, chờ giá Compass và 360 |
| SRC-557 | 2026-08-24 | Chỉ đạo: bỏ gói "Nemo Pass", đè Nemo Swim vào đó; cần trang riêng xem cả 3 gói của con và trang riêng cho các gói của bố mẹ | Hiểu "Nemo Pass" là Nemo Compass (bậc 2 đang "Sắp mở" — không có gói nào tên Pass); xoá Compass, Swim vào bậc 2 với nhãn "Vá chắc nền móng" — lộ trình cho con thành Dive → Swim → 360, hợp lý hơn bản cũ vì bậc 2 giờ là gói có giá và lịch thật thay vì một gói chưa mở. Cụm "Khoá học đang mở" tự biến mất (không còn gói lẻ ngoài lộ trình). Hai trang danh sách: /programs (3 gói của con) và /marlin-programs (3 gói của bố mẹ), mỗi trang có hero + lưới thẻ + link chéo sang nhóm kia; hai cụm trên trang chủ thêm link "Xem trang chương trình…"; nút back của trang chi tiết đổi từ "← Trang chủ" thành về đúng trang danh sách của nhóm. Link cũ /programs/nemo-compass (sống vài giờ) đổ về /programs bằng replaceState thay vì rơi vào "không tìm thấy". Đồng bộ marlins. Kiểm: typecheck + lint sạch, build web·marlins, dựng DOM cả hai trang danh sách (đúng 3 bậc mỗi trang, có link chéo) + alias cũ, chụp /programs | ✅ |
| SRC-558 | 2026-08-24 | Chỉ đạo: /programs chỉ có duy nhất 3 gói của con, /marlin-programs chỉ có 3 gói của bố mẹ | Bỏ đoạn link chéo "Bố mẹ cũng có lộ trình riêng… / Xem lộ trình của con…" ở cuối hai trang danh sách (thêm ở SRC-557) — mỗi trang còn đúng hero + 3 thẻ. Kiểm: dựng DOM cả hai trang, mỗi trang đúng 3 thẻ đúng tên, không còn nội dung nào khác; build web sạch | ✅ |
| SRC-559 | 2026-08-24 | Chỉ đạo (kèm ảnh màn Lab của learn làm mẫu): (a) đưa 2 trang programs lên NavBar; (b) bỏ giá chi tiết trên 2 trang programs; (c) trang chủ không đưa thông tin gói, chỉ link; (d) 2 trang programs và các trang chi tiết ít text, nhiều hình, ưu tiên animation (gợi ý three.js); (e) dùng Design System "biển xanh sâu thẳm" như ảnh cho www và các trang trong đó | Lớp theme od-* (ocean deep) sống RIÊNG trong apps/web/src/index.css, không vào DS chung — learn/marlins/coral giữ bảng gần-đơn-sắc v0.4, chỉ đạo chỉ nói www. Chất liệu đúng ảnh mẫu: nền gradient #2b6ea6→#17517f→#0a2c50, tia nắng xuyên nước (repeating-gradient + mask, trôi 14s), bong bóng nổi 8 nhịp lệch pha, thẻ kính mờ (trắng 8% + viền trắng 26% + backdrop-blur), hình trong thẻ lửng lơ (od-float 5s); hero n12-hero-ocean của www đè từ gần-đen sang cùng gradient để cả site một chất liệu. Không dùng three.js: hiệu ứng trong ảnh mẫu là CSS thuần, ba tầng animation CSS đạt cùng ấn tượng với 0KB thư viện (three.js ~600KB đập vỡ zero-asset), mọi animation tự tắt theo prefers-reduced-motion qua luật DS base. NavBar thêm "Cho con" + "Cho bố mẹ" (nhãn theo người học, không theo tên kỹ thuật). Trang danh sách: thẻ chỉ còn hình N12Art to (tàu ngầm=Dive, cá vượt sóng=Swim, địa cầu=360, la bàn=Compass, vỏ ốc=Mind) + Bước n + tên + một câu, không giá. Trang chủ: khối Chi phí thành hai cửa link "Cho con / Cho bố mẹ" trên nền biển, không còn giá hay mô tả — trang chủ trả lời "đi đâu", trang danh sách "có gì", trang chi tiết "bao nhiêu, thế nào". Trang chi tiết: nền biển, hình nổi, các mục thành accordion kính đóng sẵn (ít text lộ ra, nội dung đầy đủ vẫn còn), giá GIỮ ở đây (chỉ đạo chỉ bỏ ở trang danh sách). Sự cố tự gây khi sửa: lệnh thay Pricing nuốt mất khối ProgramListPage — typecheck chặn được ngay, khôi phục và xoá PackageCard chết. Kiểm: typecheck + lint sạch, build web·marlins, chụp /programs và /programs/dive | ✅ |
| SRC-560 | 2026-08-24 | Chỉ đạo: tạo trang riêng giới thiệu các Dolphins (mentors); trang HOME đừng để quá nhiều thông tin mentor như hiện nay | Trang /mentors thành trang Dolphins riêng (trước đó URL này đổ về trang bố mẹ /cho-bo-me): hero biển + mascot cá heo + câu "Những anh chị đi trước, từng ngồi đúng chỗ con đang ngồi" + câu tin cậy đếm từ dữ liệu + toàn bộ thẻ mentor và cố vấn; bấm thẻ sang hồ sơ riêng /mentors/{slug} (SRC-520). TeamStrip trên trang chủ rút về tối thiểu: tiêu đề + câu tin cậy + một nút "Gặp các Dolphins" — bỏ hẳn lưới 5-6 thẻ mentor; chi tiết thuộc về /mentors, trang chủ chỉ còn lối đi (cùng nguyên tắc SRC-559 với các gói). Nút quay lại của hồ sơ mentor đổi từ /cho-bo-me sang /mentors. Trang /cho-bo-me giữ nguyên danh sách mentor của nó (REQ-BRD-08 — vùng bố mẹ vẫn cần phần "vì sao tin được"). Giới hạn kiểm chứng: API chặn CORS với origin localhost nên preview không nhận được dữ liệu mentor — đã kiểm khung trang + trạng thái rỗng bằng DOM, còn dữ liệu thật dùng chung đường fetch với /cho-bo-me đang chạy tốt trên production | ✅ |
| SRC-561 | 2026-08-24 | Chỉ đạo (hai tin): (a) Marlin Start, Marlin Compass, Marlin Mind là 3 khoá học ONLINE, TỰ HỌC, trên Marlins Portal; (b) NavBar ghi "Nemo Programs" và "Marlin Programs", bỏ nhãn "Cho con / Cho bố mẹ" | (a) supersede phần hình thức của SRC-552: lịch 3 buổi offline sáng Chủ nhật 30/08-13/09 tại Hà Nội của Marlin Start hết hiệu lực — schedule xoá, unit thành "/ khoá", mục Hình thức thành "khoá online, tự học theo nhịp của riêng bạn trên Marlins Portal, đăng ký xong học được ngay"; khối chưa-chốt về giờ học + địa chỉ Hà Nội gỡ bỏ (không còn gì để chốt). Compass và Mind ghi cùng hình thức, vẫn "Sắp mở". CTA trang chi tiết của 3 khoá bố mẹ đổi "Liên hệ đăng ký" → "Học trên Marlins Portal" trỏ thẳng marlins.nemo12.com — khoá tự học thì nút phải dẫn tới nơi học, không dẫn tới người bán. Giá Start giữ 2.000.000 (chỉ đạo không nhắc đổi giá). (b) nhãn NavBar đổi theo tên chương trình, đè lựa chọn "theo người học" của SRC-559; hai thẻ trên trang chủ vẫn ghi "Cho con / Cho bố mẹ" vì chỉ đạo chỉ nói NavBar. Ghi chú tồn đọng: khoá "tự học trên Marlins Portal" hiện là LỜI HỨA trên trang công khai — Marlins Portal chưa có module khoá tự học nào để mở; cần dựng nội dung 3 khoá trên portal hoặc điều chỉnh lời hứa trước khi thu tiền. Kiểm: typecheck + lint sạch, build web·marlins, DOM bản build hết sạch "Hà Nội"/lịch cũ, CTA và nhãn nav mới đều hiện | 🔵 chữ xong, khoá trên portal chưa tồn tại |
| SRC-562 | 2026-08-24 | Chỉ đạo: NavBar bỏ menu "Trường chuyên" | Gỡ đúng LỐI VÀO trên NavBar; route /truong-chuyen và các trang trường vẫn sống (link đã chia sẻ và các trang khác vẫn trỏ tới — chỉ đạo chỉ nói menu, không nói bỏ tính năng SDD-020). NavBar còn: Nemo Programs · Marlin Programs · Nemos · Marlins. Kiểm: DOM bản build đọc đúng 4 mục, /truong-chuyen vẫn mở ra trang danh sách trường | ✅ |
| SRC-563 | 2026-08-24 | Chỉ đạo (hai tin): (a) NavBar bỏ 2 link "Nemos" và "Marlins", thêm link Login dẫn tới trang login mới có lối cho bố mẹ và lối cho con; (b) NavBar bổ sung link tới trang Dolphins | Trang /login theo theme biển sâu: một câu "Bạn vào Nemo12 với vai nào?" + hai cửa "Tôi là bố mẹ" (→ marlins) và "Con vào học" (→ learn) — cùng nguyên tắc hai cửa của trang chủ (WF-19 §2). Không dựng form đăng nhập thứ ba: form sống ở từng cổng (mỗi cổng một Google OAuth client), trang này chỉ là ngã ba hỏi "bạn là ai"; thêm một form nữa là thêm một chỗ phải bảo trì đăng nhập. Login là nút viền (hành động) đứng tách khỏi các mục điều hướng chữ. Dòng "Đã có tài khoản? Đăng nhập" ở hero cũng trỏ về /login thay vì thẳng marlins — trước đây nó ngầm coi mọi người quay lại đều là bố mẹ. NavBar chốt: Nemo Programs · Marlin Programs · Dolphins · Login. Kiểm: DOM bản build đọc đúng 4 mục; /login ra đúng 2 cửa với đích marlins/learn; build + lint sạch | ✅ |
| SRC-564 | 2026-08-24 | Chỉ đạo: (a) tạo Facebook fanpage, LinkedIn, YouTube, X, Threads, Instagram và rà soát mọi mạng xã hội Nemo12 nên có mặt; (b) gắn Google Tag Manager, Google Analytics, Facebook Pixel lên website; (c) gợi ý các việc khác liên quan tới channels. Chốt thêm: DUY NHẤT dac2205@gmail.com quản lý mọi kênh; làm tối đa phần máy làm được, chỉ chừa bước cần đăng nhập | Tạo tài khoản là việc của người, không phải của máy — mọi nền tảng đều đòi mật khẩu, số điện thoại và bấm chấp nhận điều khoản, nên phần (a) dừng ở bản rà soát + tài sản nhận diện; chủ dự án tự đăng ký. Rà kênh theo thị trường thật (bố mẹ Việt 30-45 tuổi): bậc 1 Facebook Page + Facebook Group + YouTube + Zalo OA (không nằm trong chỉ đạo nhưng là kênh chăm sóc phụ huynh mạnh nhất ở VN); bậc 2 TikTok (cũng không được nhắc, nhưng độ phủ tự nhiên cao nhất hiện nay) + Instagram/Threads (chung tài khoản) + LinkedIn (không bán được cho phụ huynh, cần cho tuyển Dolphins); bậc 3 X — chỉ giữ tên, gần như không có phụ huynh Việt. Ngoài social: Google Business Profile + Search Console đứng trên X và LinkedIn về giá trị. (b) đo lường trên www: apps/web/src/analytics.ts là nơi DUY NHẤT giữ ID, đọc VITE_GTM_ID/VITE_GA4_ID/VITE_FB_PIXEL_ID (GitHub repo Variables, không phải Secrets — ID đo lường công khai); CI truyền vào lúc build web. Chưa điền ID thì không script nào nạp — không cần cờ bật/tắt riêng, và site giữ nguyên zero-asset khi chưa chạy quảng cáo. www là SPA nên page_view phải bắn tay mỗi lần đổi route (gtag config send_page_view:false + trackPageView() trong usePath), nếu không GA4 chỉ đếm được một lượt mỗi phiên. Sự kiện chuyển đổi: cta_parent_start/cta_learner_start/cta_package/cta_school_interest/view_package, mỗi cái bắn đồng thời dataLayer + GA4 + Pixel (Lead, ViewContent kèm value+VND). Consent mặc định BẬT, kèm lối từ chối (CookieNotice + nemo12_analytics_consent): VN không có luật buộc chặn-trước như GDPR, chặn-trước làm mất phần lớn dữ liệu chuyển đổi; từ chối thì tải lại trang vì script đã nạp không gỡ ra được. (c) việc kèm theo đã làm luôn: trang /quyen-rieng-tu (Meta và Google đều đòi URL chính sách công khai khi duyệt tài khoản quảng cáo, và Pixel đang đặt cookie trên chính miền này) — nội dung mô tả đúng những gì hệ thống thật sự làm, đổi công cụ đo thì phải sửa trang này cùng lúc; OG + Twitter card đầy đủ cho web/learn/marlins/mentors (trước đó dán link 3 cổng lên Facebook ra thẻ trắng — đây chính là FEAT-052 phiên bản tĩnh); og-image 1200x630 + avatar vuông 1024 dùng chung mọi kênh, sinh từ chính logo cá hề qua scripts/gen-og-image.mjs (sharp, chạy lại được); sitemap.xml sinh từ mã nguồn qua scripts/gen-sitemap.mjs (đọc packages.ts + schoolsInfo.ts, khỏi nhớ hai nơi) + robots.txt cho www, và robots.txt chặn lập chỉ mục cho mentors/coral/admin (noindex cả trong <head> của mentors). Chốt vận hành: mọi kênh do duy nhất dac2205@gmail.com quản lý (chủ dự án đè khuyến nghị social@nemo12.com — đã nêu rủi ro một điểm chết, giữ quyết định); lớp đỡ thay thế là 2FA app + backup codes, Page phải tạo BÊN TRONG Meta Business Manager, YouTube phải là Brand Account, thêm admin thứ hai khi có người. Thi hành 25/08 (chỉ đạo "làm tối đa, chỉ login là việc của tôi", đồng ý Accept ToS qua chat): qua Chrome đã đăng nhập sẵn của chủ dự án — GTM account Nemo12 + container GTM-K8HHG87P (Google Tag bắn GA4, publish v1); GA4 property nemo12.com stream G-EN93KJJXT6 (giờ VN, VND); biến build chỉ điền VITE_GTM_ID (G-ID sống trong GTM, tránh đếm đôi), deploy + kiểm chứng gtm.js nạp và page_view trên production; Facebook Page Nemo12 id 61593603607780 (lần đầu bị chặn "finish SMS verification", lần hai qua; avatar + cover + bio); YouTube Brand Account Nemo12 handle @nemo12com (@nemo12 bị chiếm) id UC08jmn7eb1HwsRt6qkiz6dQ; Search Console verified (file google7e6ae8e4351711b3.html, phải sống mãi ở gốc site) + nộp sitemap 20 trang. Bộ ảnh nhận diện làm lại theo chất liệu biển sâu od-* SRC-559 và thêm 4 cover (facebook 1640x624 · youtube 2560x1440 · linkedin 1128x191 · x 1500x500) trong gen-og-image.mjs. Sự cố tự khai: một lần wrangler deploy thẳng lên production từ máy local (vi phạm luật deploy-qua-GitHub) để kịp file verify — nội dung trùng khít commit d0fb2b1 đã push, CI sau đó deploy lại cùng nội dung nên production khớp main. Thêm trong cùng phiên: LinkedIn Company Page Nemo12 id 143492046 (logo + tagline + website, E-Learning Providers, đại diện được uỷ quyền do chủ dự án chỉ đạo); Zalo OA khảo sát xong — Zalo đã bỏ loại OA thường, chỉ còn "Tài khoản xác thực" đòi hồ sơ doanh nghiệp ngay lúc đăng ký, kẹt ở giấy tờ pháp nhân. Chỉ đạo chốt kênh (25/08 tiếp): BỎ Zalo OA, X, Instagram/Threads, TikTok — không dùng; Facebook username chủ dự án tự đặt xong (nemo12com). Meta Business Manager: đã thử tạo portfolio "Nemo12" ba lần, Meta từ chối im lặng (nghi giới hạn business/tài khoản — profile đang trong 4 business ShopDunk); Business Suite của Page hoạt động bình thường nhưng Pixel + xác minh domain cần portfolio thật — lối ra ghi ở compass /channels-setup. Chỉ đạo ads (25/08 tiếp): chạy ads Facebook Page + Google Search, máy tự nghiên cứu từ khóa. Chỉ đạo này supersede luật "không ads 40 ngày đầu" của GTM §3 — đã ghi chú ngay trên trang. Harness chặn máy thao tác trực tiếp nền tảng quảng cáo (đúng ranh giới tiền), nên sản phẩm là trang compass /ads-plan: 3 ad group Google theo định vị "khám trước" (mất gốc · kiểm tra năng lực · chuyển cấp — tránh sân luyện thi CPC cao), negative list, RSA copy đủ 10 headline + 4 description, campaign Meta Traffic 2 creative, quy ước UTM khớp GA4, ngân sách đề xuất 200k/150k mỗi ngày kèm ngưỡng dừng. Làm rõ với chủ dự án: ads không chạy được TỪ profile cá nhân — profile đăng bài gốc, Page chạy ads. Còn chờ: Business Portfolio (thử lại sau vài ngày hoặc dọn business trống) → Pixel + xác minh domain → Conversions API; Google Ads account + thẻ + link GA4; chốt ngân sách bằng chữ rồi mới bật campaign. Bài đăng đầu tiên (25/08): 3 bài "không khám mà điều trị ngay" (tiền · sức · niềm tin) lên Facebook Page, lưu tại compass /posts/3-pains-khong-kham; luật mới của chủ dự án: mọi bài phải có ảnh (scripts/gen-post-images.mjs, od-*) và link trong bài là link trần không UTM ("URL nhìn kinh tởm"); luật thao tác đóng vào skill /fb-post (composer Business Suite nuốt text 2 lần → đăng qua composer Page, click bằng ref, verify sau đăng, không Delete post); bài text đã đăng KHÔNG thêm được ảnh khi edit — chỉ sửa chữ. Substack chưa có tài khoản. Boost 2 bài mới nhất 100k/ngày (ngân sách chốt bằng chữ): trang Boost Meta treo với trình duyệt tự động sau 2 lần — chủ dự án bấm tay Business Suite → Content → Boost. Sổ tay kênh về Compass (chỉ đạo tiếp 24/08): nội dung vận hành kênh thành trang apps/compass/content/channels-setup.md ("Mở kênh") — trình tự đăng ký, chữ dán sẵn từng kênh, nhận diện, quy ước UTM, trạng thái đo lường; không đè /channels vốn đã có 9 kênh với vai và nhịp, hai trang link chéo nhau. Bốn kênh Compass chưa có (Zalo OA, TikTok, X giữ tên, Google Business Profile) để riêng một mục và ghi rõ không tranh chỗ trong 40 ngày nước rút. Phát hiện kèm: compass.nemo12.com đang mở công khai (curl 200) trong khi là tài liệu chiến lược nội bộ — thêm robots.txt chặn lập chỉ mục, còn Cloudflare Access phải bật tay ở dashboard. Kiểm: typecheck + lint sạch; bản build KHÔNG ID → 0 request ngoài; bản build CÓ ID → nạp đủ gtm.js/gtag/fbevents, page_view đúng path khi đổi route, cta_parent_start→Pixel Lead, /programs/dive→view_package kèm value 3.000.000; bấm "Chỉ cần thiết" → tải lại sạch, 0 script, 0 dataLayer | 🔵 |
| SRC-565 | 2026-08-24 | Chỉ đạo/câu hỏi: cần chỗ cho người xem thấy ảnh chụp cộng đồng và rất nhiều testimonials để tăng niềm tin; hỏi có phải quản lý ở dolphin.nemo12.com và hiển thị ở vài trang riêng trên www | Trả lời: đúng, và một nửa đã có sẵn. Ảnh cộng đồng dùng photo_albums của SDD-019 (đã có CRUD ở dolphin tab Album + API công khai) — chưa ai tạo album nào, đang 0. Testimonials chưa tồn tại: dựng mới. Migration 0075_testimonials — không nhét vào bảng nội dung chung vì cảm nhận là lời khẳng định của người có thật nên cần ba thứ nội dung marketing không cần: consent (đã xin phép nêu tên chưa — đăng lời khen của một phụ huynh mà chưa hỏi là chuyện pháp lý), verified (ai đối chiếu, lúc nào), audience (kể cho bố mẹ khác kể cho học sinh). Cổng publish testimonialPublishBlockers đòi đủ consent + verified, cùng mức chặn với studentPublishBlockers của SDD-020; 4 test khoá luật này. API: GET /v1/public/testimonials?audience=&program= (khai vào allowlist authCoverage) + CRUD /v1/showcase/testimonials. Dolphin thêm tab Cảm nhận, hai nút "đã xin phép" và "đã xác minh" đặt cạnh nhau vì đó là việc chính của màn chứ không phải tuỳ chọn nâng cao; internal_note và consent_note không bao giờ ra API công khai. Web: trang /cong-dong gom cảm nhận + album, thêm vào NavBar; trạng thái rỗng nói thật là chưa có thay vì dựng ảnh mẫu — cộng đồng giả trên trang "tăng niềm tin" là thứ phản tác dụng nhất. program_code để sau này gắn cảm nhận vào đúng trang chương trình. Kiểm: 568 test API + 6 test web xanh, typecheck + lint sạch, build 3 app, migration đã áp lên D1 remote và xác minh bằng pragma, DOM /cong-dong ra đúng tiêu đề + trạng thái rỗng + nav 5 mục | 🔵 hạ tầng xong, chưa có dữ liệu thật |
| SRC-566 | 2026-08-24 | Chủ dự án 2026-08-24: dùng Shadcn cho learn.nemo12.com và nemo12.com, bản mới nhất; Tailwind cũng cần mới nhất hết | Tailwind đã sẵn 4.3.3 tức bản mới nhất (kiểm npm view), Vite 8.2.1, React 19.2.8 — không phải nâng gì. Việc thật là cài shadcn mà KHÔNG mở ra hệ token thứ hai: cách cài mặc định của shadcn dán cả bảng màu của nó vào index.css, đúng thứ RISK-012 và DS-001 paragraph1 sinh ra để chặn (legacy từng có 6+ hệ token song song). May mắn có thật là DS-001 đã đặt tên token theo đúng quy ước shadcn nên phần lớn khớp sẵn; phần còn thiếu khai trong packages/design-system/shadcn-bridge.css và khai bằng cách TRỎ VỀ token DS-001, không một giá trị màu thô nào. chart-1..5 trỏ về bốn màu trạng thái học đã có nghĩa cộng điểm màu hành động, thay vì bịa năm màu biểu đồ mới. Dùng thật ngay: accordion tự dựng ở LabPlayer thay bằng shadcn Accordion type=multiple — chính là luật đừng-đóng-mục-khác của chủ dự án, và bàn phím/aria do Radix lo. Cổng check-shadcn-tokens chặn app khai lại bảng màu, nhưng CỐ Ý không bắt theme có scope như .n12-deep (SRC-348) vì đó là quyết định thiết kế có chủ đích trong phạm vi mình; cổng bắt oan thì người ta gỡ cổng. Nợ ghi rõ trong DS-001 paragraph2: components/ui là bản sao trong từng app, chưa qua luật cấm-fork, phải kéo về packages/design-system nếu hai app bắt đầu sửa lệch nhau | ✅ |
| SRC-567 | 2026-08-24 | Chủ dự án 2026-08-24: chỉnh nốt để các webapp sau dùng shadcn hết — marlins, coral, admin, pearl, dolphin, compass | dolphin.nemo12.com chính là app mentors trong repo (truy ra từ wrangler routes) nên nó nằm trong nhóm React cài được. Bốn app React marlins, coral, admin, mentors cài đủ: alias @, lib/utils, components.json, 9 component, nạp shadcn-bridge.css — tổng cộng SÁU app React dùng shadcn. Pearl và Compass thì KHÔNG cài được và phải nói thẳng: chúng là VitePress tức Vue, còn shadcn là React cộng Radix, không có đường cài mà không dựng lại toàn bộ thư viện. Phần làm được đã làm: nạp cùng shadcn-bridge.css vào theme VitePress của pearl, compass và cả docs, để radius, popover, màu biểu đồ của trang tài liệu không lệch khỏi phần còn lại của hệ. Cổng check-shadcn-tokens thêm luật thứ hai: app nào có components.json mà chưa nạp cầu nối là đỏ — quên nạp thì component shadcn rơi về màu mặc định của thư viện, đúng kiểu hỏng âm thầm mà cổng sinh ra để bắt | ✅ |
| SRC-568 | 2026-08-25 | Chủ dự án 2026-08-24: tất cả mọi chỗ loading thì có hình con cá bơi bơi và mấy bong bóng nổi nổi lên mặt nước; thậm chí cố tình có thêm những đoạn loading đó, để learner chờ tầm 3 tới 5 giây, cho vui | SwimmingLoader vẽ cá và sáu bong bóng bằng SVG cộng CSS thuần — không bitmap theo luật cũ, và không tiêu khung hình JavaScript nào đúng lúc trang đang bận tải. Ranh giới cố ý: cá bơi cho chỗ chờ CẢ MÀN, còn chỗ chờ MỘT Ô trong bố cục đã dựng thì giữ skeleton vì hình dạng của ô nói được sắp có gì ở đây còn con cá thì không. Về phần cố tình làm chậm, tôi làm nhưng đóng khung lại và ghi rõ lo ngại: làm chậm mọi thứ 3-5 giây là cách nhanh nhất giết một app học vì learner mở app mỗi ngày vài chục lần chuyển màn, cái vui lần đầu thành cái bực lần thứ hai mươi. Ba luật: sàn chứ không cộng thêm (đồng hồ chạy từ lúc bắt đầu tải, mạng nhanh thì lấp phần thiếu, mạng chậm thì không cộng); chỉ ở chuyển cảnh lớn là vào Experience, mở Lab, bắt đầu bài khám, còn màn mặc định và fetch nền thì không có sàn; tắt được bằng prefers-reduced-motion hoặc nowait=1. Sàn 3s là đầu khoảng chủ dự án nói chứ không phải 5s. Kiểm bằng mắt trên bản chạy đã bắt được hai lỗi thật: cá màu xám gần tàng hình trên nền biển sâu, và cá bơi ra ngoài khung gần nửa chu kỳ | ✅ |
| SRC-569 | 2026-08-25 | Chỉ đạo: sửa màn Dashboard trong báo cáo con ở marlins, tái sử dụng code và UI của vùng "How solid am I in Mathematics?" bên learn | packages/design-system/ui/MasteryMap.tsx — trích NGUYÊN AllMap + MasteryBar + các helper mastery từ apps/learn/src/ProgressViews.tsx, không viết lại; onSel/pinnedKeys thành TUỲ CHỌN nên marlins dựng bản chỉ-đọc (ghim Focus và "Vào học" là quyền của learner); bỏ useLang của learn, nhận thẳng cờ en. marlins/ProgressViews.tsx bỏ lưới vòng tròn số + AreaRow + ModulePopover, thay bằng MasteryMap với 3 mức xem Gói/Chủ đề/Từng bài. Vòng tròn cũ trộn coverage và mastery vào một hình nên không đọc tách được hai đại lượng. Chưa làm: learn vẫn giữ bản trong file của nó — xem ghi chú trong commit | 🔵 |
| SRC-570 | 2026-08-25 | Chủ dự án 2026-08-25: toàn bộ learn.nemo12.com đã xài Shadcn chưa? Nếu chưa thì chỉnh toàn bộ Design System rồi chỉnh UI theo nó, cả nemo12.com và marlins.nemo12.com; bắt buộc mọi page nhỏ đều dùng Shadcn 100% giao diện và components | Trả lời thẳng: chưa, trước đợt này shadcn mới dùng ở đúng một chỗ (accordion trong LabPlayer). Đợt SRC-569 chuyển 592 chỗ trong 68 file trên 6 app bằng codemod chứ không sửa tay, vì 85 file với hàng trăm điểm chạm thì sửa tay vừa lâu vừa chắc chắn sót; codemod biến mỗi phép đổi thành một luật đọc được và chạy lại được. Biến thể Nemo12 (accent, school, outline, ghost, cao 44px, bo tròn hoàn toàn) đặt trong chính components/ui/button.tsx theo đúng mô hình shadcn code-thuộc-repo, không dựng file thứ hai. Ba lỗi codemod đã mắc và ghi lại vì đều là bẫy chung: regex dừng ở mũi tên của arrow function trong onClick nên bỏ sót phần lớn nút; gộp thẻ nhiều dòng làm comment nuốt phần còn lại của biểu thức; đổi section aria-label thành div làm mất landmark region, e2e bắt được ở trang Hồ sơ. Chưa đạt 100% và nói rõ: còn các className động và thẻ hiếm, luật template literal viết rồi nhưng tạm khoá vì bộ đếm thẻ đóng lệch khi trong khối đã có Card xen div. Cổng check-shadcn-adoption chốt số chỗ còn lại làm trần chỉ đi một chiều, thêm là CI đỏ | ✅ |
| SRC-571 | 2026-08-25 | Chủ dự án, 2026-08-25: màn Dashboard marlins quá bí so với learn; bấm thẻ bên learn ra popover; toàn bộ marlins.nemo12.com cần dùng màu và theme như màn Lab (learn.nemo12.com/turtle/lab/math/b21-read-tables-and-charts) | Bản đồ mức vững ở cổng phụ huynh dùng chung code với learn, có popover khi bấm thẻ, và cả cổng Marlins mặc một theme biển sâu duy nhất | ✅ |
| SRC-572 | 2026-08-25 | Chủ dự án, 2026-08-25: hệ thống page của marlins rối, không phân tầng khoa học. Cần xếp hạng JTBD của bố mẹ, vẽ lại site-map, và làm trang chủ + trang kế tiếp thành trang ĐIỀU HƯỚNG THUẦN (không có thông tin cụ thể), giảm số element, giấu bớt và chỉ hiện khi bấm | Marlins phân ba tầng: chọn con → chọn việc → nội dung. Hai tầng đầu chỉ điều hướng, đặt tên theo câu hỏi của bố mẹ chứ không theo tên tính năng | ✅ |
| SRC-573 | 2026-08-25 | Chủ dự án 2026-08-25 (hai ảnh): vì sao tài khoản lớp 8 mà hệ cứ bắt học bài lớp 5? Và vì sao ảnh 1 ghi Read tables and charts nhưng click vào lại nhảy sang một cái gì đó khác? | Hai lỗi khác nhau, không phải một. MỘT — bài lớp 5: SRC-545 mới siết nhánh chọn bài NỀN, còn nhánh VIỆC ĐANG DỞ thì không xét lớp; chính bài lớp 5 ấy do hệ mời sai tầm TRƯỚC bản vá, learner bấm vào một lần là nó thành đang-dở và từ đó tự giữ chỗ đầu hàng mãi mãi. Nay việc đang dở lệch quá 2 lớp so với learner thì thôi làm việc chính, xuống thẻ đã-làm-gần-đây và vào lại được bất cứ lúc nào — đây là chuyện thứ tự ưu tiên chứ không phải chặn đường; ngưỡng 2 chứ không phải 1 vì ôn lại bài năm ngoái năm kia là bình thường và đáng khuyến khích, còn unit CAO hơn lớp learner thì không bao giờ bị hạ vì học vượt là quyền của learner. HAI — không hề nhảy sang cái khác: vẫn đúng unit đó, chỉ là trang chi tiết Unit (SRC-541) chưa có chữ nào trong bảng dịch nên bật EN xong bấm vào là gặp nguyên tiếng Việt, đọc ra thành một trang lạ. Đã dịch tên unit, tên module, nhãn Experience, nhãn Lớp và nút Học tiếp | ✅ |
| SRC-574 | 2026-08-25 | Chủ dự án, 2026-08-25: trang báo cáo của marlins nền trắng, chữ trắng trên trắng nên mất chữ; chân trang cần màu xanh đáy biển; ba nút Gói/Chủ đề/Từng bài cần thành ba icon ở góc trên trái như cụm How solid am I | Vỏ toàn màn hình của trang báo cáo mang cùng theme biển sâu; chân trang có biến thể đáy biển; chọn độ sâu bản đồ bằng icon dùng chung với learn | ✅ |