Files
solution-erp/.claude/agent-memory/cicd-monitor/archive/2026-05-runs.gist.md
2026-08-03 10:53:28 +07:00

31 KiB
Raw Blame History

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 ý)

  1. Chuỗi per-NV lookup discrimination (Plan K→P, Mig 29/30/31): bug FirstOrDefault khô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ọi FirstOrDefault(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.NET default im-lặng).
  2. Saga Discovery #3 chốt sau 5 lần quan-sát: Gitea xét paths-ignore trê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".
  3. 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 userMap từ dữ-liệu nhúng sẵn; Run #217 a734bf2 = nguồn duy nhất Discovery #5 + pattern "capture pre-call mutation state".
  4. Plan T tắt DemoSeed: cờ chống re-seed chỉ tin sau restart THẬT (Restart-WebAppPool + sqlcmd đếm 0); appsettings.Production.json bị .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).
  5. Lệnh đo sai trả về IM-LẶNG (7 phát-hiện công-cụ: /actions/tasks≠runs · updated_at trễ ~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 + field accessToken) — 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 098baa6 PARTIAL — schema + FE checkbox thứ 7 đã ship nhưng AwLevelDto (ApprovalWorkflowV2AdminFeatures.cs:23-38) thiếu hẳn param AllowApproverSkipToFinal (chỉ tồn-tại trong comment dòng 60) + ToDto:156-158 thiếu ⇒ checkbox đọc/ghi vào hư-vô. #195 0062fcb vá 15 LOC ⇒ 13 key round-trip PASS, đúc checklist 8 điểm. #201 fb3c22c (Plan N) vá PurchaseEvaluationFeatures.cs:765 thêm && l.ApproverUserId == currentUser.UserId + fallback admin ⇒ điểm 9. #202 a1c8386 (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). #203 1727bd5 (Plan P) vá Controller TransitionPeBody từ 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 == ...)đ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ày3 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 trong paths-ignore nên kích CI" → BỊ BÁC ở S22-chốt vì **/*.md khớp mọi độ sâu (cc8a7d3 SKIP đúng). Chốt sau 3 lần củng-cố (#200 f4055a1, #201 fb3c22c, #202 a1c8386 — 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-.md tươ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 Reject Service: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 → #218 25837b6 (AC2) FE dựng synthetic Reject row từ Changelog entityType=5 (20 entry, 8 Workflow-entry, khớp keyword "Trả về") → #219 0aaf2df (AD) bỏ badge from/to + extractNextTargetHint() parse \[Bước (\d+) — Cấp (\d+)\] → #220 9ea62be (AE) vá 9 site UserName = currentUser.FullName ?? currentUser.Email (4 Features + 5 DetailFeatures) → #221 506cada (AF) FE userMap useMemo dựng từ 5 nguồn nhúng sẵn (drafter/approvals/levelOpinions/departmentOpinions/approvalFlow.steps), 3 nấc: tin entry.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/users chỉ-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:39 entityType=1userName="" — 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→ChoDuyet tự-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, #208 7b7b28f).
  • 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 ép Restart-WebAppPool SolutionErp-Api rồ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.json bị .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/runs trả 404; đọc không cần auth. (2) updated_at trong bảng task trễ ~2 phút — phải đối-chiếu LastWriteTime của .dll/.html trê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 (grep Program.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ông token); /api/me + /api/menu-keys 404 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ữ nguồn viết priority thường). 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) return dò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ếu PROD_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=true mặc-định + 5 false) → Mig 29 RefactorAdvancedOptionsToPerLevelAndDrafterUser (#187): Levels +5 Allow*, Users +1, ApprovalWorkflows 6; backfill 48/48 Levels=1 và 0/13 Users=1 (đúng vì nguồn false) → 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 30 AddAllowApproverEditBudgetToLevels (S22-chốt): currentLevelOptions 6 key, AwLevelDto 12 key → Mig 31 RefactorSkipToFinalToApproverLevel (#194): Levels +1, Users 1, endpoint zombie /allow-skip-final trả 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-5mb-3; #209 sidebar truncate (min-w-0 flex-1 + shrink-0 + title= tooltip); #210 widen w-60 → w-72 xl:w-80 kè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_WfView Order=2 + họ Pe_DuyetNccPhuongAn Order 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 (chép ĐỦ 10, nguyên-văn rút gọn — vá P2a-MAJOR-2 @S170): (1) Domain entity field · (2) EF config HasDefaultValue(false) · (3) Migration 3-file rule (Up + Designer + Snapshot) · (4) Service handler read field · (5) Domain DTO + Application DTO mirror · (6) Designer FE checkbox inline · (7) Admin overview AwLevelDto record + ToDto ctor · (8) CreateAwLevelInput record + Update mutation handler · (9) Lookup discrimination in handler (FirstOrDefault ADD ApproverUserId == actorId filter, fallback admin) · (10) Controller body record mirror count check ([FromBody] record param count = Command record param count) — kèm 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. (Chính draft này lượt đầu đã dính đúng bẫy đó: tuyên "bản duy nhất đủ 10" rồi chỉ giữ ~6 — reviewer P2a bắt, vá bằng chép đủ 10 ở trên.)
  • BẤT-NGỜ: checklist 10 điểm ở verbatim 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 (đủ 10 mục gốc: verbatim vùng "Key patterns extracted" mục 4). → 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#: #1 rate-limit 429 ~5 req/phút · #2 .claude/agent-memory/** không nằm trong paths-ignore (về sau bị bác) · #3 Gitea xét TRỌN push-range (số lần củng-cố: NGUỒN TỰ MÂU-THUẪN — tiêu-đề verbatim ghi "RE-CONFIRMED 4th time" nhưng thân ngay dưới ghi #210 "does NOT reinforce" ⇒ 3 lần củng-cố THẬT #200/#201/#202 + 1 lần #210 không-tính; thân-draft dùng số 3 là theo vế thân) · #4 ASP.NET Core 10 record+enum cần số · #5 sqlcmd cần \\\\SQLEXPRESS 4 backslash · (không đánh số) /actions/tasks/actions/runs (#186) · updated_at trễ ~2 phút (#187) · "Discovery 1" 503 giữa deploy + "Discovery 2" /api/auth/login + field accessToken (#221)
  • surprise: CRITICAL FAIL — K3 DTO mirror INCOMPLETE · "AllowApproverSkipToFinal mentioned 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…)" (trích cắt — nguồn còn "— NV Test = Drafter not approver") · "the Budget Adjust entry ... has userName=\"\" 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-keys returned 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 + GetWorkflowsForUserAsync auth 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.txt chố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ấy Levels[0] theo thứ-tự DB ⇒ cờ per-NV admin tick bị bỏ qua (4 site cùng bệnh) · Controller TransitionPeBody 3 field ⟂ Command 7 field ⇒ ASP.NET default im-lặng 3 field ⇒ F1/F2 không tới handler suốt 2 ngày · AwLevelDto thiếu param + ToDto thiếu ctor-arg ⇒ cột DB có mà API không trả · nhiều Changelog.Add() cùng SaveChangesAsync + 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ếu JsonStringEnumConverter ⇒ enum dạng chuỗi fail 400 · \\SQLEXPRESS (2 backslash) ⇒ 0 output, im-lặng · UserName không set ở 9 site Changelog.Add() ⇒ cột người-dùng rỗng
  • file:line / định-danh (BE): ApprovalWorkflowV2AdminFeatures.cs :23-38 (AwLevelDto record), 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) · Controller TransitionPeBody :267 (3 field) → :280-286 (7 param), mediator.Send :76-78, marker Plan P :71-75 · TransitionPurchaseEvaluationCommand :395 · Program.cs (0 hit JsonStringEnumConverter/AddJsonOptions) · DbInitializer.cs · MenuKeys.cs · appsettings.json / appsettings.Development.json / appsettings.Production.json (bị .gitignore)
  • file:line / định-danh (test + FE): test ApplyReturnMode_OneStep_AtStep1 line 350 · ApplyReturnMode_OneLevel_AtStep1Level1 line 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 · helper extractNextTargetHint(comment, decision) · regex \[Bước (\d+) — Cấp (\d+)\] · resolveActorName/resolveUserName + userMap useMemo
  • Run / sha / bundle: #186 eea86fd (id=300) · #187 c0af9e0 (301) · #188 a74e671 (302) · #189 40f64c6 · #190 8185070 CANCELLED · #191 0e70789 · #192 30d51c8 · #193 b04a11a (307) · #194 098baa6 (308) PARTIAL · #195 0062fcb (309) · #199 da30e27 · #200 f4055a1 (314) · #201 fb3c22c (315) · #202 a1c8386 (316) · #203 1727bd5 (317) · #204 108268a · #207 0b97840 · #208 7b7b28f · #209 86d8806 · #210 ac2c859 (324) · #214 ee0902a (328) · #217 a734bf2 · #218 25837b6 (332) · #219 0aaf2df (333) · #220 9ea62be (334) · #221 506cada (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 admin CzesdXLh→D5l49-70→Cclc8Uwu→CpI5OL8n→CRsX6cFo→D_JENTBi→QZIPWD-g→Dmk--X6w→CZdXQ2eo→CrHpBYFM→B5iZMa7g→CDVnRDe6→DR95zKWg→C8TvDy7r; user DP-gH4LW→B6N5hq3d→d064StNa→X7qb4Zl4→COJhbRxy→DaLTMGcx→Bd4gh3Tp→DCwhhey2→C3bCWZ90→CHJDH3M2→gAFN3NVx→BAj_Yaj5→BvcWrq2z
  • Mig / dữ-liệu prod: Mig 28 20260513114505_AddAdvancedOptionsToApprovalWorkflows · Mig 29 RefactorAdvancedOptionsToPerLevelAndDrafterUser (backfill 48/48 Levels · 0/13 Users) · Mig 30 20260513160703_AddAllowApproverEditBudgetToLevels · Mig 31 20260514160124_RefactorSkipToFinalToApproverLevel · test-count chuỗi 84 → 103 → 104 → 106 → 108 → 111 · Users 33 · Suppliers 19 · Projects 9 · Contracts 7 · PE-ID 3248f2f9-c6e9-43ff-a4ca-067ffecf9f36 (PE/2026/A/032) · 98736f06-... (A/025) · 59176ad5-... (A/027) · 6148ba7a-... (A/026) · f9476dad-... (A/021) · workflow bf31f120 · token len admin 468 / nv.test 477 · ~720 rows wiped
  • 🔐 secret (đã xử-lý): dòng 48 verbatim — appsettings.Production.json tại C:\inetpub\solution-erp\api\, user=vrapp, password prod ĐÃ ĐƯỢC LEAD REDACT thành nhãn pwd=[đã 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 — ⚠️ LƯỚI GREP THUẦN, KHÔNG PHẢI DỮ KIỆN (đoạn trích sau mỗi token là phần ĐẦU DÒNG verbatim chứa token — dòng archive là mega-line nên đoạn trích thường KHÔNG liên-quan token; CHỈ dùng để coverage-diff grep trúng, đọc nội-dung thì tra verbatim theo token — reviewer P3 @S170)

  • #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 range 83c9f7b..f4055a1 4 commits: Chunk M1 BE Service F1.OneLevel/OneStep edge case Bước 1 → reset (0,1) giữ ChoDuyet + a…
  • 8c05947PASS verdict — fix Bug 3 "Lịch sử duyệt" panel show Trả lại + Duyệt vượt cấp. Push 8c05947..a734bf2 1 commit Plan AC. Duratio…
  • Mig 26 — (S25 t4 Plan AC2 — FE merge view recover historical Reject events PE cũ — push a734bf2..25837b6 1 commit Plan AC2 FE-only). Duration 3m23s base…
  • Mig 27 — (S23 t11 Plan U FE sidebar truncate). Commit 2 file FE × 2 app mirror Layout.tsx — MenuNodeRenderer button (accordion toggle) + MenuLeaf NavLink …
  • PurchaseEvaluationDetailFeatures.cs:75 — (S23 t5 Plan O HOTFIX cascade 4 lookup sites — push range fb3c22c..a1c8386 2 commits: ae01ca5 Chunk O1-O5 atomic BE fix 4 lookup sites cùng pat…
  • PurchaseEvaluationFeatures.cs:314 — (S23 t5 Plan O HOTFIX cascade 4 lookup sites — push range fb3c22c..a1c8386 2 commits: ae01ca5 Chunk O1-O5 atomic BE fix 4 lookup sites cùng pat…
  • PurchaseEvaluationWorkflowService.cs:204 — - PurchaseEvaluationWorkflowService.cs:204 step.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=098baa6 VERDICT=PARTIAL…
  • Run #195 — ### 2026-05-14/15 — Run #195 id=309 sha=0062fcb VERDICT=PASS…
  • Run #199 — (S23 t3 Plan M push range 83c9f7b..f4055a1 4 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=f4055a1 VERDICT=PASS…
  • Run #201 — ### 2026-05-15 12:42-12:45 — Run #201 id=315 sha=fb3c22c VERDICT=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=0b97840 VERDICT=PASS…
  • Run #208 — ### 2026-05-15 ~14:30 — Run #208 sha=7b7b28f VERDICT=PASS…
  • Run #209 — ### 2026-05-15 ~14:50 — Run #209 sha=86d8806 VERDICT=PASS…
  • Run #210 — ### 2026-05-15 15:25 — added S24 t1 Plan AA Run #210 entry…
  • Run #214 — id=328 sha=ee0902a VERDICT=PASS (bundle baseline admin CZdXQ2eo + user DCwhhey2, Mig 31 TOP 1 unchanged, smoke 5/5 200) — dòng này @P3-mức-3 thay đoạn trích đầu-dòng cũ vốn dính thân entry Run #215 FAIL ⇒ gán verdict ngược (reviewer P3-B1)
  • 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=25837b6 VERDICT=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=9ea62be VERDICT=PASS…
  • Run #221 — ### 2026-05-19 13:05-13:08 — Run #221 id=335 sha=506cada VERDICT=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 range a1a910f..ac2c859 3 commits: ee776d5 Chunk A BE+Layout (6 fi…
  • eb106f2 — (Plan K 8 commits S23 t1 Mig 31 F2 refactor sang per-Approver-slot — push range eb106f2..098baa6). Run completed status=success. **Mig 31 prod T…