15 KiB
Implementer-Frontend Agent — Persistent Memory
- S171 (2026-08-04) lane FE — 🔴 CHẾT Ở LƯỢT TRẢ VỀ (
API Error: Connection closed mid-response, engine nhậnverdict: null)[LEAD HARVEST HOI-TO @S172 — no mo tu closeout truoc; owner slot (71) chot 'gom va sleep thi auto, tu quyet'. Nguon = artifact tren dia, KHONG suy dien]; nguồnruns/2026-08-04-S171-khkk-ui-mirror-pe/sub-implementer-frontend-s171.md13.132 B = **BIÊN BẢN LEAD-ON-BEHALF**, không phải lane tự khai: 🔴 Nhật-ký GỐC = 642 B, đúng 7 heading, RUỘT RỖNG HOÀN TOÀN — lane ghi khung ở lượt 1-2 đúng luật nhưng KHÔNG append dòng nào sau đó. 🔴 Đây là ĐỐI CHỨNG SẠCH trong cùng một phiên, và nó SIẾT LẠI luật chống-#53: 3 lanereviewer(khung ✅ + append ✅) cứu 74.070 B dù cả 3 chết hết-giới-hạn ·implementer-backend(khung ✅ + append ✅) return SẠCH · lane này (khung ✅ + append ❌) mất trắng. ⇒ khung-rỗng = CẦN, KHÔNG ĐỦ; APPEND-sau-mỗi-đơn-vị-việc mới là cái cứu. Câu cũ 'ép ghi khung rỗng lượt 1-2' từ nay cấm trích cụt. 🔴 Ranh phải giữ — MẤT CODE ⟂ MẤT NGHĨ: cái lane LÀM đo được từ đĩa (20/20 acceptance tĩnh ×2 app · mirror 8/8 · build 3/3, lead tự đo sau khi agent dừng hẳn); cái lane NGHĨ mất trắng — 0 bản ghi trade-off/lý-do. Đó là lý do §4 (nợ E-7) TRỐNG và không ai dựng lại được. Đừng hứa 'recover trọn' cho ca write-lane. ⚠️ Kèm: MFE @S172 đo vai này 11/13 = 85%, role duy nhất dưới 100% trên 23 role. Tag[s171, chet-o-luot-tra-ve, khung-rong-can-khong-du, mat-code-vs-mat-nghi, e7-khong-dung-lai-duoc, mfe-85]
Persistent diary cross-session. Auto-injected @spawn (L1 HOT). Update BEFORE every stop. Tiered Memory v1: L1 HOT soft-cap ~30KB · L2
archive/on-demand · L3 RAGsearch_memoryjust-in-time. Keep entry ≤ 1.5K chars (gotcha #53). Compact @S166 (2026-08-01) — L1 chạm trần đọc (26.9KB) ⇒ S113→S166 verbatim dờiarchive/2026-H2.md, dưới đây chỉ còn móc 1 dòng. NEW agent S39 (2026-05-29) — split từ implementer (FE 2 app half). Backend scaffold history ởimplementer-backend.
🧠 Bài học SỐNG (đọc trước khi nhận việc — KHÔNG archive)
- ĐO ĐĨA TRƯỚC KHI GÕ. Tiền-đề lead sai 5 lượt liên tiếp (S164 · S166-K4a ×2 · K4b · K5) theo 2 hướng: "tưởng chưa có" (bảo tạo
KHKK_GROUP_LABELSkhi map đã tồn tại 5 call-site ⇒ tạo thêm là phá đúng acceptance single-source mà nó phục vụ) và "tưởng có" (bảo đi qualines[].contractId— field không tồn tại ở cả FE lẫn BE). Lead đọc transcript dở-dang → kết luận theo Ý ĐỊNH đang chạy, không theo đĩa. Viết lại phần đã đúng = phá. Bịa field cho khớp đề bài = tệ hơn. - Đề bài mô tả CÁCH LÀM có thể giết feature đang sống. "
phasederive từ searchParams thayuseState" nguyên văn ⇒ 6 chip lọc thành nút chết (hỏng CÂM, build xanh). Đọc kỹ còn ai ghi vào state đó trước khi đổi nguồn. - Phép đo phải có RĂNG — luôn kèm CONTROL-ÂM. 0-hit trần / "0 cảnh báo" vô nghĩa nếu chưa chứng phép đo bắt được cái sai (im-vì-đúng ⟂ im-vì-câm). Chuẩn đã dùng: tiêm lỗi vào chính khối text đã ship rồi xác nhận FLAG nổ.
- 🔴 Mô phỏng framework thì phải mô phỏng CẢ vòng đời. Harness K4b bản-1 đo nhầm cái render React đã VỨT (setState trong render ⇒ React huỷ render đó + render lại trước khi commit) ⇒ nhánh thật và control-âm ra CÙNG kết quả = phép đo mất khả năng phân biệt, trông y hệt PASS. Lặp tới khi state đứng yên mới đúng.
- Chứng bằng cách CHẠY text đã ship, không chép tay:
indexOf('<neo>')→ slice →new Function; dữ liệu thử sinh từ nguồn BE thật (MenuKeys.cs/DbInitializer.cs). Mọi phép thế text phải assert-khớp trước, không khớp thì script tự chết. - Bất-biến nên là CẤU TRÚC, không phải kỷ luật. Giữ 1 danh sách phẳng canonical để đếm, phần chia nhóm chỉ chia lại chính nó ⇒ Σ luôn khớp; assert chỉ là chuông cho người sửa sau.
- Forward-provision = đổi HÌNH DẠNG (đọc-1-ô → gom-một-TẬP), KHÔNG bịa field. Thiếu nguồn thì đánh dấu chỗ cắm + trích nguyên văn bằng chứng + FLAG cho lead.
- Sai-thầm-lặng → đổi thành thiếu-nhìn-thấy-được. BE
/deletedkhông nhậngroup⇒ KHÔNG cho UI claim nhóm ở màn đó. Rỗng-vì-lọc ⟂ rỗng-vì-chưa-có-gì phải khác câu (dùng chung ⇒ user nhóm N5 tưởng cả module chưa cấu hình). Phiếu nhóm lạ gom vào "(chưa phân nhóm)" thay vì rơi ra ngoài. npm run build=tsc -b && vite build+noUnusedLocals⇒ build LÀ phép thử TS6133 thật; đừng tin IDE diagnostic (gotcha #68).- Mirror ×2 app: cái KHÔNG đổi cũng là bằng chứng. File không sửa mà hash BẰNG baseline = đối chứng dương cho phép đo hash. Lệch có chủ đích (fe-admin không có
WorkflowMatrixViewPage) phải KHAI tại chỗ, không mirror mù. - Validate query-param bằng REGEX CHUỖI, không
Number().Number("03")=3lọt lưới;/^[1-8]$/chặn. Và chốt chặn kép khi param chỉ có nghĩa với 1 ngữ cảnh (type===10 && regex). - Lọc client-side thì KHÔNG thêm trục vào
queryKeynếu payload đã tải trọn — thêm = N lần gọi mạng cho cùng một payload + N ô cache trùng. Ngược lại, trục làm ĐỔI request mà thiếu = cache dùng chung sai CÂM. - Muốn ĐẾM cái UI hiển thị thì DỰNG LẠI dữ liệu thật rồi chạy chính bộ lọc đã ship — đừng đếm bằng mắt/suy luận. Và cho phép đo tự kiểm: cây menu dựng lại được đối chứng bằng invariant T6 (mọi key
MenuKeys.Allphải có menu-row) — dựng sai thì chỉ số đó vỡ trước. - Route-resolver có nhánh ≠ thứ đó tồn tại.
resolvePathnhận code'Contract'không có nghĩa menu-rowAwV2_Contracttồn tại (0 hit repo). Cùng họ với "bịa field": đọc nhánh code rồi suy ra dữ liệu là suy ngược. - 🔴 Khuôn chỉ port được khi VỎ TRANG cùng hình dạng — đo BỀ NGANG bằng SỐ trước khi mirror. Khuôn cột-trái
19remsinh ra cho trang GIẤY-CUỘN; trang 3-PANEL cao-cố-định (h-[calc(100vh-4rem)]+grid-cols-[320px_1fr_360px], grid KHÔNGgap) không có 304px dư: sidebarxl:w-80⇒ @1366 panel chi tiết 346px→42px. Mirror-y-hệt ở đây = hỏng CÂM (build xanh). Cộng bề ngang ra số TRƯỚC, và nhớ cơ chế thu gọn của component có thể làlg:hidden= chỉ sống ở dải mà panel kia đã ẩn ⇒ vô dụng ở desktop. - 🔴
titletrên controldisabled= CÂM ở Chromium (Chrome/Edge nuốt sự kiện chuột của form-control disabled ⇒ tooltip không bao giờ bật;<label>bao ngoài KHÔNG tự thừa kế). Chỗ cắm đúng =<label>/wrapper không disabled. Hệ quả nặng hơn: thông tin PHÂN BIỆT không được nằm sau hover — 1 ô khoá "vì lý do KHÁC" mà chỉ nói bằng tooltip thì trông y hệt N ô khoá "chưa áp dụng" = ngược nghĩa, phải có chữ nhìn-thấy-được. Thêm chữ vào ô con củagrid grid-cols-2: sibling auto-place rơi sang cột 1 (đọc nhầm sang ô bên trái + đẩy lệch các ôcol-span-2) ⇒ ghimcol-start-2.
📌 Nhật ký (móc 1 dòng — verbatim → archive/2026-H2.md, cũ hơn → archive/2026-H1.md + _INDEX.md)
- S182 (08-08) vá MAJOR-1 (reviewer pre-commit bắt) — 8
titledời<input disabled>→<label>ởApprovalWorkflowsV2Page(admin-only, 0 cặp mirror). Reviewer liệt 7 site, grep cùng-lớp ra site thứ 8:1443(K3, có sẵn) — vá kèm. Ô #4 thêm chữ hiệncol-start-2vì tooltip là thông-tin-phân-biệt. Vùng cấm đo lại sau khi vá: 9/9checked=byte-identical · #8Finalize0disabled/0title. Control-âm: tiêm lại 1 title vào input ⇒ checker nổ đúng 1. FLAG-C treo: nút "+ Thêm NV":1226cùng bệnh, ngoài scope ⇒ khai không chạm.[s182, title-tren-disabled-la-cam, grep-cung-lop-ra-site-thu-8] - S167 (08-01) GĐ3 cây 4-folder lên cụm Duyệt-HĐ → BLOCKED @§0, 0 file chạm. 7 loại HĐ = 1 component trang (
?type=), KHÔNG 7 file. 3 lệch tiền-đề: vỏ 3-panel không nhận khuôn cột-19rem (@1366 còn 42px) · fe-user có 3 ứng viên trang (MyContracts/Inbox/WfMatrix) vs admin 1 · cặp trang KHÁC FILE (ContractsListPage⟂MyContractsPage) ⇒ SHA-pair identical bất khả thi (đối chứng dương: 4 cặp component/hook/HardCopies BẰNG nhau). +K6 đã ẩnContractskhỏi sidebar admin ⇒ nửa admin là trang deep-link-only.[s167, khuon-can-cung-vo-trang, sub-implfe-gd3.md] - S166 (08-01) K6 admin thu gọn về vai NƠI-CONFIG (fe-admin ONLY 1 file, fe-user 0-diff).
filterForAdminlọc ĐỆ QUY ⇒ chỉ liệt 12 ROOT; dựng lại cây seed 200 node rồi chạy bộ lọc đã ship ⇒ 166 lá → 15 lá liệt đủ tên, tự-kiểm bằng invariant T6 (113 keyAll→ 0 thiếu row). Comment vá lineage 2 lần đảo.[s166, k6-admin-thu-gon, route-resolver-khac-menu-row] - S166 (08-01) K4c WfView lọc nhóm (chốt cụm-2, fe-user ONLY 1 file, fe-admin 0-diff). Lọc
wf.code === khkkGroupWorkflowCode(n)client-side ⇒ không đổi queryKey (khai rõ); rỗng-vì-lọc tách câu riêng. 21/21 proof + 2 control-âm.[s166, khkk-k4c-wfview-loc-nhom] - S166 (08-01) K5 cây toàn-trình GĐ2 mở 8 sub-folder nhóm + forward-provision B3-A5.
groupschia lạileavesphẳng ⇒ Σ theo cấu trúc; hiện đủ 8 kể cả rỗng + "(chưa phân nhóm)";lines[].contractIdKHÔNG tồn tại → union 1-nguồn + FLAG. 15/15 proof (CA4 tiêm lỗi). SHA 4/4 pair (2 đổi + 2 đứng yên = đối chứng dương).[s166, khkk-k5-8-sub-folder] - S166 (08-01) K4b nối
?group=+ vá-3/5/6. Override 3-trạng-tháichipPhase+ reset-trong-render theonavKey(KHÔNG useEffect); queryKey +group; staticMap G1 user 6/6 · admin 5/6. Harness đo nhầm render bị vứt.[s166, khkk-k4b-group-wire, harness-do-nham-render-bi-vut] - S166 (08-01) K4a regex 42 leaf
Khkk_G{2..8}_*+ DERIVEkhkkGroupMenuLabel(không đẻ map-2) +khkkGroupWorkflowCode. 42/42 resolve + 3 control-âm.[s166, khkk-k4a-regex-42-leaf, tien-de-lead-sai-x2] - S164/S165 (07-31) K2 KHKK nhóm-duyệt N1–N8 — badge trong ô (không đẻ cột) ·
colSpan7→8 hai chỗ = lỗi CÂM · việc thật ≈1/4 mô tả.[s164, do-dia-truoc-khi-go, colspan-loi-cam] - S161 (07-29) ARC W1+W2+W3đ1 KHKK FE 3 lượt — containment 2-LỚP render+payload (chỉ
disabled= giả) · types-theo-ENTITY · FE tự suy ✓/●/○ từ con-trỏ đôi.[s161, containment-2-lop] - S153 (07-26) ctx-adopt T2+T5 — writeGuard là 2 ĐIỂM,
:235(vào prompt) mới có RĂNG ·node --checkfile thô luôn SyntaxError.[s153, t5-writeguard-2-diem] - S134 (07-17) PE lũy kế TẠM TÍNH —
sub?: ReactNodeslot-prop chèn sub-dòng vào N render-site không nhân bản markup.[s134, sub-slot-prop] - S133 (07-17) PE budget-freeze badge — className header LẶP 2 chỗ ⇒ anchor phải kèm text visible.
[s133, anchor-by-visible-text] - S117 (07-14) PE duyệt-theo-KHOẢNG radio-5 — spread conditional TRƯỚC
as T[]cast ·??undefined= omit-key axios.[s117, spread-conditional-before-as-cast] - S116 (07-13) PE nhập số ÂM — toggle dấu phải commit NGAY (chỉ flip cờ = mất dấu thầm lặng) · quote ở
details[].quotesKHÔNGsuppliers[].quotes.[s116, sign-toggle-immediate-commit] - S113 (07-12) Supplier publish/draft — publish qua endpoint riêng, KHÔNG qua UpdateSupplier (#73).
[s113, publish-not-update] - S152 (07-25) 2 ranh auto-refuse: việc <30min/trivial = em-main solo · KHÔNG hạ chuẩn dù bị giục (thiếu mirror-SHA hoặc build ×2 = trả lại).
[s152, no-lower-bar] - Cũ hơn (S65→S97: office-dashboard · dept-parent · capability-flag · hosolink…) →
archive/2026-H1.md.
🎯 Role baseline
WRITE specialist FE 2 app (fe-admin + fe-user). Cookie-cutter mirror SHA256 IDENTICAL + Pattern 16-bis 4-place + declarative KIND_CONFIG + npm build ×2. Case 1+2 only. Tools: Read, Edit, Write, Bash, Skill, Grep, Glob + 5 RAG. Skill: permission-matrix.
🚫 Split boundary
- ✅ MINE:
fe-admin/src/**+fe-user/src/** - ❌ NOT:
src/Backend/**→implementer-backend(chỉ Read DTO shape) ·tests/→test-specialist - ❌ NOT: UX flow decision (drawer/tab/modal, mở-sẵn hay đóng) → em main solo
📋 Patterns proven
- Pattern 16-bis 4-place mirror (9× cumulative): page/types ·
App.tsxRoute ·lib/menuKeys.ts· ⚠️Layout.tsxresolvePathstaticMap (DỄ MISS → silent sidebar drop, gotcha #50). Spec MUST list 4 places explicit. - SHA256 IDENTICAL ×2 app: viết 1 bên →
cp→sha256sum. Khác UX thì mirror tay +diff+ KHAI lý do tại chỗ. - Declarative KIND_CONFIG Record (3× proven):
:kindURL +Record<Kind,{fields,columns,icon,label}>. ADD-KIND = union + entry + KINDS + renderCells branch + icon; 0 route mới. - Pattern 14 Tailwind JIT: class động bị purge → full literal
as const, cycleindex % length. - TS6:
erasableSyntaxOnlycấmenum→const X = {...} as const+type X = typeof X[keyof typeof X]. Tupleas constcầnas readonly number[]mới.includes(n: number)được. - Named export only (trừ
App). UI 100% tiếng Việt. fe-user thiếu Card/Badge shadcn → fallback inline<div className="rounded-lg border bg-card">. - ⚠️ PageHeader KHÔNG một chuẩn: bản
@/components/PageHeader=title/description/actions; bản@/components/ui/PageHeader(pipeline/KHKK) thêmeyebrow/subtitle/icon/accent. Đọc bản đang import trước khi truyền prop (bài S37, lặp lại @K4c).
✅ Verify protocol
npm run build ×2 app BOTH 0 TS error + sha256sum mirror proof + proof-script có control-âm cho mọi khẳng định "đủ/đúng/không sót". Bundle >500KB + INEFFECTIVE_DYNAMIC_IMPORT realtime.ts = warning PRE-EXISTING, OK.
⚠️ Anti-patterns (DO NOT)
- ❌ Touch BE files · 2. ❌ Miss 4th Layout staticMap · 3. ❌ Skip npm build ×2 · 4. ❌
git add -A· 5. ❌ Push/commit — em main commits · 6. ❌ UX decision autonomous → REFUSE · 7. ❌ Bịa field cho khớp đề bài → FLAG.
🔄 Curate trigger
L1 > ~30KB hoặc chạm trần đọc → archive verbatim sang archive/<period>.md, L1 giữ móc 1 dòng. Commit scope (em main commits): FE-Admin · FE-User.