Files
solution-erp/.claude/agent-memory/implementer-backend/archive/2026-06.gist.md
pqhuy1987 c2d01f0dce
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m30s
[CLAUDE] Docs: S152 closeout — bookend hình B trọn 2 đầu + owner (30)(31)(32) + queue memory-ops TRỌN (squash 20 wal:)
- Owner 3-quyết: (30) JUMP để-nguyên-theo-nhịp · (31) 4 persona +NEVER-block (restart ĐÃ THOẢ) · (32) vòng 1→5 AUTO — lô consent gỡ 9 site (5 H1 + ring1-tự-bắt + 3 trio; E-013 EXT)
- Memory-ops TRỌN: A1-A4/D1/D2/R1/B-series — A7 392/392 · mfe 20/20-100% lần đầu · lead-gap drain 24.728→16.485B · strike-ledger + WARN-latch (-Ack = owner-action)
- V4 sleep AUTO đầu: 1 shard thật/16 KÊU · ring4 đầu-đời TRƯỢT-4/5 → 4 fix gist (scribe sub-ring4-close vì return-only)
- Thư model re-stamp: 59ce1d0f → 9c909007 published (G-024a) — adap-report Đính-chính @S152 + sweep 13 bề-mặt LIVE
- Bookend @close: stale 6 FLAG + gap 2 FLAG → vá 8/8; ring2 8/8 ĐẠT (4-A pin-bản-cắt → slot 33) · ring1 48Đ/5T/59-claim
- M9 13 đơn-vị diary (3 S151-deep hồi-tố) · #53 ×10-chắc → tally 60-cận-dưới + errata subject-1b85713
- Session-log 2 run= + completeness-gate 5-vòng ĐẠT · HANDOFF segment S152 (carry 3-đóng/3-mới/23-giữ; slot 33/34)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 01:58:30 +07:00

94 lines
18 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.

distill-gen: 1
# Gist — 2026-06 archive (S41-S55) · 4-field distillation
> **distill-gen: 1** — already-distilled; do NOT re-compress. Each block = VIỆC · KẾT-LUẬN(+Mig/file:line) · BÀI-HỌC · BẤT-NGỜ, ending `→ substring:"…"` grep-UNIQUE in `2026-06.md` (14 bullets moved byte-exact from MEMORY.md L87-L104, S? Harness-9 curate). Pointer-style = substring (Ctrl-F), Mig-name / phrase keyed. value tag: cao/vừa/thấp.
> The final subsection distills L1-HOT markers (S56/S57bis/S65) that REMAIN in MEMORY.md (not moved) — included here only so the coverage checklist resolves in one place; their verbatim lives in MEMORY.md, pointer notes say so.
---
## P11-A WorkflowApps wave (S41-S42) — schema + app + seed
**[cao] Mig 41 schema — 4 WorkflowApps ApproveV2 + LevelOpinions (S41 P11-A W1).** VIỆC: cookie-cutter mirror Proposal Mig 38 — 5 entity (4 {Leave,Ot,Travel,Vehicle}RequestLevelOpinion + shared WorkflowAppCodeSequence Prefix-PK) + 5 EF config (auto-discover ApplyConfigurationsFromAssembly) + 4 parent nav + enum TravelRequest=9 + 2 DbSet. KẾT-LUẬN: Mig 41 WireWorkflowAppsApprovalV2; diff CLEAN 5 CreateTable+4 AddColumn; FK Cascade parent + Restrict Level + UNIQUE composite; both DB. BÀI-HỌC: Pattern 12-bis 13× cumulative. BẤT-NGỜ: none (spec deterministic 100%). → substring:"S41 P11-A Wave 1 SCHEMA — wire ApproveV2+LevelOpinions"
**[cao] App-layer ApproveV2 CQRS (S42 Wave 2a LeaveOt stub + 2b Travel/Vehicle).** VIỆC: per-module DetailDto+LevelOpinionDto+GetById(JOIN Step/Level)+UpdateDraft+Submit+Approve(UPSERT+advance)+Reject+Return; shared internal CodeGen Serializable-tx. KẾT-LUẬN: TravelVehicleApprovalFeatures ~830 LOC; codes `{prefix}/{seq:D3}` (D3 NO year segment per spec) vs Leave/Ot `{prefix}/{year}/{seq:D3}`. BÀI-HỌC: **WorkflowAppCodeGen Serializable-tx Prefix-keyed**; **WorkflowAppStatus enum DIFFERS ProposalStatus int values (DaGuiDuyet=2 not 1, TraLai=3) → mirror by SEMANTIC enum member NOT literal**; Owner=RequesterUserId (not DrafterUserId); Submit verify wf.ApplicableType else Conflict. BẤT-NGỜ: 2a content absorbed (stub→git) into Pattern 4 + this 2b entry. → substring:"S42 P11-A Wave 2b APP — wire ApproveV2 CQRS Travel+Vehicle"
**[cao] Seed 4 sample workflow V2 (S42 P11-A) — gotcha #51.** VIỆC: DbInitializer mirror SeedSampleProposalWorkflowV2Async EXACT ×4 (Leave/Ot/Travel/Vehicle), each idempotent AnyAsync(ApplicableType) guard → 1 Workflow+1 Step+1 Level, codes QT-NP/OT/CT/XE-V2-001. KẾT-LUẬN: wired 4 calls; build 0 err 0 warn. BÀI-HỌC (marker #4): **gotcha #51 — infra seed NOT gated by DemoSeed:Disabled** (by-design reaches prod, like SeedDemoMasterData/Catalogs). BẤT-NGỜ: Bash tool runs bash NOT PowerShell despite env hint → use `cd && cmd | grep`. → substring:"S42 P11-A SEED — 4 sample ApprovalWorkflow V2"
## P11-B/C HRM business + catalogs (S43, S51)
**[cao] LeaveBalance deduct exactly-once (S43 P11-B W1) — Mig 42.** VIỆC: entity LeaveBalance:AuditableEntity (UserId/LeaveTypeId/Year + Entitled/Used/Adjustment decimal(5,2)); FK LeaveType Restrict + UNIQUE composite (UserId,LeaveTypeId,Year); deduction hook in ApproveLeaveRequestHandler terminal DaDuyet branch ONLY. KẾT-LUẬN: Mig 42 AddLeaveBalances; RemainingDays = Entitled+AdjustmentUsed COMPUTED (not stored); GetMy/GetUser lazy-merge in-memory (no EF LEFT JOIN). BÀI-HỌC (marker #12): **deduct exactly-once GUARANTEED by early guard `Status != DaGuiDuyet throw`**; HRM admin convention `[Authorize(Roles="Admin")]` not menu policy. BẤT-NGỜ: OtRequest/Travel/Vehicle untouched — only Leave has balance. → substring:"S43 P11-B Wave 1 — LeaveBalance business logic"
**[cao] Vehicle+Driver catalogs (S51 P11-C W1) — Mig 44, gotcha #57.** VIỆC: 2 entity + 2 EF config (mirror filtered HolidayConfiguration NOT buggy bare LeaveType) + 2 DbSet + HrmConfigFeatures Region5/6 + Controller 8 endpoint (GET public, write Admin) + MenuKeys + DbInitializer seed. KẾT-LUẬN: Mig 44 AddVehicleAndDriverCatalogs; diff CLEAN 2 CreateTable+2 filtered IX. BÀI-HỌC (markers #57,#13,#14): **Code UNIQUE `.HasFilter("[IsDeleted]=0")`**; admin perm AUTO via MenuKeys.All (SeedAdminPermissions + Program.cs:78 both iterate); HRM no HasQueryFilter→`.Where(!IsDeleted)` manual. BẤT-NGỜ: RAG/Qdrant DOWN → all Read/Grep on-disk. → substring:"S51 P11-C HMW W1 — Vehicle+Driver catalogs HrmConfigs"
## P11-D/E/F WorkflowApps wave2 (S52)
**[cao] ItTicket round-robin + SLA (S52 P11-D W2) — Mig 46.** VIỆC: entity +SlaDueAt/SlaWarnedSent/SlaBreached; CreateItTicketHandler SlaWindow static map (Urgent4/High8/Medium24/Low72h) shared w/ ItTicketSlaJob; round-robin least-loaded assign (itDept=Departments.Code=="IT"); new ItTicketSlaJob:BackgroundService (breach+warn only, NO auto-transition). KẾT-LUẬN: Mig 46 AddSlaFieldsToItTicket 3 AddColumn no-table; AssignItTicketCommand PUT /{id}/assign [Authorize(Roles=Admin)]. BÀI-HỌC: **SeedItDepartmentStaffAsync MUST run AFTER SeedDemoUsersAsync** (that method reconciles 2 users to PRO/CCM each boot → override to IT after, end-state deterministic). BẤT-NGỜ: agent killed session-limit before MEMORY → proxy by em main. → substring:"S52 P11-D Wave2 BE — ItTicket round-robin + SLA"
**[cao] Attendance report + IT codegen (S52 P11-E+F) — NO mig.** VIỆC: P11-F MaTicket gen at Create (kanban no-workflow) `IT/2026/001`; P11-E AttendanceReportFeatures + IAttendanceReportExcelExporter (ClosedXML mirror ContractExcelExporter). KẾT-LUẬN: 2 endpoint [Authorize(Roles=Admin)] GET `/api/attendances/report` + `/report/excel`. BÀI-HỌC: **DayOfWeek+holidaySet NOT EF-translate → `.ToListAsync()` then group/classify IN-MEMORY C#**; **Holiday.Date = DateOnly NOT DateTime (spec wrote HashSet<DateTime> wrong) → HashSet<DateOnly>**; day-type prio holiday→weekend→weekday; OtWeighted=Σ(level×coef). BẤT-NGỜ: spec type-error caught (DateOnly). → substring:"S52 P11-E+F Wave1 BE migration-FREE"
## Master + cross-stack (S53, S54, S55)
**[cao] Filter 3 Master unique indexes (S53 gotcha #57 EXT) — Mig 47 + Mig 46 catch-up.** VIỆC: test-before RED→GREEN; edit 3 config Code unique `+.HasFilter("[IsDeleted] = 0")` (Department/Project/Supplier); Supplier ONLY Code filtered, Type index left untouched. KẾT-LUẬN: Mig 47 FilterMasterCatalogUniqueIndexesByIsDeleted; Mig 46 local catch-up closed LocalDB gap; 203 GREEN. BÀI-HỌC (markers #2,#57): **gotcha #57 — soft-delete UNIQUE must filter [IsDeleted]=0**; **copied filter string BYTE-FOR-BYTE from HolidayConfiguration:18 + LeaveTypeConfiguration:19** (spaces around `=`, not guessed) → snapshot+SQL consistent w/ 13 existing filtered idx. BẤT-NGỜ: Master HAS global HasQueryFilter (unlike HRM) → app-check passes but bare DB index counts soft-deleted → 500; filter aligns. → substring:"S53 gotcha #57 EXT BE — filter 3 Master Code unique indexes"
**[cao] ItTicket reassign capability + fail-closed authz (S54 cross-stack) — NO mig.** VIỆC: new GetAssignableItStaffQuery capability endpoint + AssignItTicketHandler authz Admin-OR-dept-IT→ForbiddenException, assignee-must-be-IT→ConflictException; controller /assign lowered Roles=Admin→[Authorize]. KẾT-LUẬN: 2 patterns saved (controller-lower-authorize-handler-finegrained + scoped-capability-endpoint-anti-silent-403); reviewer chain-verified role-string "Admin" real (AppRoles→SeedRoles→JWT→cu.Roles). BÀI-HỌC (marker #11): **fail-closed authz — Forbidden BEFORE NotFound** (avoid existence-oracle); ICurrentUser lacks DepartmentId → query db.Users. BẤT-NGỜ: em main reconciled 2 patterns from stray src/Backend/.claude (cwd-relative Write mishap). → substring:"S54 ItTicket reassign cross-stack — IT-staff self-service"
**[vừa] Menu leaf AttendanceReport (S54 Task D) — NO mig.** VIỆC: 3 insert — MenuKeys const Off_AttendanceReport + All[] + DbInitializer menu tuple (Order 8, parent Off). KẾT-LUẬN: admin perm auto via MenuKeys.All 2-point (SeedAdminPermissions :1916 + Program.cs:78). BÀI-HỌC: idempotent seed upsert (existing prod gets leaf on restart, existing rows only Order-reconciled). BẤT-NGỜ: none. → substring:"S54 Task D BE — promote AttendanceReport to sidebar menu leaf"
**[cao] Real master-data import (S55) — Mig 48 + ungated seed.** VIỆC: Project +4 prop (Year int?, Investor/Location/Package, maxlen 250/500/300); SeedRealMasterDataAsync 3 tuple-loop per-code idempotent, wired UNGATED after SeedCatalogsAsync. KẾT-LUẬN: Mig 48 AddProjectMasterFields 4 AddColumn no-table; seeds 62 Project+71 WorkItem+3 Supplier; runtime Dev proof landed. BÀI-HỌC: real-data import reaches prod by-design (DemoSeed:Disabled NOT gate); FLOCK01 collision demo↔real → per-code skip (demo wins). BẤT-NGỜ: WorkItem divider row "THIẾT BỊ" dropped; agent return truncated #53 → proxy by em main. → substring:"S55 master-data import (Mig 48 `AddProjectMasterFields`"
## [stub→git d2f52ba] older absorbed (S35/S40 trim)
**[thấp] S35 BE-CRUD-4-catalog + S29 Contract-V2-mirror.** KEY absorbed into L1 Pattern 12-bis foundation (catalog-mega + HRM `.Where(!IsDeleted)` manual + Validator MaxLength=EF). → substring:"Archived S35 G-H2 BE-CRUD-4-catalog + S29 Plan-B-Chunk-C Contract-V2-mirror"
**[thấp] S40 curate — FE/test + older BE → git d2f52ba.** S35 FE inline forms 5 satellite + S34 test +10 (130 PASS) + S33 EmployeesListPage + S32 wrap/startup. → substring:"Archived FE/test + older BE entries → `archive/2026-05-q4.md` + git d2f52ba (S40 curate)"
---
## L1-HOT markers (still in MEMORY.md — NOT moved; distilled here for coverage completeness)
> These live VERBATIM in MEMORY.md (kept hot). Pointers below target MEMORY.md, not 2026-06.md.
- **[cao] S56 GOLIVE-HARDEN — ExecuteUpdate atomic + fail-closed (markers #10,#11).** LeaveBalance lost-update → `ExecuteUpdateAsync` server-side row-lock inside tx (em-main post-review bumped to `IsolationLevel.Serializable`); AssignItTicket existence-oracle → Forbidden guard BEFORE NotFound (fail-closed). STALE-TRACKED caveat: ExecuteUpdate bypasses tracker → don't re-add `bal.UsedDays +=` (double-count). → substring(MEMORY.md):"S56 GOLIVE-HARDEN 3 BE fix"
- **[cao] S57bis/S65 loose-Guid FK guard (marker #13).** loose-Guid FK (WorkItemId S57bis, Department.ParentId S65) = NO physical FK; guard `AnyAsync(x.Id==id && x.IsActive)`→Conflict (mirror S43); UpdateDraft null-safe `if (request.WorkItemId is not null)` to avoid null-ing bug-class S42. → substring(MEMORY.md):"FK-guard loose-Guid"
- **[vừa] L1 Pattern foundation markers (#3,#5,#9b).** gotcha #17 = EF migration 3-file rule (Pattern 2, BẮT BUỘC commit `.cs`+`.Designer.cs`+snapshot); gotcha #65 = `dotnet build SolutionErp.slnx` includes 2 test projects; Mig 29/30/31 per-NV admin opt-in (Pattern 7, proven 4×). → substring(MEMORY.md):"EF migration 3-file rule (gotcha #17"
## CỤM BỔ SUNG [coverage-diff @S152 D2 — máy-trích nguyên-văn + lead-review; KHÔNG phải re-distill, distill-gen giữ]
> Token load-bearing có trong verbatim `2026-06.md` mà gist thiếu — mỗi dòng = token + TRÍCH NGUYÊN-VĂN dòng chứa nó (Ctrl-F token trong verbatim để đọc trọn). Chuẩn gate: gotcha#/Mig/file-ref/guard phải sống trong gist.
- gotcha **#73** · trích: "6 #5) + absolute-set null=clear (gotcha #73) + changelog Header (sibling-consistency; spec min=SaveChanges). (6) Controller `[HttpPatch('{id:guid}/bud"
- Mig **Mig 11** · trích: "field nằm trên **`User.DepartmentId`** (Mig 11) → GROUP BY `db.Users.Where(DepartmentId!=null && IsActive).GroupBy(DepartmentId).ToDictionary` = Direc"
- Mig **Mig 43** · trích: "#57 4th+5th+6th cumulative (S45 Holiday Mig 43, S51 HRM×3 Mig 45 → now Department/Project/Supplier). Edit 3 config Code unique: `b.HasIndex(x=>x.Code)"
- Mig **Mig 45** · trích: "mulative (S45 Holiday Mig 43, S51 HRM×3 Mig 45 → now Department/Project/Supplier). Edit 3 config Code unique: `b.HasIndex(x=>x.Code).IsUnique()` → `+."
- Mig **Mig 49** · trích: "proposed):** Return-truncated #53 TRƯỚC Mig 49 + projection-3 → em main solo hoàn tất (fix CS7036 + CS8019, Mig 49 `AddWorkItemToPurchaseEvaluation` 3"
- Mig **Mig 51** · trích: "- **2026-06-16 (S65b PE +HoSoLink BE — Mig 51 `AddHoSoLinkToPurchaseEvaluation` 3-file, 6 file edit + 0 new file, em-main CHỐT spec 100% → ACCEPT Case"
- Mig **Mig 52** · trích: "olumn, snapshot verified — clean mirror Mig 52. (4) DTO `PurchaseEvaluationDetailBundleDto` +`decimal? CcmBudgetPeriodAmount` sau ExpectedRemainingAmo"
- Mig **Mig 55** · trích: "mn, snapshot ×2 verified — clean mirror Mig 55. (4a) `UpdatePeSuggestedPriceProCommand` +trailing `string? Note=null` + validator `MaximumLength(1000)"
- Mig **Mig 57** · trích: "-19 (S77 PE +2 ghi-chú giá đề xuất BE — Mig 57 `AddPeSuggestedPriceNotes` 3-file, 6 edit/0 new file, COOKIE-CUTTER S73 suggested-price + S74 CcmNote,"
- Mig **Mig 58** · trích: "Suppliers.Where(s=>s.IsWinner)` (multi, Mig 58) → sửa CHỈ comment-text 'MỌI đơn vị IsWinner (multi-winner Mig 58)'. Field/code UNCHANGED. **LESSON:**"
- Mig **Mig 59** · trích: "vity 2026-06-25..19 (S88 · PE Section-B Mig 59 · PE chuông) -->"
- file-ref **AttendanceReportFeatures.cs** · trích: "/001`. **P11-E** report chấm công: NEW `AttendanceReportFeatures.cs` (DTO 3 record EXACT + GetAttendanceReportHandler) + NEW `IAttendanceReportExcelEx"
- file-ref **DbInitializer.cs** · trích: "Report` after OffChamCong:158-159 · (3) DbInitializer.cs menu tuple `(OffAttendanceReport, 'Báo cáo chấm công', Off, 8, 'FileBarChart')` after OffCham"
- file-ref **Department.cs** · trích: "y tổ chức nền trang Hồ sơ Nhân sự. (1) `Department.cs` +`Guid? ParentId` loose-Guid KHÔNG physical FK (convention PE.ProjectId/WorkItemId/SelectedSupp"
- file-ref **DepartmentConfiguration.cs** · trích: "Id/WorkItemId/SelectedSupplierId). (2) `DepartmentConfiguration.cs` +`HasIndex(x=>x.ParentId)` only — **KHÔNG `HasOne` self-FK** (em main chốt loose)."
- file-ref **DepartmentFeatures.cs** · trích: "e` self-FK** (em main chốt loose). (3) `DepartmentFeatures.cs` +`GetDepartmentTreeQuery`+`DepartmentTreeNodeDto`+Handler (append existing file, NO new"
- file-ref **DepartmentsController.cs** · trích: "e; slnx lists projects-not-files). (4) `DepartmentsController.cs` +`[HttpGet('tree')]`. **KEY recon finding (spec asked verify):** `EmployeeProfile` h"
- file-ref **MasterCatalogFilteredUniqueTests.cs** · trích: "real code+year only, OK). Compile-fix `MasterCatalogFilteredUniqueTests.cs` +4 null args CreateProjectCommand (necessary build-green). **Runtime Dev"
- file-ref **MenuKeys.cs** · trích: "potent seed (not schema). 3 insert: (1) MenuKeys.cs const `OffAttendanceReport = 'Off_AttendanceReport'` after OffChamCong:124 · (2) MenuKeys.cs All[]"
- file-ref **PEFeatures.cs** · trích: "ote` sau CcmSuggestedPrice + projection PEFeatures.cs positional-insert ĐÚNG order (DTO positional → order khít projection BẮT BUỘC). **Call-site grep"
- file-ref **PeSuggestedPriceFeatures.cs** · trích: "file → move về budget file. (a) REMOVE `PeSuggestedPriceFeatures.cs` lines 144-199 (blank + `===== CCM NS kỳ này =====` header → `SetPeCcmBudgetPeriod"
- file-ref **PeWorkItemBudgetFeatures.cs** · trích: "ce PRO/CCM trên giữ nguyên. (b) APPEND `PeWorkItemBudgetFeatures.cs` END sau line 200 (`UpdatePeBudgetCcmCommandHandler` `}`) → cạnh budget setters `U"
- file-ref **ProjectFeatures.cs** · trích: "len 250/500/300 ProjectConfiguration). `ProjectFeatures.cs` DTO+CreateCmd+UpdateCmd+validators+handlers+List/Get projections +4 (all nullable, appende"
- file-ref **PurchaseEvaluation.cs** · trích: "nullable, no table/index/backfill. (1) `PurchaseEvaluation.cs` +`string? ProSuggestedPriceNote`/`CcmSuggestedPriceNote` ngay sau CcmSuggestedPrice. (2"
- file-ref **PurchaseEvaluationConfiguration.cs** · trích: "eNote` ngay sau CcmSuggestedPrice. (2) `PurchaseEvaluationConfiguration.cs` +`HasMaxLength(1000)` ×2 sau ApprovedPriceSource (KHÔNG index — free-text)"
- file-ref **PurchaseEvaluationDtos.cs** · trích: "G đụng. **T2 stale-comment fix:** `Dtos/PurchaseEvaluationDtos.cs` ~250-254 comment trên `decimal WinnerQuoteTotal` ghi SUM 'của SelectedSupplierId' ("
- file-ref **PurchaseEvaluationFeatures.cs** · trích: "ngle-winner) → verified actual compute `PurchaseEvaluationFeatures.cs:1093-1099` = `Suppliers.Where(s=>s.IsWinner)` (multi, Mig 58) → sửa CHỈ comment-"
- file-ref **PurchaseEvaluationWorkflowService.cs** · trích: "= +1 block trong `LogTransitionAsync` (PurchaseEvaluationWorkflowService.cs ~line 1058) NGAY SAU drafter-notify, KHÔNG endpoint mới (Pattern 4 — noti"
- file-ref **TravelVehicleApprovalFeatures.cs** · trích: "— wire ApproveV2 CQRS Travel+Vehicle (`TravelVehicleApprovalFeatures.cs` ~830 LOC + 2 controller edit):** Cookie-cutter mirror Wave 2a / ProposalFeat"
- file-ref **WorkflowAppsFeatures.cs** · trích: "ullName)` capability endpoint (REGION 5 WorkflowAppsFeatures.cs) + MODIFIED `AssignItTicketHandler`: authz Admin-OR-dept-IT → `ForbiddenException`; as"
- file-ref **menuKeys.ts** · trích: "ing DocxRenderer warn). KHÔNG touch FE (menuKeys.ts/Layout = implementer-frontend) / tests / commit. Tag `[s54, task-d, menu-leaf, no-mig, admin-perm-"
### BỔ-SUNG-2 [F1/F2 sau Fidelity-gate @S152 — mở đuôi infra {yml,yaml,json,slnx,csproj,sql,config} + guard IsUnique/optimistic. N/A CỐ-Ý (F5): bundle-hash xoay #69 · tên-giả phép-thử ZZfakehash* · đuôi .md]
- file-ref **SolutionErp.Application.csproj** · trích: "mirror S35 EF-source-of-truth). Build `SolutionErp.Application.csproj -v q` **0 warn 0 err** (4s). KHÔNG test (test-specialist)/FE/mig/commit. Tag `["