@ -204,6 +204,8 @@ KHÔNG `*` / `latest`. Critical pins:
## 📅 Recent activity (last 10 FIFO)
## 📅 Recent activity (last 10 FIFO)
- **2026-05-15 (S24, Plan M Chunk M3 PASS):** FE rename Phase=TraLai (98) display label "Trả lại" → "Cần chỉnh sửa lại" cho UAT disconnect fix. Spec scope HẸP (display badge label + status reference) tuân thủ strict: 4 file FE × 2 app = 8 edit total. **2 file types/purchaseEvaluation.ts** × 2 app: `PurchaseEvaluationPhaseLabel[98]` (raw phase badge) + `PeDisplayStatusLabel.TraLai` (display status badge — main user-facing). **2 file components/pe/PeWorkflowPanel.tsx** × 2 app: rename 2 inline literal hardcode "Trả lại" trong F1 dialog tooltip (`Phase → "..."` ) + confirm message (`Phiếu sẽ về "..."` ) — đây là status display reference, KHÔNG phải action verb. Pattern 5 mirror 2 app strict applied. KHÔNG đụng: (1) action button label `← Trả lại` (verb), (2) F1 mode picker label `Trả về Người soạn thảo` (4 mode action), (3) comments narrative line 62/71/etc giữ rationale dev (rule §6.5), (4) `types/contracts.ts` + `types/budget.ts` Phase 98 'Trả lại' — module Contract + Budget khác PE, ngoài scope M3. Verify: `npm run build` fe-admin PASS clean (0 TS err, 9.40s, 1395 KB bundle unchanged trivial) + `npm run build` fe-user PASS clean (0 TS err, 6.92s, 1275 KB). Diff +4/-4 LOC × 2 = 8 LOC tổng trên 4 file. Token ~9k. Decision tactical: 2 chỗ inline literal PeWorkflowPanel rename để giữ UX consistency với badge label sau rename — KHÔNG drift outside spec vì cùng "status display reference" semantics (badge + tooltip + confirm message phải mirror). Anti-fiddle threshold < 20 % LOC respected .
- ** 2026-05-14 ( S23 t1 , K7 Chunk F PASS ) : ** Mig 31 Approver F2 service regression tests . Sub-task 1 fix broken Drafter F2 test reference K1 flagged: `PurchaseEvaluationWorkflowServiceReturnModeTests.cs:253` `drafter.AllowDrafterSkipToFinal = true` ( DELETE 3 deprecated Drafter F2 tests entire — `SkipToFinal_DrafterAllowed_SetsPointerToFinalLevel` + `SkipToFinal_DrafterDenied_NonAdmin_Throws` + `SkipToFinal_AdminBypass_Succeeds` , semantic deprecated no value ). Sub-task 2 add 3 new Approver F2 tests: `ApproveV2_SkipToFinal_AdminTickFlag_SetsPhaseDaDuyet` ( happy path — slot Cấp 1 Bước 1 admin tick → Phase = DaDuyet, pointer cleared , opinion + PEA + Changelog logged ), `ApproveV2_SkipToFinal_FlagOff_NonAdmin_ThrowsConflictException` ( denied — flag off non-admin slot user → throw " chưa được phép duyệt thẳng Cấp cuối "), `ApproveV2_SkipToFinal_FlagOff_Admin_BypassesFlagCheck` ( admin bypass — flag off admin role → DaDuyet allowed ). Pattern 11 SeedWorkflowAsync cookie-cutter REUSE — created `SeedApproverF2WorkflowAsync` helper ( 2 Steps × 2 Levels — multi-step verify skip thẳng terminal KHÔNG fallthrough advance pointer next Step ), AllowApproverSkipToFinal per-slot param . PE init Phase = ChoDuyet + CurrentWorkflowStepIndex = 0 + CurrentApprovalLevelOrder = 1 ( vs S22 happy path từ DangSoanThao ). Add `using Microsoft.EntityFrameworkCore` cho `.ToListAsync()` PEL / PEA / Changelog query . File header narrative line 17-25 REWRITE để track Mig 31 refactor semantic Approver scope ChoDuyet vs Drafter-from-Nháp cũ . Verify: `dotnet build` clean 0 err 2 warn pre-existing DocxRenderer . `dotnet test SolutionErp.slnx` 104 PASS ( 58 Domain + 46 Infra , 3 deleted + 3 added cancel out , baseline preserved ). 3 Approver F2 tests verified individually PASS . Diff + 175 / -92 LOC trên 1 file . Token ~ 14k .
- ** 2026-05-14 ( S23 t1 , K7 Chunk F PASS ) : ** Mig 31 Approver F2 service regression tests . Sub-task 1 fix broken Drafter F2 test reference K1 flagged: `PurchaseEvaluationWorkflowServiceReturnModeTests.cs:253` `drafter.AllowDrafterSkipToFinal = true` ( DELETE 3 deprecated Drafter F2 tests entire — `SkipToFinal_DrafterAllowed_SetsPointerToFinalLevel` + `SkipToFinal_DrafterDenied_NonAdmin_Throws` + `SkipToFinal_AdminBypass_Succeeds` , semantic deprecated no value ). Sub-task 2 add 3 new Approver F2 tests: `ApproveV2_SkipToFinal_AdminTickFlag_SetsPhaseDaDuyet` ( happy path — slot Cấp 1 Bước 1 admin tick → Phase = DaDuyet, pointer cleared , opinion + PEA + Changelog logged ), `ApproveV2_SkipToFinal_FlagOff_NonAdmin_ThrowsConflictException` ( denied — flag off non-admin slot user → throw " chưa được phép duyệt thẳng Cấp cuối "), `ApproveV2_SkipToFinal_FlagOff_Admin_BypassesFlagCheck` ( admin bypass — flag off admin role → DaDuyet allowed ). Pattern 11 SeedWorkflowAsync cookie-cutter REUSE — created `SeedApproverF2WorkflowAsync` helper ( 2 Steps × 2 Levels — multi-step verify skip thẳng terminal KHÔNG fallthrough advance pointer next Step ), AllowApproverSkipToFinal per-slot param . PE init Phase = ChoDuyet + CurrentWorkflowStepIndex = 0 + CurrentApprovalLevelOrder = 1 ( vs S22 happy path từ DangSoanThao ). Add `using Microsoft.EntityFrameworkCore` cho `.ToListAsync()` PEL / PEA / Changelog query . File header narrative line 17-25 REWRITE để track Mig 31 refactor semantic Approver scope ChoDuyet vs Drafter-from-Nháp cũ . Verify: `dotnet build` clean 0 err 2 warn pre-existing DocxRenderer . `dotnet test SolutionErp.slnx` 104 PASS ( 58 Domain + 46 Infra , 3 deleted + 3 added cancel out , baseline preserved ). 3 Approver F2 tests verified individually PASS . Diff + 175 / -92 LOC trên 1 file . Token ~ 14k .
- ** 2026-05-14 ( S23 t1 , K5 Chunk D PASS ) : ** Cleanup zombie F2 endpoint + UsersPage column + DTO field + stale narrative comments ( Reviewer Major #1 + Major #2 + Minor #3 + Minor #4 ). Pattern post-refactor full cleanup atomic 1 commit . BE 7 file ( UsersController . cs DELETE PATCH / allow-skip-final endpoint + SetAllowDrafterSkipToFinalBody record ; UserFeatures . cs DELETE UserDto field + SetUserAllowDrafterSkipToFinalCommand + Handler + sentinel-false mappings cleanup ; ApprovalWorkflow . cs REWRITE stale narrative line 78-80 Mig 31 semantic + docstring line 108 ; PurchaseEvaluationFeatures . cs REWRITE Command DTO comment line 401 ; ApprovalWorkflowConfiguration . cs APPEND Mig 31 narrative line 22-24 + clean storage move comment line 87 ; ApprovalWorkflowV2AdminFeatures . cs clean DTO comment line 58 ; IPurchaseEvaluationWorkflowService . cs + PurchaseEvaluationDtos . cs clean stale " storage Users . AllowDrafterSkipToFinal " references ) + FE Admin 2 file ( UsersPage . tsx DELETE " Skip cuối " column TableHeader / TableCell + FastForward import + allowSkipMut mutation hook + FastForward toggle button ; types / users . ts DELETE allowDrafterSkipToFinal field ). fe-user KHÔNG đụng ( no UsersPage admin-only + K6 sẽ handle Workspace Drafter checkbox ), FE Designer page KHÔNG đụng ( K3 done — 2 stale comment line 75 + 504 leftover deferred K6 ). Grep `AllowDrafterSkipToFinal` + `allow-skip-final` + `allowDrafterSkipToFinal` + `Skip cuối` + `FastForward` ZERO results across src / Backend ( excl migrations ) + fe-admin / src . Build BE production projects clean ( 0 err , 2 pre-existing DocxRenderer warn ). Build fe-admin clean ( 0 TS err , 0 new warn ). Diff + 42 / -94 LOC trên 9 file . Token ~ 12k . K6 Workspace Drafter checkbox cleanup next .
- ** 2026-05-14 ( S23 t1 , K5 Chunk D PASS ) : ** Cleanup zombie F2 endpoint + UsersPage column + DTO field + stale narrative comments ( Reviewer Major #1 + Major #2 + Minor #3 + Minor #4 ). Pattern post-refactor full cleanup atomic 1 commit . BE 7 file ( UsersController . cs DELETE PATCH / allow-skip-final endpoint + SetAllowDrafterSkipToFinalBody record ; UserFeatures . cs DELETE UserDto field + SetUserAllowDrafterSkipToFinalCommand + Handler + sentinel-false mappings cleanup ; ApprovalWorkflow . cs REWRITE stale narrative line 78-80 Mig 31 semantic + docstring line 108 ; PurchaseEvaluationFeatures . cs REWRITE Command DTO comment line 401 ; ApprovalWorkflowConfiguration . cs APPEND Mig 31 narrative line 22-24 + clean storage move comment line 87 ; ApprovalWorkflowV2AdminFeatures . cs clean DTO comment line 58 ; IPurchaseEvaluationWorkflowService . cs + PurchaseEvaluationDtos . cs clean stale " storage Users . AllowDrafterSkipToFinal " references ) + FE Admin 2 file ( UsersPage . tsx DELETE " Skip cuối " column TableHeader / TableCell + FastForward import + allowSkipMut mutation hook + FastForward toggle button ; types / users . ts DELETE allowDrafterSkipToFinal field ). fe-user KHÔNG đụng ( no UsersPage admin-only + K6 sẽ handle Workspace Drafter checkbox ), FE Designer page KHÔNG đụng ( K3 done — 2 stale comment line 75 + 504 leftover deferred K6 ). Grep `AllowDrafterSkipToFinal` + `allow-skip-final` + `allowDrafterSkipToFinal` + `Skip cuối` + `FastForward` ZERO results across src / Backend ( excl migrations ) + fe-admin / src . Build BE production projects clean ( 0 err , 2 pre-existing DocxRenderer warn ). Build fe-admin clean ( 0 TS err , 0 new warn ). Diff + 42 / -94 LOC trên 9 file . Token ~ 12k . K6 Workspace Drafter checkbox cleanup next .
- ** 2026-05-14 ( S23 t1 , K3 Chunk C PASS ) : ** FE Admin Designer 7th checkbox AllowApproverSkipToFinal + banner rewrite . Pattern Mig 29 / 30 admin opt-in per-slot mirror **reinforced 3× ** cumulative ( Mig 29 F1 + F3 5 checkbox + Mig 30 F4 1 checkbox + Mig 31 F2-refactor 1 checkbox = 7 checkbox total per slot ). Cookie-cutter 1 file fe-admin only ( `ApprovalWorkflowsV2Page.tsx` , fe-user no Designer per Investigator K0 S1 ). 7 sub-items atomic: ( 1 ) LevelDto type + `allowApproverSkipToFinal: boolean` , ( 2 ) EditLevelEntry type + same , ( 3 ) `makeDefaultLevelEntry` default false , ( 4 ) `copyFromDefinition` propagate `?? false` , ( 5 ) inline checkbox row position **cuối list** sau F4 AllowApproverEditBudget logical grouping ( Edit Section 2 → Edit Budget → Skip to Final ), ( 6 ) banner rewrite line ~ 623 từ " F2 cấu hình ở User Management " ( Plan D S22 stale ) → " Cấu hình quyền duyệt riêng cho từng NV trong slot Approver bên dưới ( Trả lại / Edit Section 2 / Edit Budget / Duyệt thẳng Cấp cuối )", ( 7 ) POST / PATCH mutation body `levels.map` + allowApproverSkipToFinal . Verify: `npm run build` fe-admin PASS clean 0 TS error , 0 new warning . Bundle 1395 . 74 KB ( unchanged trivial vs baseline ). Diff + 26 / -7 LOC . Token ~ 6k . K5 next chunk cleanup zombie endpoint + UsersPage column .
- ** 2026-05-14 ( S23 t1 , K3 Chunk C PASS ) : ** FE Admin Designer 7th checkbox AllowApproverSkipToFinal + banner rewrite . Pattern Mig 29 / 30 admin opt-in per-slot mirror **reinforced 3× ** cumulative ( Mig 29 F1 + F3 5 checkbox + Mig 30 F4 1 checkbox + Mig 31 F2-refactor 1 checkbox = 7 checkbox total per slot ). Cookie-cutter 1 file fe-admin only ( `ApprovalWorkflowsV2Page.tsx` , fe-user no Designer per Investigator K0 S1 ). 7 sub-items atomic: ( 1 ) LevelDto type + `allowApproverSkipToFinal: boolean` , ( 2 ) EditLevelEntry type + same , ( 3 ) `makeDefaultLevelEntry` default false , ( 4 ) `copyFromDefinition` propagate `?? false` , ( 5 ) inline checkbox row position **cuối list** sau F4 AllowApproverEditBudget logical grouping ( Edit Section 2 → Edit Budget → Skip to Final ), ( 6 ) banner rewrite line ~ 623 từ " F2 cấu hình ở User Management " ( Plan D S22 stale ) → " Cấu hình quyền duyệt riêng cho từng NV trong slot Approver bên dưới ( Trả lại / Edit Section 2 / Edit Budget / Duyệt thẳng Cấp cuối )", ( 7 ) POST / PATCH mutation body `levels.map` + allowApproverSkipToFinal . Verify: `npm run build` fe-admin PASS clean 0 TS error , 0 new warning . Bundle 1395 . 74 KB ( unchanged trivial vs baseline ). Diff + 26 / -7 LOC . Token ~ 6k . K5 next chunk cleanup zombie endpoint + UsersPage column .