30 KiB
cicd-monitor/2026-05-runs — gist
distill-gen: 1 source-verbatim: .claude/agent-memory/cicd-monitor/archive/2026-05-runs.md (6 tóm-tắt + 20 Run + 8 key-pattern → 10 cụm) pointer-style: substring
TỔNG-HỢP (3-5 ý)
- Chuỗi per-NV lookup discrimination (Plan K→P, Mig 29/30/31): bug
FirstOrDefaultkhông lọc actor sống 2-3 ngày prod, "em main + Reviewer + Implementer all missed across 3 plan", checklist phình 6→8→9→10 điểm — với schema OR-of-N, mọiFirstOrDefault(Order==)là điểm mù (quét TOÀN kho, không chỉ handler lộ bệnh); record body Controller phải soi-gương param với Command (thiếu field ⇒ ASP.NETdefaultim-lặng). - Saga Discovery #3 chốt sau 5 lần quan-sát: Gitea xét
paths-ignoretrên TRỌN push-range — muốn loại một biến phải tìm ca VẮNG biến mà hiện-tượng vẫn còn (#202 then-chốt); kết-luận là "lỗi" nhưng "Anomaly is BENEFICIAL". - Chuỗi audit-trail S25 (#215 FAIL → #221): phát hiện "field X không set ở N chỗ" thì vá cả N chỗ một lượt (9 site UserName); dữ-liệu cũ hỏng cứu ở FE bằng
userMaptừ dữ-liệu nhúng sẵn; Run #217a734bf2= nguồn duy nhất Discovery #5 + pattern "capture pre-call mutation state". - Plan T tắt DemoSeed: cờ chống re-seed chỉ tin sau restart THẬT (
Restart-WebAppPool+ sqlcmd đếm 0);appsettings.Production.jsonbị.gitignore⇒ default phải đặt ởappsettings.json; chính cờ này về sau nuốt seed hạ-tầng Plan B (gotcha #51 — xem gist q2). - Lệnh đo sai trả về IM-LẶNG (7 phát-hiện công-cụ:
/actions/tasks≠runs ·updated_attrễ ~2 phút · 429 ~5 req/phút → cache token · sqlcmd 4-backslash Discovery #5 · enum cần số Discovery #4 · 503 recycle lành · route/api/auth/login+ fieldaccessToken) — mỗi phép đo cần ca đối-chứng dương. MEMORY tự phình 35→72KB qua 8 nấc cảnh-báo leo thang không tự dừng ⇒ cần cổng ngoài. 🔐 dòng 48 verbatim: password DB prod ĐÃ redact bởi lead — ROTATE REQUIRED.
Entries
Ghi-chú hợp-nhất nội-file: phần (a) tóm-tắt ∩ phần (b) đầy-đủ của verbatim chồng 4 Run (#202 · #203 · #210 · #219) — cụm dưới đây chọn bản DÀY; riêng #215 + #217 CHỈ có ở phần (a) — ĐÃ GIỮ khi hợp-nhất (KHÔNG mất Run #217).
[cao] D1 — Chuỗi per-NV lookup discrimination (Plan K → P), sinh checklist 10 điểm
- VIỆC: wire cờ opt-in per-NV (Allow* theo từng slot Approver) xuyên Mig 29/30/31, rồi vá 5 lượt liên-tiếp khi lộ ra thiếu điểm nối.
- KẾT-LUẬN: #194
098baa6PARTIAL — schema + FE checkbox thứ 7 đã ship nhưngAwLevelDto(ApprovalWorkflowV2AdminFeatures.cs:23-38) thiếu hẳn paramAllowApproverSkipToFinal(chỉ tồn-tại trong comment dòng 60) +ToDto:156-158thiếu ⇒ checkbox đọc/ghi vào hư-vô. #1950062fcbvá 15 LOC ⇒ 13 key round-trip PASS, đúc checklist 8 điểm. #201fb3c22c(Plan N) váPurchaseEvaluationFeatures.cs:765thêm&& l.ApproverUserId == currentUser.UserId+ fallback admin ⇒ điểm 9. #202a1c8386(Plan O) quét ra 4 site cùng khuôn (...WorkflowService.cs:204+:258-260,...DetailFeatures.cs:75-76,...Features.cs:314-315) + 3 test hồi-quy (111/111). #2031727bd5(Plan P) vá ControllerTransitionPeBodytừ 3 → 7 param ⇒ điểm 10. - BÀI-HỌC: với schema OR-of-N (nhiều NV cùng một Cấp), mọi
FirstOrDefault(... Order == ...)là điểm mù: phải quét TOÀN kho (grep -n "FirstOrDefault.*Order.*==") chứ không chỉ sửa handler lộ bệnh. Và record body của Controller phải soi-gương số param với Command — thiếu field thì ASP.NET không báo lỗi, chỉ lặng-lẽdefault. - BẤT-NGỜ: bug sống trên prod 2-3 ngày và 3 lượt refactor liên-tiếp (Mig 29/30/31) đều trượt — verbatim tự khai "em main + Reviewer + Implementer all missed across 3 plan"; đồng-thời checklist phình 6 → 8 → 9 → 10 điểm, tức mỗi lần "đã đủ" đều sai. → substring:"098baa6"
[cao] D2 — Saga Discovery #3 (paths-ignore xét trọn push-range)
(trùng liên-file "Verify S22 chốt": bản dày = file này; cicd-monitor--2026-05-q3 B2 giữ bản mỏng — đóng-kín per-file, không xoá bên nào)
- VIỆC: truy vì sao commit docs-only vẫn kích CI (ngược gotcha #41), qua 5 lần quan-sát.
- KẾT-LUẬN: giả-thuyết đầu (Discovery #2, Run #188): "
.claude/agent-memory/**không nằm trongpaths-ignorenên kích CI" → BỊ BÁC ở S22-chốt vì**/*.mdkhớp mọi độ sâu (cc8a7d3SKIP đúng). Chốt sau 3 lần củng-cố (#200f4055a1, #201fb3c22c, #202a1c8386— lần 3 0 file agent-memory nên loại hẳn biến này): Gitea xét paths-ignore trên TRỌN push-range, chỉ cần 1 commit trung-gian có file không-bị-ignore là cả range chạy. #210 mixed-diff nên không tính là bằng-chứng. - BÀI-HỌC: muốn loại một biến thì phải tìm ca VẮNG biến đó mà hiện-tượng vẫn còn (#202 là ca then-chốt) — thêm ca có-biến chỉ củng-cố giả-thuyết sai. Ghi rõ ca nào không tính là bằng-chứng (#210) cũng quan-trọng ngang ca tính.
- BẤT-NGỜ: kết-luận cuối là "lỗi" nhưng verbatim đánh giá "Anomaly is BENEFICIAL" — CI chạy dư lại cứu được gate verify trên commit docs; và gotcha #47 tuy bị bác vẫn giữ giá-trị phòng-ngừa cho file non-
.mdtương-lai. → substring:"f4055a1"
[cao] D3 — Chuỗi audit-trail S25 (Plan AB → AF): 5 khuôn phục-hồi lịch-sử (trùng liên-file #215: bản dày hơn ở cicd-monitor--2026-05-q3 B1; #215+#217 trong verbatim file này chỉ có ở phần tóm-tắt (a) — Run #217 = nguồn duy nhất Discovery #5 + pattern "capture pre-call mutation state", ĐÃ GIỮ)
- VIỆC: làm "Lịch sử duyệt" hiển-thị đúng + cứu dữ-liệu lịch-sử đã ghi thiếu.
- KẾT-LUẬN: #215 FAIL (tie-break, xem q3) → #217
a734bf2(AC) thêm Approval-row nhánh RejectService:75-103+ prefix[Duyệt vượt cấp tới Cấp cuối]:472, xác-minh 6/6 approval có đủ 8 key → #21825837b6(AC2) FE dựng synthetic Reject row từ ChangelogentityType=5(20 entry, 8 Workflow-entry, khớp keyword "Trả về") → #2190aaf2df(AD) bỏ badge from/to +extractNextTargetHint()parse\[Bước (\d+) — Cấp (\d+)\]→ #2209ea62be(AE) vá 9 siteUserName = currentUser.FullName ?? currentUser.Email(4 Features + 5 DetailFeatures) → #221506cada(AF) FEuserMapuseMemo dựng từ 5 nguồn nhúng sẵn (drafter/approvals/levelOpinions/departmentOpinions/approvalFlow.steps), 3 nấc: tinentry.userName→ tra map → "Hệ thống". Cumulative 7 commit, 1 catch + 6 PASS, 0 regression. - BÀI-HỌC: khi phát-hiện "field X không set ở N chỗ giống nhau", vá cả N chỗ một lượt thay vì chỗ báo lỗi (AE: 1 lộ + 8 phòng-xa). Dữ-liệu cũ đã hỏng thì cứu ở FE bằng dữ-liệu đã nhúng sẵn trong bundle — không cần đổi hợp-đồng API, né luôn ràng-buộc
/api/userschỉ-admin. - BẤT-NGỜ: bằng-chứng chốt Bug 1 là một dòng dữ-liệu cũ còn sót: entry Budget Adjust
02:31:39entityType=1cóuserName=""— tức prod tự lưu giữ vật-chứng tiền-sửa để đối-chứng sau deploy; và AD bỏ bớt thông-tin (badge from/to) lại làm UI đúng hơn vì phần lớn làChoDuyet→ChoDuyettự-lặp. → substring:"a734bf2"
[cao] D5 — Plan T tắt DemoSeed + chứng bằng restart THẬT
- VIỆC: chặn seed demo tự mọc lại trên prod (#207
0b97840, #2087b7b28f). - KẾT-LUẬN: bọc 5 method demo trong
if (!demoSeedDisabled)(V1 workflow ×2, demo Contract, demo PE, sample AW V2); GIỮ 8 nhóm seed hạ-tầng (Roles/Admin/30 user UAT/master/template/catalog/backfill). T5 xoá 4 PE + 1 V2 + 2 V1 + cascade; T6 épRestart-WebAppPool SolutionErp-Apirồi sqlcmd: PE=0, V2=0, V1=0, master còn nguyên (Users 33 · Suppliers 19 · Projects 9 · Contracts 7). Tổng R+S+T ≈ 720 dòng bị xoá, cờ tồn-tại vĩnh-viễn. - BÀI-HỌC: cờ chống re-seed chỉ được tin sau khi khởi-động lại thật rồi đếm lại — không tin vào việc đọc code. Và vì
appsettings.Production.jsonbị.gitignore, giá-trị mặc-định phải đặt ởappsettings.json(thứ đi qua git) mới tới được prod. - BẤT-NGỜ: chính cái cờ chứng-minh-tốt này về sau nuốt luôn seed hạ-tầng của Plan B (Run #231/#232, gotcha #51) — biện-pháp đúng ở lớp này thành bẫy ở lớp khác. → substring:"Restart-WebAppPool"
[cao] D6 — 7 phát-hiện về CÔNG-CỤ ĐO (dễ mất nhất khi nén)
- VIỆC: gom các bài học về chính phép đo, rải rác trong 6 Run.
- KẾT-LUẬN: (1) API liệt-kê Run của Gitea là
/api/v1/repos/.../actions/**tasks**,/actions/runstrả 404; đọc không cần auth. (2)updated_attrong bảng task trễ ~2 phút — phải đối-chiếuLastWriteTimecủa.dll/.htmltrên VPS. (3) đăng-nhập ~5 request/phút là 429 ⇒ cache token ra%TEMP%\*_token.txt, 2 login + 8 lệnh dùng lại (Run #188 dính 429, S22-chốt hết dính). (4) Discovery #5: sqlcmd Windows-auth qua ssh cần escape 4 dấu\\\\SQLEXPRESS— 2 dấu ra rỗng KHÔNG báo lỗi. (5) Discovery #4: ASP.NET Core 10 record + enum đòi số, không cóJsonStringEnumConverter(grepProgram.cs= 0 hit) ⇒ payload mẫu"Drafter"trong brief là sai, fail 400. (6) 503 giữa lúc IIS recycle (~5-15s) là bình-thường, tự khỏi. (7) route thật là/api/auth/login(không/api/v1/...), field token làaccessToken(khôngtoken);/api/me+/api/menu-keys404 vì không tồn-tại, không phải regression. - BÀI-HỌC: lệnh đo sai trả về IM-LẶNG (2-backslash ra rỗng; enum string ra 400; endpoint sai ra 404) — mỗi phép đo phải có ca đối-chứng dương, và phải phân-biệt "0 kết-quả" với "đo hỏng".
- BẤT-NGỜ: brief do người ra lệnh viết lại chính là nguồn sai (payload
"Drafter") — và verbatim ghi thẳng "brief example payload was misleading", không đổ cho hệ-thống. → substring:"JsonStringEnumConverter"
[cao] D7 — MEMORY phình 35→72KB: 8 lần cảnh-báo leo thang mà không ai dừng
- VIỆC: vai tự theo-dõi kích-thước diary của chính mình sau mỗi entry.
- KẾT-LUẬN: chuỗi tự khai: ~35KB ("approaching") → ~40 → ~43 ("over 25KB trigger, under 50KB hard") → ~50 ("at hard threshold") → ~58 ("REQUIRED ARCHIVE ... BEFORE next entry") → ~60 ("MANDATORY") → ~62 ("DEDICATED CURATION SESSION PRIORITY NEXT") → ~66→69 ("priority MAX") → ~72 ("PRIORITY MAX REINFORCED"). Chốt chỉ xảy ra khi có phiên curate riêng (chính file archive này), kéo về mục-tiêu ~25-30KB.
- BÀI-HỌC: cảnh-báo do chính kẻ đang phình phát ra thì không tự dừng được — cần cổng ngoài (ngưỡng cứng chặn ghi) hoặc việc riêng có chủ; và ngưỡng "mềm 25KB / cứng 50KB" bị vượt gần 3 lần vẫn chỉ sinh thêm chữ in-đậm.
- BẤT-NGỜ: mức độ khẩn-cấp trong câu chữ leo thang 8 nấc (approaching → REQUIRED → MANDATORY → PRIORITY MAX → REINFORCED) — bản thân nó là dữ-liệu: leo-thang ngôn-từ không thay cho cơ-chế. → substring:"PRIORITY MAX REINFORCED"
[cao] D10 — Tự khai tác-dụng-phụ và giới-hạn phép đo
- VIỆC: ghi lại thứ phép kiểm-chứng làm hỏng + thứ nó KHÔNG chứng được.
- KẾT-LUẬN: kiểm-chứng bằng POST thật đã đổi state prod: PE/2026/A/025 phase 10→98 (admin bypass qua
if (isAdmin) returndòng 186), khai rõ "admin bypass là thiết-kế, không phải regression", đề bro tự chọn revert hay giữ; PE/2026/A/021 trả 409 ⇒ không đổi state (atomic) — có kiểm lại chứ không đoán. Giới-hạn tự khai: NV Test không đóng vai approver (đã quét 20 PE) nên biến-thể actor không khả-thi; #194 dùng chữ "presumed" 4 lần cho phần không đo được; #219 bỏ qua sqlcmd vì thiếuPROD_DB_PASSWORD, chấp-nhận verify gián-tiếp và nói rõ là gián-tiếp. - BÀI-HỌC: báo-cáo verify phải tách 3 mức: đo trực-tiếp / suy ra (
inferred,presumed) / không đo được — và ghi luôn phép đo đã làm bẩn dữ-liệu. - BẤT-NGỜ: ca 409 lại là bằng-chứng dương mạnh nhất cho Plan O: lỗi 409 "mode mismatch" chứng-tỏ đã qua được cửa actor-check (403 cũ), tức thất-bại đúng chỗ = thành-công. → substring:"no state change (atomic)"
[vừa] D4 — Chuỗi Mig 28→31 + backfill có kiểm số
- VIỆC: 5 lượt deploy schema per-NV/per-Level.
- KẾT-LUẬN: Mig 28
AddAdvancedOptionsToApprovalWorkflows(#186, 6 cờ Allow* mức workflow,allowReturnToDrafter=truemặc-định + 5 false) → Mig 29RefactorAdvancedOptionsToPerLevelAndDrafterUser(#187): Levels +5 Allow*, Users +1, ApprovalWorkflows −6; backfill 48/48 Levels=1 và 0/13 Users=1 (đúng vì nguồnfalse) → Plan D/C/E (#188):/api/users+allowDrafterSkipToFinal, PATCH admin 204 / nv.test 403, scope V2 chặt (nv.test 8 PE < admin 17) → Mig 30AddAllowApproverEditBudgetToLevels(S22-chốt):currentLevelOptions6 key,AwLevelDto12 key → Mig 31RefactorSkipToFinalToApproverLevel(#194): Levels +1, Users −1, endpoint zombie/allow-skip-finaltrả 404 đúng ý. - BÀI-HỌC: backfill phải kiểm cả hai chiều — "48/48 = 1" và "0/13 = 1" đều là kết-quả ĐÚNG cần xác-nhận; số 0 ở đây là bằng-chứng, không phải thiếu-sót. Dọn field cũ thì phải kiểm cả endpoint lẫn key trong DTO đã biến mất.
- BẤT-NGỜ: cùng một tính-năng bị dời chỗ 3 lần (workflow → user → level) trong ~2 ngày; test-gate suy-ra từ "deploy chạy được" chứ không đọc trực-tiếp (
test gate inferred PASS). → substring:"AddAdvancedOptionsToApprovalWorkflows"
[thấp] D8 — Đánh-bóng UX + 1 ca revert trong phiên
- VIỆC: 4 Run FE thuần: #204 banner
mx-5→mb-3; #209 sidebartruncate(min-w-0 flex-1+shrink-0+title=tooltip); #210 widenw-60 → w-72 xl:w-80kèm revert Plan U; #214 wrap nhãn dài. - KẾT-LUẬN: 4/4 PASS, bundle rotate đúng kỳ vọng mỗi lần; menu
Pe_DuyetNcc_WfViewOrder=2 + họPe_DuyetNccPhuongAnOrder 6-10, tổng 1-10 liền mạch không hở/không chồng (seed idempotent). - BÀI-HỌC: đổi FE-thuần vẫn verify được gián-tiếp bằng bundle-hash làm proxy; nhưng khi một chunk bị revert trong cùng phiên thì hash phản-ánh trạng-thái tích-luỹ, không phải diff của chunk ⇒ đừng đọc hash như chữ-ký của một thay-đổi đơn lẻ.
- BẤT-NGỜ: phép đo bundle của Plan P bắt nhầm thay-đổi của Run #204 đang bay cùng lúc (
QZIPWD-g/DaLTMGcx) — vẫn kết-luận đúng nhờ đối-chiếu diff có 0 file FE, tức dùng nguồn thứ hai để cứu phép đo bị nhiễu. → substring:"ac2c859"
[cao] D9 — "Key patterns extracted S21-S25" (giữ gần như nguyên)
- VIỆC: phần (c) đã là bản chưng-cất 8 mục do chính vai viết.
- KẾT-LUẬN: 8 mục = Discovery #3 · Discovery #4 · Discovery #5 · checklist 10 điểm per-NV (liệt-kê đủ 10) · gotcha #48 + cách vá · "CI test-gate bắt được lỗi mà UAT-skip-test bỏ sót" · FE merge synthetic + userMap · capture pre-call mutation state.
- BÀI-HỌC: khi nguồn đã có lớp chưng-cất, việc nén nên giữ lớp đó gần như nguyên văn và cắt ở lớp Run bên dưới — nén lại cái đã nén là chỗ dễ mất mã-số (#48, điểm 9/10) nhất.
- BẤT-NGỜ: checklist 10 điểm ở đây là bản duy nhất liệt-kê đủ 10 trong toàn batch A — mọi chỗ khác chỉ nhắc số "8"/"9"/"10 surface points" mà không kèm nội-dung. → substring:"Key patterns extracted"
Phụ-lục token (coverage)
- gotcha#:
#41(path filter — dẫn ≥6 lần) ·#44(silent 403 — "fix confirmed" ở #210) ·#45(fix Trả lại, Run #186) ·#47(agent-memory — disproven, giữ vai PREVENTIVE) ·#48(NEW multi-Changelog.Add+ SQLite frozen-clock tie-break) - Discovery#:
#1rate-limit 429 ~5 req/phút ·#2.claude/agent-memory/**không nằm trong paths-ignore (về sau bị bác) ·#3Gitea xét TRỌN push-range (củng-cố 4 lần: #200/#201/#202 + #210 "NOT applicable") ·#4ASP.NET Core 10 record+enum cần số ·#5sqlcmd cần\\\\SQLEXPRESS4 backslash · (không đánh số)/actions/tasks≠/actions/runs(#186) ·updated_attrễ ~2 phút (#187) · "Discovery 1" 503 giữa deploy + "Discovery 2"/api/auth/login+ fieldaccessToken(#221) - surprise:
CRITICAL FAIL — K3 DTO mirror INCOMPLETE· "AllowApproverSkipToFinalmentioned only in comment line 60, NOT as actual record param" · "em main + Reviewer + Implementer all missed across 3 plan" · "Bug present 2 days prod" / "3-day prod bug latency" · "Spec hypothesis ... disproven for this commit" · "Anomaly is BENEFICIAL — catches verify gate even on docs-only tip" · "PROVES ACTOR VALIDATION SUCCESS ... 409 mode mismatch NOT 403" · "First attempt with string enum\"Drafter\"→ HTTP 400 ... Brief example payload was misleading" · "Test 2 HTTP 409 = handler threw exception → no state change (atomic)" · "NV Test actor variant not feasible (scanned 20 PEs)" · "the Budget Adjust entry ... hasuserName=\"\"empty — this is the EXACT pre-fix Bug 1 evidence" · "Side effect logged: Admin transition on PE/2026/A/025 mutated phase 10→98" · "Run #190 ... CANCELLED by concurrency ... normal not a fail" · "/api/me+/api/menu-keysreturned 404 (route names different) — Not regression" · "Memory size ... PRIORITY MAX REINFORCED" · "8 surface points checklist (NOT 6)" · "prophylactic codebase scan is needed" - guard:
if (isAdmin) return(line 186, admin bypass CỐ Ý) ·if (!isAdmin && currentLevel is not null)(line 264) ·&& l.ApproverUserId == actorId+throw if null(4 site Plan O) · fallback?? curStep?.Levels.FirstOrDefault(...)cho admin/non-approver (Plan N) ·[Authorize]class-level +GetWorkflowsForUserAsyncauth filter (fix #44) ·if (!demoSeedDisabled)bọc 5 seed demo (Plan T) ·.Where(c => c.Summary!.Contains("Chuyển phase"))(vá #48) ·HasDefaultValue(false)(điểm 2 checklist) · Migration 3-file rule (Up + Designer + Snapshot — điểm 3) ·[FromBody]record param count = Command param count (điểm 10) · seed Order shift idempotent (1-10 liền mạch) · token-cache%TEMP%\*_token.txtchống 429 · test-gate CI chặn trước deploy - root-cause:
FirstOrDefault(l => l.Order == curLevelOrder)không lọc actor ⇒ luôn lấyLevels[0]theo thứ-tự DB ⇒ cờ per-NV admin tick bị bỏ qua (4 site cùng bệnh) · ControllerTransitionPeBody3 field ⟂ Command 7 field ⇒ ASP.NETdefaultim-lặng 3 field ⇒ F1/F2 không tới handler suốt 2 ngày ·AwLevelDtothiếu param +ToDtothiếu ctor-arg ⇒ cột DB có mà API không trả · nhiềuChangelog.Add()cùngSaveChangesAsync+ SQLite frozen-clock ⇒OrderByDescending(CreatedAt)tie-break bất-định · Gitea xét paths-ignore trên trọn push-range ⇒ tip docs-only vẫn chạy · thiếuJsonStringEnumConverter⇒ enum dạng chuỗi fail 400 ·\\SQLEXPRESS(2 backslash) ⇒ 0 output, im-lặng ·UserNamekhông set ở 9 siteChangelog.Add()⇒ cột người-dùng rỗng - file:line / định-danh (BE):
ApprovalWorkflowV2AdminFeatures.cs:23-38 (AwLevelDtorecord), comment :60,ToDto:156-158, vùng :184-238 ·PurchaseEvaluationFeatures.cs:765 (per-NV lookup), :314-315 (AdjustBudget) ·PurchaseEvaluationWorkflowService.cs:204 (EnsureCanRejectV2Async), :258-260 (ApplyReturnModeAsync), :264 (guard), :186 (admin bypass), :75-103 (nhánh Reject Plan AC), :472 (prefix[Duyệt vượt cấp tới Cấp cuối]), :287-333 (F1 edge Bước 1), :268-275 (F1.Drafter giữ TraLai) ·PurchaseEvaluationDetailFeatures.cs:75-76 (EnsureEditableForDetailsAsync) · ControllerTransitionPeBody:267 (3 field) → :280-286 (7 param),mediator.Send:76-78, marker Plan P :71-75 ·TransitionPurchaseEvaluationCommand:395 ·Program.cs(0 hitJsonStringEnumConverter/AddJsonOptions) ·DbInitializer.cs·MenuKeys.cs·appsettings.json/appsettings.Development.json/appsettings.Production.json(bị.gitignore) - file:line / định-danh (test + FE): test
ApplyReturnMode_OneStep_AtStep1line 350 ·ApplyReturnMode_OneLevel_AtStep1Level1line 308 ·GetPurchaseEvaluationCurrentLevelOptionsTests.cs(2 method) ·PurchaseEvaluationPerNvLookupRegressionTests.cs(3 test) ·PeDetailTabs.tsx(fe-user + fe-admin, mirror §3.9) ·PeWorkflowPanel.tsx·types/purchaseEvaluation.ts(WorkflowReturnMode = { OneLevel:1, OneStep:2, Assignee:3, Drafter:4 }) ·Layout.tsx(w-60 → w-72 xl:w-80;min-w-0 flex-1+shrink-0+truncate+title=) ·WorkflowMatrixViewPage.tsx·approvalWorkflowV2.ts·App.tsx· helperextractNextTargetHint(comment, decision)· regex\[Bước (\d+) — Cấp (\d+)\]·resolveActorName/resolveUserName+userMapuseMemo - Run / sha / bundle: #186
eea86fd(id=300) · #187c0af9e0(301) · #188a74e671(302) · #18940f64c6· #1908185070CANCELLED · #1910e70789· #19230d51c8· #193b04a11a(307) · #194098baa6(308) PARTIAL · #1950062fcb(309) · #199da30e27· #200f4055a1(314) · #201fb3c22c(315) · #202a1c8386(316) · #2031727bd5(317) · #204108268a· #2070b97840· #2087b7b28f· #20986d8806· #210ac2c859(324) · #214ee0902a(328) · #217a734bf2· #21825837b6(332) · #2190aaf2df(333) · #2209ea62be(334) · #221506cada(335) · commit lẻ:c2042ef/4dd6f9c/508b17a(Plan M) ·0326458(N1+N2) ·ae01ca5(O1-O5) ·ee776d5/c667802(AA) ·b079b27(BE Mig 30) ·cc8a7d3(SKIP) ·3d725c4..cc8a7d3·e23f51c..506cada· bundle-chain adminCzesdXLh→D5l49-70→Cclc8Uwu→CpI5OL8n→CRsX6cFo→D_JENTBi→QZIPWD-g→Dmk--X6w→CZdXQ2eo→CrHpBYFM→B5iZMa7g→CDVnRDe6→DR95zKWg→C8TvDy7r; userDP-gH4LW→B6N5hq3d→d064StNa→X7qb4Zl4→COJhbRxy→DaLTMGcx→Bd4gh3Tp→DCwhhey2→C3bCWZ90→CHJDH3M2→gAFN3NVx→BAj_Yaj5→BvcWrq2z - Mig / dữ-liệu prod: Mig 28
20260513114505_AddAdvancedOptionsToApprovalWorkflows· Mig 29RefactorAdvancedOptionsToPerLevelAndDrafterUser(backfill 48/48 Levels · 0/13 Users) · Mig 3020260513160703_AddAllowApproverEditBudgetToLevels· Mig 3120260514160124_RefactorSkipToFinalToApproverLevel· test-count chuỗi 84 → 103 → 104 → 106 → 108 → 111 · Users 33 · Suppliers 19 · Projects 9 · Contracts 7 · PE-ID3248f2f9-c6e9-43ff-a4ca-067ffecf9f36(PE/2026/A/032) ·98736f06-...(A/025) ·59176ad5-...(A/027) ·6148ba7a-...(A/026) ·f9476dad-...(A/021) · workflowbf31f120· token len admin 468 / nv.test 477 ·~720 rows wiped - 🔐 secret (đã xử-lý): dòng 48 verbatim —
appsettings.Production.jsontạiC:\inetpub\solution-erp\api\,user=vrapp, password prod ĐÃ ĐƯỢC LEAD REDACT thành nhãnpwd=[đã che 71b7740a — ROTATE REQUIRED]— gist chép NHÃN CHE này, TUYỆT ĐỐI không tra/chép giá-trị gốc từ git history; ROTATE REQUIRED vẫn treo (mật-khẩu từng nằm trong lịch-sử git) - meta / size-trend:
~35KB → ~40 → ~43 → ~50 → ~58 → ~60 → ~62 → ~66 → ~69 → ~72KB· ngưỡng mềm 25KB / cứng 50KB · FIFO~8 → ~9 → ~10 → ~11 → ~12 → ~13 entry· token-cost mỗi lượt~10k-28k·feedback_md_compact_narrative.md(§6.5) ·feedback_uat_skip_verify·feedback_per_nv_permission_scope.md
Bổ-sung coverage @P3-gate S170 (token literal — nội-dung đã sống dạng dải/range ở trên; dòng dưới chép NGUYÊN-VĂN context verbatim làm lưới grep)
#216— > Target slim MEMORY.md after archive: ~25-30KB (~5 entries kept: Run #215 fail lesson + Run #216 fix + Run #222-#227 S26 + setup baseline).…#222— > Target slim MEMORY.md after archive: ~25-30KB (~5 entries kept: Run #215 fail lesson + Run #216 fix + Run #222-#227 S26 + setup baseline).…#227— > Target slim MEMORY.md after archive: ~25-30KB (~5 entries kept: Run #215 fail lesson + Run #216 fix + Run #222-#227 S26 + setup baseline).…83c9f7b— (S23 t3 Plan M push range83c9f7b..f4055a14 commits: Chunk M1 BE Service F1.OneLevel/OneStep edge case Bước 1 → reset (0,1) giữ ChoDuyet + a…8c05947— PASS verdict — fix Bug 3 "Lịch sử duyệt" panel show Trả lại + Duyệt vượt cấp. Push8c05947..a734bf21 commit Plan AC. Duratio…Mig 26— (S25 t4 Plan AC2 — FE merge view recover historical Reject events PE cũ — pusha734bf2..25837b61 commit Plan AC2 FE-only). Duration 3m23s base…Mig 27— (S23 t11 Plan U FE sidebar truncate). Commit 2 file FE × 2 app mirrorLayout.tsx— MenuNodeRenderer button (accordion toggle) + MenuLeaf NavLink …PurchaseEvaluationDetailFeatures.cs:75— (S23 t5 Plan O HOTFIX cascade 4 lookup sites — push rangefb3c22c..a1c83862 commits:ae01ca5Chunk O1-O5 atomic BE fix 4 lookup sites cùng pat…PurchaseEvaluationFeatures.cs:314— (S23 t5 Plan O HOTFIX cascade 4 lookup sites — push rangefb3c22c..a1c83862 commits:ae01ca5Chunk O1-O5 atomic BE fix 4 lookup sites cùng pat…PurchaseEvaluationWorkflowService.cs:204— -PurchaseEvaluationWorkflowService.cs:204step.Levels.FirstOrDefault(l => l.Order == curLvl && l.ApproverUserId == actorId)+ throw if null…PurchaseEvaluationWorkflowService.cs:258— -PurchaseEvaluationWorkflowService.cs:258-260`step.Levels.FirstOrDefault(l => l.Order == evaluation.CurrentApprovalLevelOrder && l.ApproverUserId …Run #187— ### 2026-05-13 20:12-20:15 — Run #187 id=301 sha=c0af9e0 VERDICT=PASS…Run #193— (S22 chốt — em main spawn cumulative verify cuối S22). Latest CI run #193 id=307 sha=b04a11a(S22+5 Chunk B FE) success at 23:16. **Tip commit…Run #194— ### 2026-05-14 ~16:30 — Run #194 id=308 sha=098baa6VERDICT=PARTIAL…Run #195— ### 2026-05-14/15 — Run #195 id=309 sha=0062fcbVERDICT=PASS…Run #199— (S23 t3 Plan M push range83c9f7b..f4055a14 commits: Chunk M1 BE Service F1.OneLevel/OneStep edge case Bước 1 → reset (0,1) giữ ChoDuyet + a…Run #200— ### 2026-05-15 ~11:21-11:25 — Run #200 id=314 sha=f4055a1VERDICT=PASS…Run #201— ### 2026-05-15 12:42-12:45 — Run #201 id=315 sha=fb3c22cVERDICT=PASS…Run #202— ### 2026-05-15 13:18 — added S23 t5 Plan O HOTFIX Run #202 entry…Run #203— ### 2026-05-15 13:45 — added S23 t6 Plan P HOTFIX Run #203 entry…Run #207— ### 2026-05-15 ~14:15 — Run #207 sha=0b97840VERDICT=PASS…Run #208— ### 2026-05-15 ~14:30 — Run #208 sha=7b7b28fVERDICT=PASS…Run #209— ### 2026-05-15 ~14:50 — Run #209 sha=86d8806VERDICT=PASS…Run #210— ### 2026-05-15 15:25 — added S24 t1 Plan AA Run #210 entry…Run #214— FAIL verdict at test_infra gate — 2 Plan M edge case tests brokenApplyReturnMode_OneStep_AtStep1line 350 + `ApplyReturnMode_OneLevel_AtStep1…Run #215— > Target slim MEMORY.md after archive: ~25-30KB (~5 entries kept: Run #215 fail lesson + Run #216 fix + Run #222-#227 S26 + setup baseline).…Run #216— > Target slim MEMORY.md after archive: ~25-30KB (~5 entries kept: Run #215 fail lesson + Run #216 fix + Run #222-#227 S26 + setup baseline).…Run #218— ### 2026-05-19 11:00-11:03 — Run #218 id=332 sha=25837b6VERDICT=PASS…Run #219— ### 2026-05-19 11:25 — added S25 t5 Plan AD Run #219 entry…Run #220— ### 2026-05-19 12:33-12:36 — Run #220 id=334 sha=9ea62beVERDICT=PASS…Run #221— ### 2026-05-19 13:05-13:08 — Run #221 id=335 sha=506cadaVERDICT=PASS…Run #222— > Target slim MEMORY.md after archive: ~25-30KB (~5 entries kept: Run #215 fail lesson + Run #216 fix + Run #222-#227 S26 + setup baseline).…a1a910f— (S24 t1 Plan AA — IsUserSelectable filter + WfView menu + sidebar widen). Push rangea1a910f..ac2c8593 commits:ee776d5Chunk A BE+Layout (6 fi…eb106f2— (Plan K 8 commits S23 t1 Mig 31 F2 refactor sang per-Approver-slot — push rangeeb106f2..098baa6). Run completedstatus=success. **Mig 31 prod T…