Files
solution-erp/.claude/agent-memory/reviewer/MEMORY.md
pqhuy1987 57e672f71f
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
[CLAUDE] Docs: S179 closeout — va doi STYLE 2 vong (C7 bat 2 MAJOR trong chinh ban va) + H24 9 FLAG + drift-audit thang
SUA-1..6b tron 6/6, acceptance C1-C6b 12/12. Vong-2 sua chinh vong-1 sau reviewer C7 (PASS-WITH-8, 3 MAJOR):
- Doi ba-cham -> hai-cham la REGRESSION co dieu-kien, KHONG phai cosmetic: chi tuong-duong khi origin/main
  con ancestor; cay phan-ky thi hai-cham liet ca file CHI CO tren origin/main (= DA PRODUCTION) vao "phan MOI".
  Thu pham that = git diff mu untracked. Sandbox 2 chieu CONFIRMED.
- git status --porcelain | cut -c4- de path RAC (rename in MOT dong "R old -> new"; path co dau cach bi quote).
  Sandbox: 2/2 MISS; thuoc moi 2/2 OK.
- Thuoc CHOT 4/4 site: { git diff --name-only origin/main...HEAD; git diff --name-only HEAD;
  git ls-files -o --exclude-standard; } | sort -u

Bai: chan-doan sai VAN pass acceptance — acceptance do HINH-DANG chuoi, khong do HANH-VI.

Lop mo-neo TU-VO-HIEU: con-tro so-dong tro vao CHINH tep chua no tu thoi moi lan sua dau tep
(112->118->121 trong 1 phien) => neo TEN, khong neo SO DONG. Ap cho index.css, gotchas.md, PipelineStageFolders.
Con-tro verbatim _mind doi ve commit DA PUSH (ee21056/d081681) — ban truoc tro 727a512 nam trong dai squash
=> tu de con-tro mo-coi.

H24 light-audit 9 FLAG, flush 8 o canonical: Mig 71->72 - Gotchas 86->87 - Tests 644->645 (chay that
dotnet test: 45 Domain + 600 Infra, 0 fail) - user-mem 59->60 - header S168->S179 - roster 23->26 (go han so
theo B1) - HANDOFF dong 4 slot (68)-(71) + E4.

"So noi doi theo huong BI QUAN" x3 ca/1 phien (4 slot - E4 - run.md S173) => leo thang lan 3 phai DO LAI TIEN-DE.

Kem: 2 NO vong-3 - 2 synthesis ORPHAN (run-chua-gom 2->0) - di-tru cua-so 6 vao _context - keo+ap 2 thu
loi-do-luong (BAC Lop 8 CO SO: mtime cum SE 0,7% vs hub 69%) - drift-audit thang PASS_WITH_FLAGS-8 (va 2, con 6)
- _mind 99,67%->84,2% - don 9 dir rong - archive-gate strike 1/2.

#53: 4/4 vai garble return dau, vot tron 4/4 bang resume-in-session. Mat 0 byte.

0 file code nghiep-vu. Build 2/2 app PASS. Test 645/645.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 12:25:55 +07:00

127 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Reviewer Agent — Persistent Memory
- **S179 (2026-08-07) C7 re-review sau vá SỬA-1..6b — `PASS-WITH-8`, 3 MAJOR `[LEAD SEED ON-BEHALF]`:** 🔴 **Lượt ăn tiền nhất từ trước tới nay của vai này: 2/3 MAJOR là lỗi TRONG CHÍNH BẢN VÁ vừa pass 12/12 acceptance.** [1] `git status --porcelain | cut -c4-` **đẻ path RÁC** — rename in MỘT dòng `R old -> new`, path có dấu cách bị quote; lead dựng sandbox đo lại: **2/2 MISS**, thước đề-xuất **2/2 OK**. [2] đổi ba-chấm→hai-chấm **KHÔNG vô-hại mà là REGRESSION có điều-kiện** — lead ĐÚNG rằng md5 y hệt, nhưng chỉ khi `origin/main` còn ancestor; sandbox phân-kỳ: hai-chấm liệt cả `upstream_only.txt` (= ĐÃ PRODUCTION) vào "phần MỚI", ba-chấm ra đúng. ⇒ **thủ phạm thật luôn là `git diff` mù untracked**, lead gán sai tội cho ba-chấm. [3] khối MIRROR lead vừa viết mang số `:112` trong khi chính 6 dòng đó đẩy thành 118 — **mỏ-neo TỰ-VÔ-HIỆU ngay lúc viết**; lead vá thành `:118` thì 3 dòng vá đẩy tiếp thành 121 ⇒ **sửa gốc = bỏ số dòng, neo TÊN SELECTOR**. [4] census "8/9 khoá" của lead THIẾU — §D gốc 25 mục, **3 ý đóng im lặng**, 1 trong 3 (`Đợt B — NỘI DUNG từng mục`) **0 hit ở cả `_mind` lẫn `_context`**. [5] con-trỏ verbatim `ca9208f` sai (thiếu 4.636 B) ⇒ lead vá **per-block**: `d081681` cho MIND-1, `727a512` cho 3 block S179, đối chứng từng cái resolve ra bản CHƯA nén. 🔸 **Bài đắt nhất:** *chẩn-đoán sai vẫn pass acceptance* — cả 2 MAJOR lọt vì acceptance đo **HÌNH-DẠNG chuỗi**, không đo **HÀNH-VI**. 🔴 #53 garble, resume vớt trọn; mảnh garble mang "a third thước defect" ⇒ lead biết có cái thứ 3 trước khi đọc verdict. Tag `[s179, C7, bat-loi-trong-ban-va, ba-cham-dung-hai-cham-regression, cut-c4-path-rac, moc-neo-tu-vo-hieu, acceptance-do-hinh-dang-khong-do-hanh-vi]`
- **S171 (2026-08-04) — 3 lane lens ĐỐI-KHÁNG (`/fable-clone reviewer` ×3), **cả 3 CHẾT hết-giới-hạn nhưng ĐĨA CỨU 74.070 B** `[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ồn `runs/2026-08-04-S171-khkk-ui-mirror-pe/sub-reviewer-lens-{feasibility,regression,fidelity}-s171.md` 26.461 + 24.432 + 23.177 B`:** **feasibility 8 ĐẠT / 6 BROKE** — mở đầu bằng **tự bác giả-thuyết của chính lane** (*'chỉ ghi 1 nhánh' = SAI; claim D-2 HELD, ≥9 chỗ ghi → thật 10*); bắt **trích-dẫn hỏng dạng nhẹ**: `WorkflowService.cs:552` **không trỏ vào cái gì cả** (call-site thật `:485`/`:554`, định-nghĩa ở file KHÁC) nhưng **nội dung claim vẫn HELD***cite sai ≠ claim sai*, phải tách. **regression 8 ĐẠT / 4 BROKE / 10 bỏ-sót** — phát hiện nặng nhất: **A-6 kiểm SAI KHOÁ ⇒ lỗ thủng NGAY TRONG hàng rào bảo-vệ R-4** (bắt `canPe`); R-4 HELD nhưng *lý-do bản invest đưa QUÁ THÔ*. **fidelity DỞ** (§6+§8 trống, `VERDICT=?`) — lead derive ≈12/6/3; bảng N-1→N-4 đối chiếu **từng claim bằng lệnh dán kèm**: N-1 tự phân loại 35 dòng ⇒ khớp 27/6/2 · N-2 khớp chính xác `:106/:125/:249` · **N-3 HELD về THỨ TỰ nhưng lệch con số hình-thức** (chỉ 3 hit `title="N.` vì Section 2 dùng template-literal đếm động, Section 4 là `<section>` trần) — 🔴 **chính bẫy này sau đó lead tự dẫm** (grep `'<Section title='` ra 0, suýt kết FAIL). ⇒ **Bài kép: lane dự báo đúng cái bẫy mà người viết bản sửa vẫn sa vào** — có thước đúng trong tay ≠ sẽ dùng thước đúng. Tag `[s171, 3-lane-doi-khang, dia-cuu-74070, cite-sai-khac-claim-sai, a6-sai-khoa-canPe, template-literal-dem-dong]`
- **[→ archive/2026-07.md §@S166-K5-curate — verbatim] S166 gate K4b · K4a · vá F-1 (digest):** mỏ-neo XUYÊN FILE · **tham-số-trang-trí** (đo AI ĐỌC từng param) · mỏ-neo tự-vô-hiệu ngay lúc land · ô canonical sai đo được bằng 1 curl · khuôn-nguồn 2 tầng ⇒ đo GIÁ-TRỊ KHỞI-TẠO · **cây phình giữa review** ⇒ re-đo `--stat` TRƯỚC verdict · HIGH-nằm-ở-git (`git status --porcelain -- src tests | grep '^??'`) · khoá-cache định-danh REQUEST không định-danh URL.
- **[→ archive/2026-07.md §@S167-K7-curate — verbatim ĐÃ PROBE moved-not-cut] S166 gate K5 cây-GĐ2-8-folder · K4c cụm-2 (digest):** bất-biến Σ do CẤU TRÚC · **phép-đo-rẻ-nhất nằm ở file RÁC của lane khác** · chân-lý-RỖNG phải khai là rỗng · tương-đương-TỪNG-VẾ > 'cùng tập' · tiền-lệ đo ở BASE không ở cây đã sửa · 'N/N OK' chết theo phiên khi FE 0 hạ-tầng-test · **flake chỉ lộ ở LƯỢT ĐẦU và `-v q` NUỐT assert** · probe RED bằng đổi TEST-INPUT chỉ khi tham số xuất hiện ĐÚNG 1 chỗ · `Total` là vân-tay lọc-SERVER chỉ khi `CountAsync` sau `Where` trước `Skip/Take`.
- **[→ archive/2026-07.md §@S167-K7-curate-2 — verbatim ĐÃ PROBE moved-not-cut] S167 gate K7 cầu KHKK→HĐ — PASS-WITH-FLAGS 10 (digest):** **1 con số đóng 2 câu hỏi** (639 = 622 baseline + 17 `[Fact]` ⇒ chứng CẢ 'chạy thật' LẪN '0 test cũ vỡ'). **Mỏ-neo tự-vô-hiệu** — comment trỏ `:2516` nhưng cây đã là `:2523` do chính diff đẩy xuống ⇒ phải đo **2 THẾ GIỚI (HEAD ⟂ cây)**. **Prod probe sửa con số của chính comment** (13/13 role → thật 12/13). **Răng phủ NỬA**: T11 assert 4 vế nhưng `await` tuần tự ⇒ ca ĐỒNG THỜI vẫn hở. **SHA-identical KHÔNG bảo chứng route-identical** ⇒ grep route CẢ 2 app. Tag `[s167, mot-so-dong-2-cau-hoi, moneo-tu-vo-hieu, rang-phu-nua]`
- **[→ archive/2026-07.md §@S168-curate — verbatim ĐÃ PROBE moved-not-cut] S168 gate GĐ3-D cắm cây vào Panel-3 ×3 trang — PASS-WITH-FLAGS 10, 0 blocker (digest):** **khuôn dùng-lại phải ĐO LẠI theo HOST**`max-h`/`sticky` hiệu-chỉnh cho host CŨ: cây cần 100vh158 mà Panel-3 chỉ có 100vh184 (InboxPage) ⇒ 2 thanh cuộn lồng; 2 trang kia thừa 5px/13px = khít đến mong manh. **Class chết ÂM THẦM khi đổi kiểu cha** (`self-start` cha `block` · `lg:sticky` con DUY NHẤT của chính scroll-container) — tsc+build KHÔNG bắt, chỉ đọc CSS-chain mới thấy. `aside` lồng `aside``aria-label` vẫn giữ `role=complementary` ⇒ 2 landmark lồng. Prod-probe biến lo-ngại thành số: `canPe` 13/13 True ⇒ ca `!canPe` chưa xảy ra (control-âm `Permissions`/`Users` False 12/13). `{!selectedId && <X/>}` = unmount ⇒ mất state thuần (`search`) trong khi `localStorage` sống ⇒ trade-off spec khai THIẾU. Thước hỏng: python Windows đọc JSON phải khai `encoding` · `while read` bỏ dòng CUỐI khi thiếu newline · `join` text-mode đẻ CRLF vào tên file. Tag `[s168, khuon-do-lai-theo-host, class-chet-am-tham, unmount-mat-state]`
- **[→ archive/2026-07.md — verbatim @S168 K8] S168 gate K8-blocker Lines-editor KHKK — PASS-WITH-FLAGS 8, 0 blocker (digest):** 642 = 639 baseline + 3 Fact ⇒ **1 con số đóng 2 câu hỏi** · **quy-ước-của-chính-file là thước rẻ nhất** (mọi changelog sub-entity điền `EntityId`, chỗ mới là chỗ DUY NHẤT trống ⇒ MAJOR bằng 1 grep) · **`<select>` controlled NUỐT giá-trị đã lưu** khi option vắng (đang tải · query lỗi không toast · entry `IsActive=false` sau gán) ⇒ regression hiển thị do ĐỔI KIỂU Ô, tsc+build+test 0 bắt · **bình-luận tự-hẹn mắt-xích tương lai** chưa trả ⇒ nhưng ĐO khả-chạm trước khi hô (UNIQUE tầng trên khoá ⇒ hạ MINOR) · khe RỖNG khai rỗng ×2 · test phủ NỬA vế `if` (`!IsActive` chưa chạy lần nào) · thước hỏng `$?` sau `| tail` ⇒ đo lại `tsc -b --force`.
- **S170 GATE Fidelity /sleep-recovery-memory-l2 (16 gist-draft) — PASS-WITH-FIXES (digest):** **tên-cờ-bịa sống 4 hiện-vật** — grep 0-hit CẦN dụng-cụ THỨ HAI (`git log --all -S` + control-dương) mới nâng 'nghi'→'chốt: chưa từng tồn tại'; 3/4 là drift của cờ THẬT, 1/4 (`AllowDelegate`) 0 đối-ứng ⇒ **đừng gộp 2 lớp**. 🔴 **Nhãn phủ TÊN mà không phủ CON-SỐ** — claim mang tải là 'proven 4×' (kích-hoạt luật ≥2× promote), và đơn-thuốc 'giữ 4 lần, bỏ tên cờ' = **giữ khẳng-định + vứt CHỨNG-NHÂN** ⇒ bất-khả-bác (Goodhart). **Census tự-xưng đủ** ('4 LỖ') thiếu 4 lỗ nữa gồm 1 lỗ +23 — số-đóng-vai-đã-phủ-hết (meta-count blind-spot), dù draft TỰ chép đủ số để trừ ra. **Chính-sách số BẤT-ĐỐI-XỨNG trong cùng đợt**: file A bị buộc 'KHÔNG tự sửa số', file B lén sửa 7→6 field không khai ⇒ đọc-sau không biết số nào là chữ nguồn. **`pointer-style: substring` phải CHẠY THỬ**: 1/10 con-trỏ CHẾT do lệch hoa-thường (`PRIORITY` vs `priority`). **Lưới token máy-append in ĐẦU-DÒNG không in lân-cận-token** ⇒ mega-line cho trích-dẫn LẠC HẲN (gán FAIL cho Run PASS) — tái-lập ở 2 file độc-lập. Thước tốt giữ lại: control-ÂM cạnh control-dương · claim liên-file phải HAI BỜ CÙNG KHAI · tag-chain 14/14 đo bằng grep -F từng chuỗi. Tag `[s170, nhan-phu-ten-khong-phu-so, census-tu-xung-du, con-tro-chet-hoa-thuong, luoi-dau-dong]`
- **[→ archive/2026-07.md §@S167-K7-curate-2 — verbatim] S167 gate K6 admin thu-gọn — PASS-WITH-FLAGS 5 (digest):** **cây menu PROD SỐNG là thước, seed chỉ là bản vẽ** (`curl /api/menus/me` + control-âm bỏ 1 key). **`filterForAdmin` mới là bước MỘT** — còn `resolvePath→null` drop im lặng (#50) + group rỗng-hoá render như LEAF. **typo-noop**: key ẩn sai chính tả = `Set.has` false, module vẫn hiện, tsc vẫn xanh ⇒ assert TỪNG key TỒN TẠI trong cây prod. MAJOR: CẤM số-đếm trong comment.
- **[→ archive/2026-07.md §@S166-curate — verbatim] S164/S165 K3 · S164 K1 · S162 cây-4-folder · S161-W2 (digest):** tham-số-chết-vì-thiếu-tầng-UI (đo TẦNG-CUỐI ai GỬI) · sweep 2-cờ bất-đối-xứng · flake ⇒ 'N/0 tươi' phải khai SỐ LƯỢT · **ghost-policy** (grep policy, đừng suy từ 'key đã vào All') · **#82 ngược chiều** (FE OR nhiều key LỎNG HƠN policy khớp-CHÍNH-XÁC-1-key ⇒ tự chuốc 403) · hợp-đồng FE↔BE VỠ 6 điểm mà tsc+build+574-test XANH ⇒ so ROUTE+FIELD trên ĐĨA.
- **[→ archive/2026-07.md — ĐÃ RE-PROBE @S168: nội-dung CÓ trong archive; 2 nhãn `S161-W1`/`S152-D2` 0-hit nên GIỮ ở đây] S159-đợt5 · S161-W1 · S155-đợt2 · S145-4lane · S143 · S139 · S134b · S133 · S146/S147/S152-D2 (digest gộp):** chú-thích-mang-SỐ phải chạy phép đếm · cookie-cutter soi CẢ phần bản gốc đã CHẶN · `tsc`+`noUnusedLocals` > grep cho claim 'đã cắt' · comment 'bên kia lo' = ĐI ĐỌC BÊN KIA · grep bằng TOKEN-SONG-SINH · `hợp-đồng-đứt-2-bờ` · đổi-chiều-assert ≠ nới-assert · `bằng-chứng-tự-huỷ-sau-squash` · 'mọi nhánh set X' phải grep assignment-qua-BIẾN (#81) · `ExecuteDelete` ngoài transaction = mất dữ liệu · 3 THƯỚC-HỎNG (md5 CRLF · `grep -c` citation-trap · `grep -iF` MSYS 0-hit im lặng).
> **Persistent diary cross-session.** Auto-injected first ~200 lines at spawn (L1 HOT).
> Update BEFORE every stop. Tiered Memory v1: L1 HOT cap ~17KB (hook 24.4KB read-limit) · L2 `archive/` on-demand · L3 RAG `search_memory` just-in-time. Keep entry ≤ 1.5K chars (gotcha #53).
> Full verbatim history pre-S40 → git `d2f52ba` + `archive/2026-05-q1..q2.md`; S51→S76 detail → `archive/2026-06.md` (S69/S70/S71/**S80** curate). Archive map: `archive/_INDEX.md` + per-period `.gist.md`.
- **[→ archive/2026-07.md @S161-curate] S160 (07-29) CHỐT-CUỐI 13-fix:** fix áp NỬA spec = dư-lượng (soi CẢ FILE khi nhận 'đã fix') · anchor-list là artifact RIÊNG phải sync · verify NGƯỢC premise · owner để-mở ⇒ finding MOOT-đúng.
## 📁 Area memory (L2 on-demand — Read khi review vùng tương ứng)
- [S62 PE budget soft-warning](project_s62_pe_budget_soft_warning.md) — hard-block→soft-warning, submit-guard intact (additive-only).
- [Wire/mirror claim verification anchors](feedback_wire_claim_verification_anchors.md) — sha256 twin-file · `git diff -U0` isolate true-adds · `allowNegative` bleed check · guard-still-intact grep.
- **[→ archive @S161-curate] S160 review SPEC-BỘ KHKK:** review SPEC ≠ review CODE · seeder-grant kiểu insert = NO-OP 403 im lặng ⇒ acceptance đo CỜ không đếm ROW · acceptance 'PASS SẴN' = 0-bit · choke-point 'DUY NHẤT' sai vì gán QUA BIẾN (#81).
- **S89 trio** ([sectionB](project_s89_pe_sectionb_review.md) · [endsBeforeCeo](project_s89_pe_endsbeforeceo_plan_review.md) · [finalize-note](project_s89_finalize_note_plan_review.md)) — authz-lens ≠ concurrency-lens; FE 4 render-site, plan sót 2.
- **S101 H18/H19 WF2 + LANE-C:** content-hash ≠ commit-SHA (hex strip/no-strip) · exact-token sweep miss paraphrase → widen concept-phrase. → `archive/2026-07.md`.
- [S103 H20 + crystallized-backfill](project_s103_h20_crystallized_backfill_review.md) — cảnh báo multi-axis phải nằm trong OUTPUT của script, không chỉ trong doc.
- [S111 PE sign-off design (schema/history)](project_pe_signoff_history_schema_review.md) — opinion-history append-only; REJECT version-col (phá UNIQUE + UPSERT).
- **PE per-hạng-mục ×5** ([1](project_pe_multiwinner_perhangmuc_review.md) · [2](project_s114_pe_multi_ncc_perhangmuc_financial_review.md) · [3](project_pe_multi_ncc_perhangmuc_specreview.md) · [4](project_s114_multi_ncc_perhangmuc_impl_review.md) · [5](project_pe_negative_quote_correctness_review.md)) — derived source-of-truth: re-derive MỌI write-path KỂ CẢ Delete; grep field-NGUỒN không chỉ field-đọc.
- [S113 Supplier import v2](project_s113_supplier_import_v2_review.md) — "filter added" ≠ "drafts hidden": grep-all-consumer + create write-path.
- [S118 Procurement master-access seeder](project_s118_procurement_master_access_review.md) — menu-flag grant ≠ API capability; `[Authorize]` trần = mở cho mọi user.
- [S123 governance 4-change](project_s123_governance_4change_review.md) — citation-trap gen-2: vá 1 CLASS phải grep MỌI matcher cùng-lớp TRONG diff.
- [S147 Project whitespace-dupe merge](project_project_dupe_merge_verify.md) — "FK Projects" trong COMMENT ≠ FK vật lý; INNER-join + filter = biến mất im lặng.
---
## 🎯 Role baseline
Adversarial pre-commit reviewer SOLUTION_ERP. Read-only verify + live curl prod UAT (`*.solutions.com.vn`). Tools: Read, Grep, Glob, Bash (curl + git diff + sqlcmd read) + 5 RAG MCP. Skills: `dependency-audit-erp` + `contract-workflow` + `permission-matrix`. Output: PASS/FAIL + concrete issues file:line. NEVER write code.
---
## 🚨 Recurring bug patterns (catch priority)
- **#44 Silent 403 class-level Authorize quá strict** — Drafter dropdown empty silent (TanStack catch silent → UI empty). Grep `\[Authorize\(Policy=.*\)\]` class-level + curl non-admin expect 200. Fix: class-level `[Authorize]` only (any authenticated); POST/PUT/DELETE giữ `[Authorize(Policy="X.Create")]`.
- **#43 Step.Order ≠ index 0-based** — `Where(s=>s.Order==i)` wrong row. Fix: EF query → in-memory `OrderBy(Order).ToList()` → index.
- **#42 Dual schema V1/V2 — Service phải branch** — `if (entity.ApprovalWorkflowId is Guid awId) ApproveV2Async else V1Legacy`.
- **Wire BE claim** — grep diff `// Mock`/`alert(`/no POST-PUT-DELETE call + live curl expect 2XX. Severity CRITICAL block.
- **#70 FE absolute-set stale-echo race** — N field cùng-cột share 1 mutation + echo sibling từ server-snapshot + `invalidate()` không await ⇒ lưu 2 ô liên-tiếp đè mất. Window mở SAU `isPending=false`, KHÔNG lúc in-flight. Catch: đếm field-cùng-cột share mutation + check invalidate awaited.
- **#71 enum proxy-predicate pollution** — thêm enum value vào entity dùng-chung → UI/guard phân-loại theo PROXY-predicate (`supplierId===null`) thay vì enum tường minh → value mới lẫn nhầm phân-loại + false-pass guard. Catch: grep mọi field-proxy predicate, loại value mới tường minh; build-verify TỪNG app.
- **Cross-module security mirror (S29 Smart Friend)** — mirror entity/Command cross-module (PE→Contract→Budget V2) hay focus data-shape mà MISS security guard. Luật: validate `aw.ApplicableType == ExpectedType` ON Create TRƯỚC khi instantiate (khuôn `PurchaseEvaluationFeatures.cs:62-77`) — FK Restrict chỉ check Id-tồn-tại, KHÔNG check type ⇒ Drafter forge `approvalWorkflowId` module khác = pin sai-scope. Re-verify `IsActive`+`IsUserSelectable` server-side. MAJOR.
- **#17 EF migration 3-file** — `git diff --name-only | grep Migrations/` expect 3 (target + Designer + Snapshot).
---
## 📋 6-category checklist (EVERY review)
- **Cat 1 Wire BE/feature claim:** grep mock markers diff + `await api\.(post|put|delete|patch)\(` + live curl POST/PUT/DELETE if deploy claim + status matrix.
- **Cat 2 Schema integrity:** 3-file rule Mig + column types vs entity def. Reference `docs/gotchas.md` (71 active).
- **Cat 3 Security:** `[Authorize]` class-level ALL new controllers + per-action policy admin-scoped (gotcha #44) + FE PermissionGuard + menuKeys.ts mirror BE MenuKeys.cs + FluentValidation + EF parameterized.
- **Cat 4 Code quality:** `dotnet build SolutionErp.slnx` 0 err + `npm run build` × 2 app (TS6 strict) + tests baseline **354 PASS** (Phase 9 UAT exception OK) + no `--no-verify` + anti-fiddle (scope drift >20% LOC = FAIL) + mirror 2 FE app §3.9.
- **Cat 5 Test coverage:** new helper → xUnit · new endpoint → integration · bug → regression test-before-fix. Phase 9 UAT test-after default OK (`feedback_uat_skip_verify`). Baseline 354.
- **Cat 6 Writing-quality (Harness-7, S64):** outward text (verdict gửi anh / report) = tiếng Việt câu hoàn-chỉnh đủ dấu đúng ngữ-pháp; describe issue + acceptance criteria, NOT code edits. Escalate disagreement explicit.
---
## ⚠️ Anti-patterns + 🛡️ Smart Friend guard
1. ❌ Recommend code edits (only describe issue+criteria) · 2. ❌ Skip live curl if deploy claim · 3. ❌ Accept "wire" without grep proof · 4. ❌ Defer to em main authority (escalate explicit) · 5. ❌ Skip MEMORY · 6. ❌ **Lower bar match em main** (Smart Friend Cognition anti-pattern).
**Smart Friend (Cognition):** NEVER lower bar. Em main code fine → PASS. Em main issues → FAIL with specifics regardless social pressure. "Quality ceiling set by primary, not escalation." Value = raise quality through catch.
---
## 🧠 SOLUTION_ERP review essentials (S80 verified — re-ground từ docs/STATUS.md canonical)
- **Tests · gotchas · migration · endpoint · bảng = SỐ CANONICAL ở `docs/STATUS.md`** (B1 derived-trỏ-canonical — KHÔNG chép số vào sổ này, chép là stale sau 1 phiên; mốc @S161 để nhận diện độ trôi: test 566 · gotcha 83 · Mig 69 · 96 bảng). Test phải TĂNG khi thêm feature (§7); Phase 9 UAT exception (`feedback_uat_skip_verify`).
- **Identity password ≥12 chars** (reject 11-char). Test creds: admin `admin@solutions.com.vn/Admin@123456` (full) · UAT `nv.test@solutions.com.vn/TestUser@123456` (Drafter CCM).
- **Prod:** api/admin/eoffice.solutions.com.vn. Bundle live admin `CsJetgZH` / user `BVS0ApIm` (Run #330). **Pin:** MediatR `12.4.1` (flag `Version="14`) · Swashbuckle `6.9.0` · Node CI `20.x`.
- **Conventions:** `docs/rules.md` (§1.1 outward writing, §3.9 mirror 2 FE, §5.2 commit, §6.5 docs narrative, §7 test timing, §2.8 pin).
---
## 📅 Recent activity (compressed — full verbatim → `archive/2026-06.md` + `archive/2026-07.md` via `archive/_INDEX.md`)
- **[→ archive @S126/@S134] S123·S124·S125·S129·S131 (digest):** follow-up phải GIỮ con-số source · re-derive từ raw (fencepost) · writer-only = NỬA-VÁ · do-token trap ⇒ re-Read full + sibling-test 2-CHIỀU · 🔴 ghi diary TRƯỚC return + vá-1-lớp phải grep MỌI matcher cùng-lớp.
- **Digest S93→S117 + June-2026 (verbatim → `archive/2026-07.md`):** code-gate re-derived denom · default-flip byte-mirror SHA ×2 · persist-claim cần reader-side + tracked + 0-drift · outward-claim 'đã sửa X' phải cat X trước gate · claim-về-code grep lại kể cả reword · verify EACH regex-alt by-hand · merge-distill đẻ false-specificity ⇒ QUALITY gate SAU presence · sha = self-declared NOT recompute · TRACKED = check-ignore ≠ ls-files · menu-hide ≠ API-lock.
- **S92 PROD-security hide 5 menu-groups admin-only — PASS (1 note):** → [project_s92_admin_only_modules_revoke.md](project_s92_admin_only_modules_revoke.md).
- **[→ archive/2026-07.md @S128/@S134] S112·S126·S127·S128 (digest):** derive guard từ ENDPOINT authz, self-flip ≠ external-accept · AGGREGATE cumulative KHÔNG vào outward artifact · direction-of-error quyết mức lỗi outward + brute-force sha-variant TRƯỚC phán tamper · hedge broadcast bằng MỞ config THẬT.
---
## 🔄 Curate trigger
- ⚠️ **@S168-K8 đo lại: 18.3KB — VƯỢT cap 17.1KB ⇒ spawn sau curate NGAY** (đã append verbatim K8 vào `archive/2026-07.md`, L1 chỉ giữ digest).
-**@S168 curate: 22.2KB → <17.1KB (ĐO, không đoán).** Trình tự S102 giữ nguyên: append archive TRƯỚC probe moved-not-cut + control-âm mới cắt. 🔴 **Bài mới:** (a) tôi ghi '~20.6KB' bằng ƯỚC LƯỢNG trong khi `wc -c` cho 22.2KB **số trong sổ phải là số ĐO**, baseline '19.0KB' thừa kế từ pass trước cũng đã stale; (b) probe moved-not-cut bằng token lấy từ DIGEST cho **0-hit GIẢ** (digest paraphrase, bản gốc dùng chữ khác) 0-hit phải **thử token thứ 2 từ thân bài** trước khi kết luận cut-not-moved suýt giữ lại 938B ích; (c) **script sinh chữ lại đẻ chữ hỏng câm** (token `join` trong chuỗi làm entry vỡ đôi dòng) đúng bài S166-K5, byte-count KHÔNG bắt, chỉ ĐỌC LẠI mới thấy.
- Hook-cap **>17.1KB** (24.4KB read-limit, S109) → archive recent → L2 `archive/<period>.md` (append additive) + `_INDEX.md` pointer. Stale >3mo → remove.
- **Prev curates:** S166-K5 (probe 3/3) · S162 (2/2) · S145 · S140 · S134 · S128 · **S102 recovery: cut-not-moved ×5 `f229b07` ⇒ mọi L1-shrink kèm '→archive' BẮT BUỘC grep moved-not-cut TRƯỚC khi trust** · S116·S113·S109·S80·S71·S70·S40.
## S152 (07-25) — R1 ranh NEVER (on-behalf lead)
- **NEVER Edit/Write code-tree · NEVER commit · NEVER push** — vai = verdict-only; sửa là việc em-main/implementer. Khai thật 2 nấc: ranh commit/push/code-tree **chưa từng vỡ**; Write/Edit runtime CÓ cấp và dùng hợp lệ cho sub-file run-folder + diary-self (AS-10). "NEVER" áp cho ĐÍCH (code/commit/push), không phải cho tool-tồn-tại; containment thật = git-diff lead. Tag `[s152, r1-retention, never-target-scoped]`
- **[→ archive/2026-07.md @S165-curate] S159 đợt-1 (07-29) diff pipeline — 7 FLAG:** rút TOÀN BỘ chuỗi hiển-thị MỚI từ diff rồi soi từng chuỗi = phép đo 100%-tiếng-Việt · 2 queryKey cùng resource = 2 ảnh-chụp khác thời-điểm · a11y nút TRÙNG tên đọc-được · bác-claim cũng phải có chứng.
## S176 (08-06) — SETUP-REVIEW đội STYLE 3 vai (engine `/fable-real`, run `wf_264fb5c2-0db`) — verdict `SỬA-6`
- **Chấm THIẾT-KẾ một đội sub-agent, không phải diff code** — trục mới của vai. Vật: `runs/2026-08-06-S176-doi-style-3-vai/sub-reviewer-0.md` (15.798 B, full-detail).
- 🔴 **Bài đắt nhất — THƯỚC DISPATCH MÙ WORKING-TREE:** đội gate pre-commit mà thước là `git diff origin/main...HEAD` (ba-chấm) ⇒ lúc review lệnh trả **RỖNG** ⇒ dispatch kết "diff không chạm ⇒ không gọi" ⇒ **0 con spawn, 0 SKIP-CO-KHAI để lộ** ⇒ đội **chết câm** đúng use-case chính. Lớp `guard-chặn-không-đường-ghi` / `dry-run bắt lời-hứa-chưa-land`. Sửa: `git diff origin/main` (2-chấm) `git status --porcelain` lọc `??`.
- **Thước TREE tự lành ca REVERT** (bằng chứng revert thật `3f339c0`): revert xong code không còn trong tree ⇒ không thành chuẩn. Lo-nghi "revert phá thước" = **lo hão** — vì thước là tree, KHÔNG phải history. Ranh này đáng nhớ: đo TREE ≠ đo HISTORY.
- **Miễn-trừ chỉ-con-trỏ = dấu-cao-su:** 3 nguồn bằng-chứng (commit-message · WAL · prompt) thì 2 do **chính lead** viết — đúng người vai sinh ra để kèm. Đòi **TRÍCH NGUYÊN VĂN ≤1 dòng** thay vì chỉ con-trỏ ⇒ khép vòng bằng **owner-visibility** (owner đọc report tự bác câu bịa), không cần đẻ thêm vai.
- **Thách-CLEAN nhánh DAT bẻ được** nếu chỉ đòi "nêu 1 khối đã khớp" mà KHÔNG bắt neo `file:line`. Khuôn `db` (kèm số đếm 3-file — con số sai được) mạnh hơn 2 con kia. Luật: **cặp neo `file:line ⇄ file:line` + 1 chi-tiết khớp cụ-thể**, thiếu neo = coi như CHƯA SOI.
- **Vắng-mặt trông giống ổn (tái phát):** 3 vai mới **thiếu dir `agent-memory/<vai>/`**`measure-agent-memory.ps1` enumerate theo DIR ⇒ 3 vai **vô hình câm** trong đo/budget. Lead tự đo lại: 3/3 THIẾU — CONFIRMED.
- **3/5 lo wiring của lead là LO HÃO** (engine đo từng đường): `spawn-model-audit.ps1` · `governance-detectors.ps1` · `mfe-eval.ps1` đều enumerate **ĐỘNG**, không hardcode ⇒ tự nhận vai mới. Bài: **đừng giả-định script hardcode — mở ra đo.**
- **Chép-luật-vào-persona vi phạm chính B1 vừa viết trong CÙNG file** (`db:32/34-35/61` vs `db:71` cấm chép; `fe:4` chép digits "React 19 + Vite 8" — class ĐÃ drift thật: root `CLAUDE.md` ghi React **18** vs `package.json` ^19.2.5). Bài: viết luật cấm-chép xong phải **grep chính file mình** xem có chép không.
- Tag `[s176, setup-review, thuoc-mu-working-tree, do-tree-khong-do-history, mien-tru-can-trich-nguyen-van, vang-mat-giong-on]`