diff --git a/.claude/agents/ctx-audit.md b/.claude/agents/ctx-audit.md index 46e379c..b5d04db 100644 --- a/.claude/agents/ctx-audit.md +++ b/.claude/agents/ctx-audit.md @@ -65,7 +65,7 @@ Input BẮT BUỘC do lead pin: (a) path `_mind-s-.md` · (b) path run-folder ### (iv) @close — bất-biến chuỗi (TỰ tái-dựng số, KHÔNG tin lời khai) -- 🔴 **Tự đếm ĐĨA:** `p` = số tệp `_pause-*.md` **+** `pause-*.md` trong session-dir (dual-accept, mirror ORPHAN-L). Kỳ vọng `|block| ∈ {p, p+1}`. So số mày đếm với số máy in — **lệch ⇒ in CẢ HAI số + TRƯỢT**. +- 🔴 **Tự đếm ĐĨA:** `p` = số tệp `_pause-*.md` **+** `pause-*.md` trong session-dir (dual-accept, mirror ORPHAN-L). Kỳ vọng `|block| ∈ [p, p+3]` — khớp máy `mind-check` phép (6): block-0 + p refresh-pause + tối đa 2 refresh-bookend (refresh-bookend là nhịp HỢP-LỆ @S162). *(Bản cũ ghi `{p, p+1}` = SAI so máy — chính vai khai @S162 + @S169, vá @S170.)* So số mày đếm với số máy in — **lệch ⇒ in CẢ HAI số + TRƯỢT**. - 🔴 Dòng tự-khai `markers:` / `mind-blocks=` trong `_end` **CHỈ để cross-check**, KHÔNG BAO GIỜ là nguồn đếm. **Đĩa thắng**; lệch tự-khai vs đĩa = cờ-INFO (đúng thứ khai-THIẾU mà thư đo được). ### (v) @close — chấm mồi-ngầm + thách-CLEAN diff --git a/.claude/agents/investigator-codebase.md b/.claude/agents/investigator-codebase.md index c8b8a14..8485740 100644 --- a/.claude/agents/investigator-codebase.md +++ b/.claude/agents/investigator-codebase.md @@ -78,7 +78,7 @@ ssh vietreport-vps "powershell -Command \"sqlcmd -S '.\SQLEXPRESS' -d SolutionEr ### EF migration diff - `ls Migrations/*.cs` vs prod `__EFMigrationsHistory` drift check - Mig 3-file rule verify (Up/Down + Designer + Snapshot) -- 40 migration hiện tại (Mig 34-40 Phase 10 G-* port) +- Số migration hiện tại → `docs/STATUS.md` dòng CURRENT (canonical — B1, KHÔNG neo số ở persona; bản cũ neo "40" đã stale tới 71, lead-stale FLAG @S169) ### Reference implementation mirror PE module flagship V2 → reference cho Contract V2 / Proposal V2 mirror. Grep `ApproveV2Async` / `LevelOpinion` / `ApplicableType` cross-module pattern. Pattern 12-bis 12× cumulative. diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index d6ed391..93284f5 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -8,7 +8,7 @@ **(64) 🔴 Gắn 2 user TEST vào quy trình duyệt qua Designer — CHỈ ANH LÀM ĐƯỢC** ((54)-FINAL anh chốt *"nếu điều chỉnh, tao sẽ tự tay"*). `TEST Người duyệt` (`test.approver@solutions.com.vn`) hiện có role CostControl+DeptManager nên **thấy** màn duyệt nhưng **không nằm trong trạm nào** ⇒ chưa bấm duyệt thật được. Bộ user test: **`ADMIN_TEST`** (`admin_test@…`, Admin) · `test.drafter@…` (Drafter+Procurement) · `test.approver@…` — **password chung `Test@12345678`** (policy prod ≥12 ký tự). Anh muốn em đổi mật khẩu sau buổi thử thì nói 1 câu. -**(65) 🔴 Nhắn team bỏ qua notification ZZTEST — HẠN HÔM NAY.** Dry-run + bộ fx3 đã bắn thông báo tới roster THẬT (11 người `KHKK-N4` + trạm HĐ) trong khung 16:12→19:38. Mọi bản ghi mang tiền tố **ZZTEST/TEST**. Em **không có kênh Zalo/email** (khai từ B0.iv) ⇒ việc này chỉ anh làm. +**(65) 🔴 Nhắn team bỏ qua notification ZZTEST — hạn **2026-08-01**, ĐÃ QUÁ HẠN 2 ngày (phát-hiện @S170 `/tiep` 2026-08-03; bản cũ ghi "HẠN HÔM NAY" = neo tương-đối tự-phá sau nửa đêm — ctx-verifier cờ ⑩).** Dry-run + bộ fx3 đã bắn thông báo tới roster THẬT (11 người `KHKK-N4` + trạm HĐ) trong khung 16:12→19:38 ngày 01/08. Mọi bản ghi mang tiền tố **ZZTEST/TEST**. Em **không có kênh Zalo/email** (khai từ B0.iv) ⇒ việc này chỉ anh làm. **(66) Dọn HĐ ZZTEST trên prod — chờ anh gật.** 2 HĐ `ZZTEST-K8/…/01` + `ZZTEST-K8-2/…/01` đều **DaPhatHanh** ⇒ guard numeric chặn xóa qua API (HỐ-1). Lối thoát = `sqlcmd` soft-delete + NULL lại `Line.ContractId`/`pe.ContractId`, lệnh sẵn ở `sub-k8-dryrun.md` §B15. Backup pre-K8 27,8 MB đã có (`C:\Backups\SolutionErp\SolutionErp_preK8_S168.bak`). Giữ nguyên cũng được (có tiền tố, không lẫn HĐ thật) — **anh chọn**. @@ -107,8 +107,8 @@ 🔴 **Vì sao slot này nguy hiểm hơn một con số sai:** nó xin anh tiêu một **quyết định owner** (nâng khoá `mind_ctx_kb` / vá luật nén) dựa trên số đo của một artifact đã chết. Quyết-định của owner là tài-nguyên hiếm; báo-động-giả tiêu mất một lượt. Class = **tham-chiếu trượt khi L7 `_end` và L8 mở, sổ owner không đi theo**. 🔸 **Giữ phần CÒN ĐÚNG (không vứt cả cụm):** mối lo NỀN là thật — `ctx-verifier` dự báo tường này từ **S156**, và L8 sẽ lớn dần. Cái bị bác là **BỘ SỐ + tính khẩn "cửa kế tiếp"**, không phải câu hỏi thiết kế. Khi `_mind-s-8` thật sự tới ~90% thì mở lại slot mới, đo trên file SỐNG. **(46)** 🔴 **Thước "17,1K" là thước MA — chọn 1 trong 3 ngã** (`harness-refine` A1, nó **cố ý không đặt số** vì số là quyền anh): **(i) WIRE** thêm key `tiers.l1_hot.self_target_bytes` để máy soi được · **(ii) RETIRE** gỡ luật khỏi 5 diary vì thước thật là 25.600 · **(iii) RELABEL** giữ nhưng ghi rõ "advisory". Bằng chứng nó **đang tốn công thật**: `investigator-codebase:58` nén về ~17,1K @S155, **3 ngày sau 20.646 B lại**; áp thước này thì **9/23 vai vượt** trong khi mọi máy in "0 over". -**(47)** `cicd-monitor/archive/_INDEX.md` **19.484/20.480 = 95,14%**, tăng ~81 B/ngày ⇒ **chạm cap ~2026-08-09**. A1@S153 chưa land, `harness-refine` đã kích chốt-dừng ⇒ lead {thi-hành nguyên văn | HỦY ghi rõ}; nếu chọn **nâng cap 20.480** thì là quyền anh. -**(48)** `harvest-curator/MEMORY.md` **19.456 B = 0 byte đổi kể từ S154**; món nợ **tự khai 2 lần** (budget `:192` từ S107 · diary `:5` từ S153) chưa trả lần nào — 3 lối ra đều là số/nhịp của anh. +**(47)** `cicd-monitor/archive/_INDEX.md` — 🔄 **THƯỚC TƯƠI @S169/S170: 47,3% (9.682/20.480) sau rotate `_INDEX-2026-H1.md` @01-08 — HẾT ÁP LỰC, KHÔNG còn hạn 08-09**. *(Số cũ 95,14%/chạm-cap-08-09 = đo trước rotate — ctx-audit @open S169 bắt anh đang được mời quyết trên thước chết, vá @S170.)* Câu hỏi cho anh GIỮ nhưng hết khẩn: nâng cap / giữ nguyên? +**(48)** `harvest-curator/MEMORY.md` — 🔄 **THƯỚC TƯƠI @S164: 18.781 B, ĐÃ trả −4.712 B (không còn "0 byte đổi")**. *(Bản cũ "19.456 = 0 đổi kể từ S154" chết theo S164 — cùng đợt vá ctx-audit.)* Món nợ tự-khai 2 lần: trạng-thái mới cho thấy vai ĐÃ tự-compact — anh còn muốn đặt nhịp riêng thì cho số, không thì đóng slot. 🔸 **Không chặn W1-W2:** 5 câu thiết kế spec KHKK (Q3 · Q6 · Q11 + O-Q1 · O-Q2) · nguồn thứ 4 `SOL-PRO-SP-001` chưa ai đọc · 2 đường kết thúc sớm W3: `AllowApproverFinalize` **ĐÃ PORT @K3 S165** (OG-9 đảo "PHÁ VỠ" @S155 — owner @S164 verbatim *"chỗ budget chốt chặn là a Chương… bài toán trần budget xem như đóng"*; ⚠️ **gate-K3 F-1 MAJOR — checkbox opt-out màn duyệt CHƯA có UI, đầu việc #1 lần sau**: hiện `?? true` ⇒ MỌI lượt anh Chương bấm Duyệt đều KẾT THÚC phiếu — muốn phiếu lên CEO tạm thời chỉ có cách admin BỎ cờ ở Designer trước; vá = mirror checkbox `PeWorkflowPanel.tsx:778` vào KhkkWorkflowPanel ×2 + DTO expose cờ level) · `CeoApprovalThreshold` KHÔNG BAO GIỜ port (OG-3 human-gate vĩnh viễn) · thứ tự chạy wave. 🔸 **Treo CÓ CHỦ ĐÍCH, không phải quên:** lỗ hổng an ninh HĐ (`ContractWorkflowService.cs:48-66` Reject-trước-guard + controller class-trần) — anh chốt *"chỗ hợp đồng cứ từ từ"*. **Wave 5 chạm HĐ ⇒ phải hỏi lại anh trước khi chạy.** diff --git a/docs/STATUS.md b/docs/STATUS.md index 2000ffd..b8bc47b 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -471,7 +471,7 @@ monthly re-tier mega-line + ef-core SKILL Mig→59 + 3 vocab-fork (2026-07-01 du | Menu keys | **113** | 🔄 **113 @S166 K4a** (đo RUNTIME `MenuKeys.All` — test T2; +49 `Khkk_G{2-8}`+42-leaf bộ-sinh by-construction K4a · +8 `AwV2_KhkkN1..N8` K3 · +1 `ContractCatalog` K1 trên nền 55). Cũ: **+1 S161 `KeHoachKyKet` vào `All` (W1 KHKK — policy `KeHoachKyKet.*` sinh runtime; menu-row prod KHÔNG đổi, 142 giữ)** · +1 S69 `Off_Dashboard` (landing Văn phòng số). Prev re-ground S61 (`MenuKeys.cs` const — Mig 50 gỡ 4 `Bg_*` Budget menu cũ). Prev 57 (S58) | | Tests | **644 PASS** | 45 Domain + 599 Infra · 🔄 **644 @S168 #444** (+5 Fact Lines-editor) · 🧊 **639 @S168-sáng** (đo tươi local 45D+594I sau K7 Δ+17; chuỗi K lineage: 597 K1 → 614 K3 → 622 K4c @S167 KHỚP CI #439 tách-phần → **639** K7 — gate `639=45+594` KHỚP cicd-K7 dòng-1) · 🧊 **+28 @S161** (5 wave KHKK: W1 566 → W2 574 → W3 580 → W6 587 → W7 590; đo tươi @S162 `dotnet test` 45+545, gate CI Run #432 khớp). ~~45 Domain + 517 Infra~~ · 0 fail / 0 skip · **S155 +30** (PE xóa-by-approver: `PeDeleteByApproverTests.cs` + T26/T27 — 🔴 **T27 khoá CẢ LỚP lỗi** *entity-có-cờ-mà-DTO-không-có* bằng reflection [mọi cờ `Allow*` trên entity phải có mặt trên DTO], **fault-inject xác nhận có răng**: tiêm bug ⇒ ĐỎ, khôi phục ⇒ xanh — không phải guard tuyên-bố suông; T26 giữ ĐỎ có chủ ý vì bug production thật, lead vá bằng đảo thứ tự chứ KHÔNG nới assert. Số 562 cross-check 2 nguồn độc-lập: log CI run #417 + `dotnet test` local @S156) · **S147 +4** (`ProjectCodeNormalizationTests` — Trim khi lưu + kiểm-trùng bỏ-dấu-cách; 🔴 **ô canonical này STALE 528/483I suốt S147→S148**, header `:6` và session-log S147 đều ghi 532/487I từ đầu — closeout S147 vá header mà quên ô canonical; H24 `lead-view-auditor` bắt @S148, lead verify 3-nguồn rồi vá) · **S134 +8** (`PePendingAccumulationTests` C1-C8 lũy-kế-TẠM-TÍNH: C1 ChoDuyet+winner vào delta-selected + PriorPes · C2 TuChoi/DaDuyet loại sạch · C3 Nháp list-only KHÔNG cộng tiền [D1] + TraLai vào delta-submitted [D2] · C4 peer-window CreatedAt · C5 delta âm signed · **C6 complementary-no-double-count exact-numbers [ComputeAsync bất động khi thêm peer non-terminal]** · C7 frozen→pending 0/null · C8 D4 changelog `[S134 pending-prior]` positive+contrast) · **S133 +11** (`PeBudgetFreezeTests` freeze-NS-at-DaDuyet: **T0 repro test-before RED→GREEN** [phiếu DaDuyet phải giữ số cũ sau `UpdatePeBudgetPro` — RED bắt 999tr @:184 pre-fix, phiếu đưa tới DaDuyet QUA service finalize mirror `PeApproverFinalizeTests` KHÔNG seed thẳng Phase] + **T1-T9** spec-coverage [snapshot các nhánh finalize + display-gate + 2 terminal-guard chặn sửa NS phiếu đã kết thúc (cả Admin) + backfill] + **site-5 AdminOverride** [reviewer catch — override thẳng → DaDuyet cũng chốt snapshot]) · **S118 +8** (PRO-perm scope-isolation **+4** `ProcurementMasterAccessSeedTests` [reflection no-prod-touch: upgrade-path Suppliers R+C+U + Master-Read · **scope-isolation** DeptManager-riêng vẫn revoke=false · insert-path no-Delete · idempotent] · ReportsController authz **+4** `AuthorizePolicyRegressionTests` [dashboard/export require Reports.Read · my-dashboard KHÔNG action-policy · class-level [Authorize] intact]) · **S117 +6** (PE endsBeforeCeo pointer-aware **+1** `PeFinalizeProjectionTests.ListPe_EndsBeforeCeo_ChoDuyet_PointerAware_PastFinalizeIsFalse` [ChoDuyet con-trỏ QUA cấp finalize → endsBeforeCeo=false, test-before RED→GREEN + EF-subquery translate smoke] · duyệt-theo-khoảng ProMinMax **+5** `PeApprovedPriceFinalizeTests` [happy set Min+Max · min==max boundary lock strict-`>` · thiếu-Max→Conflict not-finalized · min>max→Conflict · single-source+Max→Conflict wire-bug + regression Max=null] · harness `InvokeApply` 4→5 args fix TargetParameterCountException) · **S116 +9** (PE nhập giá âm: T1 ngân-sách-bất-biến khi quote-âm · T2 winnerQuoteTotal signed-sum · T3 submit-guard all-zero-blocked/pure-neg+net-zero-submittable · T4 CCM-net-threshold) · **S114 +9** (PE multi-NCC per hạng mục: `PeSelectWinnerClearTests` delete-invariant +4 [DeleteQuote/DeleteDetail re-derive IsWinner **test-before RED→GREEN** + guard-no-over-clear + UpsertQuote-update-branch coverage] + impl-lane +5 [per-hạng-mục-total · giaTri-single-partial · threshold-crossing · derive-invariant]) · **S113 +19** (Supplier import v2: `SupplierImportV2DedupTests` 13 [dedup MST-primary+Code-backstop T1-T7 · draft-on-import IsPublic · all-or-nothing · LayoutValid re-bake real-token · **null-Code→nháp FIXED** flipped-from-characterization] + `SupplierPublishAndListTests` 6 [publish-guard Code-required→409 · unpublish · list-filter published · DTO IsPublic]) · **S112 +18** (Supplier `SupplierExcelImportServiceTests` +10 [case-collation dedup có-RĂNG SQLite-BINARY-collation-nên-chứng-dedup-ở-SERVICE · fill-nulls-safe · all-or-nothing-abort · parser abs-cell-index/#REF!-null/header-fingerprint · Type-lạ→NCC · Status-emoji-strip] · PE `PeSubmitGuardAndBypassTests` 4-update→A1 [minOwn subordinate-only, pointer-stop] + 8-new [A1-happy · non-contiguous · EDGE-5 non-admin-throw/admin-pass/system-pass · opinion-history log/none]) · Prev 440: **S96 +6** (PE `PeApproverFinalizeTests` +2 [#6 finalize-opt-out→advance-CEO · #7 stale-noti-clear ExecuteUpdate] · `PeSuggestedPriceSetterAuthzTests` +4 [price-lock phase-guard after-submit — PRO/CCM ChoDuyet/DaDuyet→Conflict, Admin-override; +sửa SeedPeAsync default ChoDuyet→DangSoanThao spec-change]) · **S92 +3** (`AdminOnlyModulesRevokeTests` ẩn 5 nhóm menu chỉ Admin — non-Admin revoked-4-cờ / Admin untouched / Pe_* preserved) · **S91 +9** (ChangePassword self-service BE+test) · **S89 +3** (`PeDraftVisibilityTests` IDOR nháp riêng-tư) · **S88 +17** (D1 financials/CEO-notify/HoSoLink null-safe +11 · D2 create-contract multi-winner +6) · **S87 +25** (Mig 58 net +18: `PeMultiWinnerTests` sum + `PeSelectWinnerClearTests` multi-update + `PeSubmitGuardAndBypass` budget=0 + `PeApproverFinalizeTests` 5 auto-finalize [từng 7, −2 khi opt-in→auto rework] + `PeCcmThresholdFinalize`/`PeWorkItemBudget` collateral; Mig 59 +7 `PeCcmBudgetPeriodSetterAuthzTests` role-gate Admin|CCM/budget=0/null-clear) · **S86 +3** (`PeApproverNotifyExcludesDrafterTests` — notify "cần duyệt" loại NGƯỜI TẠO phiếu: drafter-excluded · co-approver-vẫn-nhận · drafter-vẫn-nhận-chuông-kết-quả) · **S85 +18** (PE CV PRO C5 hủy/đổi NCC winner +10 · urgent drafter-self-unset +5 · workflow-preserve bug-class S42 +3 `PeUpdateDraftWorkflowPreserveTests`) · **S83 +2** (PE require-workflow: `PeWorkItemGuardTests` ApprovalWorkflowId `NotEmpty` ×2 validator + submit-guard rewrite test 7/13 `PeSubmitGuardAndBypass` V1-submit-deprecated, no-count-change) · **S77 +10** (+7 `PeSuggestedPriceSetterAuthzTests` ghi chú PRO/CCM Mig 57 absolute-set/role-gate/null-clear/max-1000 · +3 `PeUrgentToggleAuthzTests` rewrite cờ-gấp **BẤT ĐỐI XỨNG** SET=function role / UNSET=function+DeptManager, plain-PRO-unset Forbidden) · **S76 +5** (`PeWorkItemBudgetTests` PRO split: set ProInitial+ProAdjust gồm âm · validator ProInitial≥0/ProAdjust-cho-âm · full=proFull khi CCM empty · full=CCM khi CCM present) · **S74 +5** (`PeWorkItemBudgetTests` §4b CcmNote: set CCM/Admin · null-clear absolute-set · non-priv Forbidden+no-mutate · all-3-persist) · **S73 +28** (PE opt-in finalize spec 6→11 + 10 giá-chốt `PeApprovedPriceFinalizeTests` + 13 setter-authz `PeSuggestedPriceSetterAuthzTests`) · **S69 +20** (Office-golive OfficeModulePermissionSeed 6 + PE PeCcmThresholdFinalize 5 + PeUrgentToggleAuthz 9) · **S67 +23 HRM test-after** (DepartmentTreeTests 8 cycle-guard/rollup + PeHoSoLinkTests 9 absolute-set + HrmProfilePermissionSeedTests 6 reflection-seed) → 286 · S61 +22 `PeWorkItemBudgetTests` −14 `BudgetPolicyTests` −1 → 263 · S60 +14 `PeSubmitGuardAndBypassTests` +2 spec → 256 (Domain 58→45 do drop Budget module tests) | | Gotchas | **86** | **+S168 #86** (2-push-sát → Gitea auto-CANCEL run đầu cùng-branch: CANCELLED ≠ fail — verifier đọc run CUỐI của range + bằng-chứng artifact-level; side-effect @startup chỉ 1-startup cho cả cụm push; ca thật `aaed699` ship qua #442) · **+S162 #85** (menu-key OR-gate FE ≠ policy per-action BE: cây 4-folder GĐ gate `['Khkk_List','Khkk_G1','KeHoachKyKet'].some(can)` NHƯNG endpoint gắn `[Authorize(Policy="KeHoachKyKet.Read")]` [`ContractSigningPlansController.cs:36`] + `MenuPermissionHandler.cs:40` so khớp **CHÍNH XÁC 1 key** — KHÔNG kế-thừa cha, KHÔNG OR key con ⇒ role `Khkk_List=1 ∧ KeHoachKyKet=0`: FE mở cổng → API **403** → folder GĐ2 hiện "—" dưới **MỌI** gói thầu, claim "gate trước fetch ⇒ 0 rác 403" **vỡ**. Bẫy: luật "OR nhiều key" **ĐÚNG ở tầng HIỂN-THỊ** [`GetMyMenuTreeQuery.cs:61-96` trả node khi con `CanRead`] nhưng **SAI ở tầng API-authz** — mặt thứ 2 của #82, lần này **menu-hiện RỘNG hơn API-cho** [#82 là chiều ngược]. Fix = gate đúng key policy CỦA endpoint; **mở controller đọc attribute TRƯỚC khi wire gate**, đừng suy từ cây menu. Reviewer bắt **trước ship**; Dev 13/13 role đều `Contracts=1 ∧ KeHoachKyKet=1` nên **chưa lộ** — lớp "chưa vỡ vì dữ-liệu hiện tại may mắn", vá ngay không đợi triệu chứng). **+S159 #84** (revoker-2-chiều: sửa data tay trên prod bị code-path ungated @restart ĐẢO NGƯỢC im lặng — grant menu SQL tay bị revoker [S92] lật 447/494 row; fix = code-first seeder + gỡ nhánh + guard 2-vế + khuôn 3-chân-kiềng; liên-quan #75/#76 chiều seeder). **+S133 #81-EXT** (instance 2 indirect-assignment, KHÔNG số mới: snapshot-NS-at-DaDuyet hook đặt ở finalize choke-point NHƯNG 2 site gán Phase TRỰC TIẾP bypass — admin-override `PurchaseEvaluationWorkflowService.cs:308` `= targetPhase` + seeder `DbInitializer:1323` `= current` → phiếu vào DaDuyet qua 2 đường này KHÔNG snapshot [frozen=0, display rơi về live = đúng bug đang vá]; reviewer adversarial bắt pre-commit, em-main + 3 invocation implement đều sót — cùng bài enumeration-writer #81; meta: field-đích có hook/derive/snapshot ⇒ grep MỌI assignment-site kể cả override/seeder). +1 S126 (**#83** số AGGREGATE session-cumulative tự-lão-hoá — audit COUNTS đổi bởi CHÍNH spawn review sau đó [2/2/0→4/4/0]; outward mời-reproduce = bảng per-lane theo run-id, KHÔNG số tổng; reviewer-gate bắt, em-main-solo sót). +1 S118 (**#82** menu-flag grant ≠ quyền API thật: display-layer [Permission `CanRead`→`GetMyMenuTree` FE-menu] ⟂ API-authz-layer [controller `[Authorize(Policy=)]`] = 2 tầng ĐỘC-LẬP; grant `Suppliers` R+C+U cho PRO nhưng `PUT/DELETE /suppliers` gate `[Authorize(Roles="Admin,CatalogManager")]` → PRO vẫn 403 sửa/xóa NCC [chỉ Publish/Import theo `Suppliers.Update` là ăn]; ngược lại `ReportsController` `[Authorize]` trần → mọi authed-user đọc `dashboard` tài-chính-HĐ ngược S92; fix gate `[Authorize(Policy="Reports.Read")]` per-method + grep controller authz TRƯỚC khi tin hiệu-lực grant; reviewer adversarial bắt, em-main-solo tin menu-flag=quyền thì sót; liên-quan #44). +1 S114 (**#81** derived-invariant re-derive ở write/select NHƯNG SÓT DELETE writer [DeleteQuote/DeleteDetail cascade] → xóa quote-selected cuối của NCC → `Supplier.IsWinner` kẹt stale [Any(IsSelected)=false] → `CreateContract Where(IsWinner)` gom NCC phantom → **HĐ giaTri=0**; fix helper `PeWinnerInvariant.ReSyncAfterQuoteRemovalAsync` gọi sau SaveChanges 2 handler; **enumeration-writer-trong-spec KHÔNG đáng tin** → grep MỌI `.Remove(`/`.Add(`/`=field` chạm entity chứa field-nguồn; chỉ **verify-adversarial-refute** bắt [invest/review/implement đều sót]; cardinality S87/S88 lên tầng mutation-path). +1 S113 (**#80** null-forgiving `!` che NRE trên external-parsed data: `SupplierExcelImportService.NewSupplier` gán `Code = r.Code!.Trim()` → NullReferenceException khi parser trả `null` cho ô cột-4 rỗng [ĐÚNG path R4 "thiếu Mã NCC → nháp"] → confirm nổ 500 CẢ batch dù preview classify New-draft KHÔNG lỗi; sibling `IsPublic=!IsNullOrWhiteSpace(row.Code)` null-safe nhưng NewSupplier thì KHÔNG; empty-string `""` chạy OK nhưng FE round-trip blank→JSON `null` → nổ. Fix `(r.Code ?? "").Trim()`. **Build 0/0 KHÔNG bắt** [`!` tắt nullable-warning]; chỉ test-before-critical bắt. Lesson: `!` null-forgiving trên dữ-liệu-parse-ngoài = mìn, dùng `?? default`). +1 S97 (**#79** backfill soi NHẦM bảng — transition-marker "[Duyệt KẾT THÚC]" nằm ở `PurchaseEvaluationChangelogs.ContextNote` KHÔNG phải `PurchaseEvaluationApprovals` → Mig 60 backfill match 0, phiếu finalize-CCM giữ flag=0 hiện sai "Đã được CEO duyệt"; fix Mig 61 query đúng bảng. PE 2 bảng lịch-sử tách vai [Approvals=ai-duyệt record :745 · Changelogs=chuyển-phase+marker LogTransition :1073]; verify marker-count prod trước khi tin backfill). +1 S97 (**#78** display-flag suy CONFIG thay RUNTIME → nói dối khi instance lệch config: `endsBeforeCeo` từ "workflow CÓ cấp finalize" thay "phiếu NÀY finalize" → phiếu lên CEO báo sai "không qua CEO"; nặng sau S97 default-flip opt-in; fix field runtime `EndedByLevelFinalize` Mig 60. Flag = "instance ĐÃ làm-gì" KHÔNG "config CÓ THỂ"). +1 S96 (**#77** SPA deploy bundle cache-lag: team thấy UI CŨ dù đã deploy + Ctrl+F5 — index.html no-cache ĐÚNG-chuẩn + JS hash-immutable nhưng browser giữ tab-SPA-mở/cache-local → verify bundle prod **BYTE-LEVEL** (curl + grep string-fix trong `/assets/index-.js`) phân-biệt cache-vs-deploy; **incognito = golden-test**; no-service-worker nên clear-site-data đủ). +2 S91 (**#76** deploy render config từ `.example` KHÔNG phải file-gitignored → prod thiếu setting tới khi điền tay · **#75** seed ungated per-code RESURRECT data đã-wipe mỗi restart → gate sau env-flag `DemoSeed:Disabled` + verify-by-restart-thật). +1 S90 (**#74** Chrome-MCP screenshot kẹt SPA-SignalR `document_idle` → PowerShell `CopyFromScreen` + Win32 lọc-process-`chrome.exe`). +2 S85 (**#72** lệch giờ +7h — DateTime lưu UTC nhưng serialize thiếu 'Z' → FE `new Date()`=local → `UtcDateTimeJsonConverter` global ép UTC-with-Z · **#73** UpdateDraft absolute-set CLEAR field SÓT khỏi pattern null-safe = bug-class S42 → guard `if (request.X is not null)`). +1 S78 **#71** (thêm enum value vào entity DÙNG-CHUNG → pollute UI/guard phân-loại theo PROXY-predicate `supplierId===null` thay vì enum tường minh; file-khi-duyệt purpose=5 lẫn "Bảng so sánh" + false-pass submit-guard → grep mọi field-proxy predicate loại value mới + build-verify TỪNG app; em-main grep no-leak bắt trước deploy). +1 S76 **#70** (FE absolute-set echo field anh-em từ server-snapshot + `invalidate()` fire-and-forget → cửa-sổ stale-echo mất-dữ-liệu khi lưu 2 ô liên-tiếp; guard `useIsFetching` gate nút Lưu tới khi refetch land; reviewer workflow bắt, impl self-review sót). +1 S72 **#69** FE bundle-hash non-deterministic + `deploy.yml` rebuild-FE-unconditional → bundle rotate kể cả commit governance (SPA-fallback-200 trap; cicd Run #312). +2 S69: **#67** Tailwind v4 accent palette thiếu stop (teal/violet/amberx/greenx chỉ 50/100/500/600/700; dùng -300 → teal/violet rơi DEFAULT Tailwind sai-hệ, amberx/greenx drop hẳn — build PASS, phải soi dist CSS) · **#68** IDE TS diagnostic giữa background-agent/workflow = snapshot dở-dang (TS server bắn mỗi save), chỉ tin build SẠCH sau-cùng (2× session này: re-skin + PE-FE đều false-alarm). Prev +1 S68 **#66** Tailwind v4 rule element thô `h1-h4{color:#0b1220}` viết NGOÀI `@layer` thắng utility `text-white` → heading render đen; fix ĐIỂM `text-white!` (important, grep dist confirm), KHÔNG move `@layer` (load-bearing ~30+ heading toàn app). Prev +1 S65 **#65** build csproj con (vd `SolutionErp.Api.csproj`) ≠ `dotnet build SolutionErp.slnx` (gồm tests) → miss test-compile khi đổi chữ ký record command (CreateDepartmentCommand +ParentId) → CI CS7036 FAIL-gated Run #291 (deploy chặn, prod nguyên — test-gate làm đúng việc). Fix: build full slnx trước push BE signature-change. Prev +2 S61: **#63** EF scaffold tự sinh `RenameColumn` SAI-semantics khi drop+add cùng type (test xanh không bắt — SQLite EnsureCreated không replay migration) · **#64** `dotnet ef database update` áp Design-DB 0-rows ≠ Dev-DB → data-migrate `Sql()` chạy thật lần đầu trên prod. Prev +2 S59 (#61 sqlcmd `-f 65001` · #62 rename natural-key UPDATE trước deploy) | -| User memory | **31** | +S84 `feedback_derived_flush_execution` (derived→canonical flush = em-main execution KHÔNG gate user-confirm; monitor INFORM-only ≠ cần-anh-duyệt; chỉ ĐỔI-con-số/policy = quyền anh). +S79 `feedback_canonical_spec_over_broadcast` (adap pull canonical-command/§P đừng phỏng-theo broadcast + report-before-stamp dogfood + residual own-diary OK). +S75 `feedback_harness11_engine` (engine governance tự-bảo-trì + gotcha #30-via-Edit + multi-workflow-verify + git-add-specific lesson). re-ground S71 (H1 disk-count: 25 `feedback_*` + 3 `project_*`; STATUS "21" stale từ S64). +S71 `feedback_harness10_run_trace` (run-trace + 3 lesson). Prev +1 S64 `feedback_harness7_outward_writing_quality`; re-grounded S54 base 19 | +| User memory | **59** | 🔄 re-ground S170 — đếm đĩa 60 file `.claude/auto-memory/*.md` trừ 1 index `MEMORY.md` = 59 (số "31" stale từ S84; lead-stale FLAG @S169, ring2 verify, vá @S170 SAU khi ring chấm — đúng thứ-tự H24 §2(4) fire→chứng-kiến→vá). +S84 `feedback_derived_flush_execution` (derived→canonical flush = em-main execution KHÔNG gate user-confirm; monitor INFORM-only ≠ cần-anh-duyệt; chỉ ĐỔI-con-số/policy = quyền anh). +S79 `feedback_canonical_spec_over_broadcast` (adap pull canonical-command/§P đừng phỏng-theo broadcast + report-before-stamp dogfood + residual own-diary OK). +S75 `feedback_harness11_engine` (engine governance tự-bảo-trì + gotcha #30-via-Edit + multi-workflow-verify + git-add-specific lesson). re-ground S71 (H1 disk-count: 25 `feedback_*` + 3 `project_*`; STATUS "21" stale từ S64). +S71 `feedback_harness10_run_trace` (run-trace + 3 lesson). Prev +1 S64 `feedback_harness7_outward_writing_quality`; re-grounded S54 base 19 | | Skills | 6 | 3 domain + 3 ops | | Sub-agents | **23** | **+S153 bộ-ba vòng Ctx** (adopt thư `0df10df4` — 🔄 **OWNER-VETO @S153 hub-form 3-vai**: bản đầu (38)(a) 1-vai OWNER-DELEGATED→LEAD-DECIDED, **anh bác cùng ngày** chốt trực tiếp *"Build đủ 3 vai như hub"* qua AskUser = owner chốt THẬT cho quyết này; 🔄 **RENAME cùng phiên theo lệnh anh** *"đặt tên giống hub và sisters để dễ audit"* — tên khai-sinh `ctx-pause-check`/`ctx-reload` → **hub-form `ctx-curator`/`ctx-verifier`** [đo đĩa 3 nhà: hub = curator/verifier/audit · VIPIX = check/reload/chain · hub≠sister ⇒ SE theo HUB-form, tiền lệ rename S149 lead-*]): **`ctx-curator`** vai-1 KIỂM nháp @mỗi-`/pause` (carve-out `pause.md §1` mirror hub O-1(a)) · **`ctx-verifier`** vai-2 ĐỐI-CHIẾU+NẠP-LẠI @mỗi-`/tiep` (dòng `LEAD-PHAI-NHAC-LAI:` = bằng-chứng nội-dung) · **`ctx-audit`** vai-3 SOI-CHUỖI @2-bookend (kiểm-vết vai-1/2, hồi-tố = fallback phiên 1-cửa). Nấc: ctx-audit `file-land + registry-surfaced @S153` cho CẢ 3 vai ctx [🔄 vá @S153 FLAG-6: bản đầu chỉ cấp nấc này cho `ctx-audit` trong khi `hmw.js:42` + writeGuard + README `:27`/`:199`/`:200` chứng 2 vai mới ĐẠT CÙNG nấc — khai THIẾU vẫn là lệch] — spawn-probe ALIVE cả 3 = phiên sau restart T9; hmw VALID_ROLES 20→**23** + writeGuard :228/:235; ⚠️ **roster 23 > `hmw_width.cap` 20** ⇒ full-roster-sweep LOUD-skip 3 lane cuối — số cap = quyền anh, O-7 (câu (40) đang treo). **🔄 RENAME @S149 (anh ratify "OK đồng ý"): 5 vai đổi tên đồng-bộ sister — `tooling-harvest-audit`→`ring1-audit` · `h24-audit`→`ring2-audit` · `sleep-audit`→`ring4-audit` · `lead-view-auditor`→`lead-stale-auditor` · `lead-omission-auditor`→`lead-gap-auditor` (ring* = 2 sister TRÙNG tuyệt đối; lead-* = hub-form, VIPIX-form là prefix). Nấc **NÂNG @cùng-phiên: `registry-listed-in-session`** — harness list 5 tên MỚI + gỡ 5 tên CŨ NGAY TRONG PHIÊN S149 (không restart), **TRÁI phép đo S120/S121 no-hot-reload** (môi trường có thể đã đổi — đây là data-point ĐO ĐƯỢC, không suy). Spawn-probe vẫn CẦN để chứng instantiate (list ≠ spawn được — đúng 0.6b). Tên cũ trong narrative/runs/history = vết lịch-sử, CỐ Ý giữ.** **+S145 🔬 `ring1-audit` (18th sub — round-KIỂM vòng tooling/harvest, C4/C4b adap dot-11 khoản ① `harness-dong-du-vong:51`, owner-decision [2] TÁCH mỗi-vòng-1-con-KHÔNG-gộp). Vai-KIỂM ĐỘC-LẬP đọc OUTPUT H1 `tooling-auditor` (4-mặt freshness) + H2 `harvest-curator` (5-trục integrity), **KHÔNG re-chạy đo**: verdict per-claim ĐẠT/TRƯỢT + falsify ≥2 + **tự tái-dựng ≥1 số CÓ-THỂ-SAI** (đếm `.claude/agents/*.md` vs roster-count H1 · N-harvested/M-spawned) + **thách-CLEAN** (H1 PASS/H2 GATE-0 → mở 1 skill "fresh"+1 sub "harvested" xem thật). 🔴 no-self-exempt ≠ H1/H2 (m-3 S139). **AUTO fire-after-measure @session-end §L.b(g-bis)** — owner-chốt S145 KHÔNG consent-gate (KHÁC trio/H24), fail-safe NO-OP nếu H1/H2 không chạy phiên đó (CẤM ĐẠT-ảo); tuần-tự C4b (invocation SAU con-đo, mtime chứng). Propose-only, backstop = git-diff commit-gate (KHÔNG dựa thiếu-tool `[carry:tools-whitelist-no-teeth]`). `model: opus`+`effort: max`+`memory: project`+`maxTurns: 16`. **Vai #1/3 round-KIỂM** — `ring2-audit` (vòng soi-lead) + `ring4-audit` (vòng nén-ngủ) land dần incremental (§6 broadcast báo-nấc-per-vòng, owner S145). 🔴 **Nấc = executed-file / verified-pending-restart** — registry Agent-tool KHÔNG hot-reload (`agents/README` §Memory discipline — anchor không-số-dòng, vá cite-dòng-trống @S151 per H1 F-3), spawn-probe alive cần **restart CLI**; run-thử-thật @session-end phiên sau. Design-doc: `runs/2026-07-22-S144-adap-dot-11/C4-design-3-vai-kiem.md`.** **+S145 🔬 `ring2-audit` (19th sub — round-KIỂM vòng soi-lead H24, vai #2/3 C4/C4b). Đọc OUTPUT `lead-stale-auditor` + `lead-gap-auditor` (🔴 KIỂM 2 con-đo H24, **KHÔNG soi lead trực-tiếp**) → verdict per-FLAG + tự tái-dựng ≥1 số (flag-count · mở 1 FLAG đối-chứng source · `class_repeat` `.session-counter.json`) + **thách-CLEAN** (H24 báo ít/0 FLAG ⇒ tự soi 1 surface tìm FLAG sót — CLEAN "lead ổn" là ca nguy nhất, khớp H24 §2(1) phép-thử-nhanh). Verify vai H24 KHÔNG tự chế class ngoài enum ĐÓNG `flag_classes`. no-self-exempt ≠ lead-stale/lead-gap (m-3; tên mới @rename S149). AUTO wired `session-end §L.b(j)(ii-bis)` sau cặp H24; fail-safe NO-OP nếu H24 không chạy (nhịp/consent). `maxTurns: 16`.** **+S145 🔬 `ring4-audit` (20th sub — round-KIỂM vòng nén-ngủ, vai #3/3 C4/C4b). Đọc OUTPUT `/sleep-recovery-memory-l2` (`.gist.md` mới + Fidelity verdict + claim giảm-byte) → verdict per-claim + **tự ĐO LẠI byte** archive gốc vs gist (đối-chứng claim) + **thách-CLEAN** (Fidelity 5P/0F ⇒ mở 1 gist đối-chứng `.md` gốc xem có giữ 4-field load-bearing hay nén quá tay) + kiểm bất-biến gist-ADDITIVE (gốc byte-identical). no-self-exempt độc-lập lượt nén (m-3). AUTO wired `sleep-recovery-memory-l2.md Phase 4.5` sau nén; fail-safe NO-OP nếu 0 gist tươi. `maxTurns: 16`.** **+S141/S142 🧪🧭🧮 `harness-eval` + `harness-refine` + `harness-audit` (15th–17th sub — bộ-ba đồng-kiểm HỆ MEMORY, adopt AI_INFRA khuôn 5-câu `58e28bae` khối B, wave adap đợt-9/10; land S141 persona+seed+`hmw.js` VALID_ROLES 14→17, wiring nghi-thức S142 vòng-2 sau khi vòng-1 chết giữa chừng). Read-only INFORM-only propose-only, frontmatter **không khai Write/Edit** — 🔴 nhưng đo S143: **runtime VẪN cấp** (append cuối tool-list, 9/9 vai read-only; nhân-chứng `reviewer` đã Write+Edit thật) ⇒ đây là **tuyên-bố ý-định**, KHÔNG phải chặn-bằng-thiếu-tool; containment thật = single-writer + git-diff commit-gate · `model: opus`+`effort: max`+`memory: project`+`maxTurns: 18`. Trục = **CHÍNH HỆ MEMORY**, chạy **TUẦN TỰ** eval→refine→audit (🔴 CẤM `parallel()` — con KIỂM chạy song song sẽ chấm bản CŨ ⇒ verdict vô-nghĩa): `harness-eval` = con **ĐO** (chỉ trả số nguyên-văn từ instrument, CẤM số-từ-trí-nhớ) ⟂ `harness-refine` = con **ĐỀ-XUẤT** (4 lớp reinject/promote/archive/distill, bắt buộc có mục "đã cân-nhắc→BÁC") ⟂ `harness-audit` = con **KIỂM** (verdict ĐẠT/TRƯỢT per-claim + re-chạy ≥2 số load-bearing; PIN run-folder đích-danh, CẤM tự tìm "run mới nhất"). 🔴 **KHÔNG gộp** với H1 tooling-freshness / H2 harvest-integrity / H24 lead-surface / reviewer diff-code — 4 trục khác nhau. Nghi-thức 2-đầu-phiên **AUTO 1 vòng/phiên GIỮA 2 bookend** (`session-start §2.1.9(a)` canonical + `session-end §L.b(k)(i)` trỏ): owner chốt @S151 — em-main IN 1 dòng trạng-thái rồi CHẠY, KHÔNG chờ gật [🔄 vá @S153 FLAG-4 HIGH: ô này còn khai "consent-gated + anh gật mới chạy" sau khi owner (32) đã lật AUTO, và ngược chính `:466` cùng file; trio đã chạy THẬT 3 vòng S151/S152/S153]; skip → ghi vết WAL `trio: skipped S` (vết-2-lớp, chuỗi skip nhìn thấy được). Budget seed đo TƯƠI `measure-agent-memory.ps1`: eval 1547B · refine 1616B · audit 1513B (l2_*=0 = SEED-STATE đúng, chưa chạy lần nào). 🔸 **Nấc trung-thực = executed-file / verified-pending-restart** — 3 vai CHƯA spawn-probe lần nào (cần restart CLI + anh consent; KHÔNG được đọc thành verified-runtime).** **+S121 👁 `lead-stale-auditor` + `lead-gap-auditor` (13th+14th sub — H24 lead-self-audit, adopt broadcast `2026-07-14-Governance-harness-24`, anh chốt S119 `owner-decisions-15-07-2026`, land S121 wave-W2 `hmw.js` VALID_ROLES 12→14 CÙNG COMMIT roster+STATUS [R3-M2: lệch landing ⇒ C2/B3 flag mọi derived ghi "14" là stale-vs-12 ⇒ detector BÃO trên chính thay đổi của H24]). 2 monitor INFORM-only propose-only, cookie-cutter frontmatter monitor sẵn (`model: inherit` lúc-land [S124 re-pin → `opus`+`effort:max` cùng toàn roster] · `memory: project` · `maxTurns: 18` · 8 tool read-only, **NO Write/Edit**). Trục: `lead-stale-auditor` = **view LỆCH source** (5 class `view-*`) ⟂ `lead-gap-auditor` = **cái BỊ THIẾU** (6 class `gap-*` — +`gap-incident-unrecorded` @S143 owner-duyệt) — 🔴 **KHÔNG gộp** vào tooling-auditor(H1 tooling-freshness)/harvest-curator(H2 harvest-integrity): H24 §2(1) *"gộp là mất tiêu-điểm; cái ta cần là cặp mắt CHỈ dành cho lead"*. Class-flag = **enum ĐÓNG** `lead_self_audit.flag_classes` ở `.claude/agent-memory/memory-budget.json` (11 class = 5+6, vai CẤM tự chế — mở enum là quyền owner). Nhịp = `h24_cadence` cùng file (single-source H24 §2(3) — doc TRỎ key, KHÔNG chép số ⇒ 🔄 **đã GỠ digits `{6/15/3}` @S153** theo `ring2-audit` R-3: chép số ngay cạnh câu cấm-chép-số là **B1-copy** [số vẫn KHỚP canonical nên KHÔNG phải stale — F-6 chống vu-oan]; đọc số sống ở `memory-budget.json → h24_cadence`); 🔄 **HÌNH B @S149**: cặp soi-lead spawn **VÔ-ĐIỀU-KIỆN 2 bookend mỗi phiên** — `light_every` hạ thành **stats-only** (KHÔNG còn cổng bắn), `deep_every` GIỮ cổng nhịp [vá @S153 FLAG-5: ô này còn mô-tả bắn thuần-cadence; đối-chứng hành-vi = cặp chạy @counter 27 với light 1/6 CHƯA tới hạn]; counter `.claude/governance/.session-counter.json` (content-based `last_ticked_head`, KHÔNG blind-increment — hook `wal-flush.ps1` auto-commit `agent-memory/` mỗi turn sẽ làm hỏng đếm mù; đặt ngoài **4 path** hook CÓ CHỦ-ĐÍCH — *hook nới từ 3 lên 4 @S146 khi thêm `.claude/sessions/`; mệnh-đề "governance/ nằm ngoài" đã RE-VERIFY sau khi nới, vẫn đúng*). ✅ **verified-runtime S122** (spawn-probe toàn-roster-KHI-ĐÓ SỐNG post-restart — **N=14 tại thời-điểm S122**, chứng runtime, §Recently-Done S122; 🔸 +3 trio S141 CHƯA nằm trong phép đo này) **+ chạy THẬT S124** (dogfood 2-vai đầu-tiên, owner-triggered @counter 3) **+ S137** (light-audit consent OVERDUE 8/6 → 2 FLAG view-stale-status + 1 FLAG gap-decision-sunk). 🔸 Residual THẬT giữ: đường `hmw.js→agentType` cho 2 vai H24 chưa exercise (Agent-tool path đã chứng; workflow-path chưa) [S137 view-audit lật ⚠️→✅ khớp source, giữ residual]. 🔸 Từ-vựng "view"/"omission" chọn có chủ-đích tránh va-chạm: `governance-detectors.ps1:15` đã sở-hữu `derived-staleness`, và "GAP" quá-tải (`session-end` build-gap · `memory-selfimprove-audit.ps1` CRITERIA+GAP).** **+S107 📄 `office-document` (12th sub — Office document WRITE specialist: docx·xlsx·pptx·pdf + form-engine; floor OD1–OD10; VALID_ROLES hmw.js 9→10; anh giao trực tiếp S107 "Sub chính" Office; ✅ **verified-runtime S107 CÙNG PHIÊN** — registry hot-reload agent MỚI giữa phiên [S27 lesson thu hẹp còn EDIT-agent/command] + spawn-test PASS OD1/OD4/OD5 template thật, model self-report `claude-fable-5` [data-point #5 flip-8]; finding: 2 template `wwwroot/templates` 0-placeholder mẫu-blank).** **worker-tier-pin (owner-decision S124 2026-07-15 — thay all-inherit H8 S66, trước nữa two-tier H4; sub TOÀN-ROSTER pin cứng KHÔNG theo lead; H23-precedence ĐO S126: spawn-param THẮNG hard-pin ⇒ `/fable-real` SỐNG). Lead = **DEFAULT Opus 5 MAX** (thư `9c909007` @S149 (re-stamp 07-25 G-024a; pre `59ce1d0f`); **anh chốt ô canonical hiển-thị DEFAULT-fleet @S151** — *"cần gọi Fable tao chọn đầu mỗi phiên hoặc gọi bằng command fable-real"* ⇒ Fable = anh `/model` đầu phiên HOẶC per-invocation `/fable-real`; runtime thật = BƯỚC 0.6 probe mỗi phiên, KHÔNG ghi sổ mỗi flip — hết class stale-2-flip ring1 bắt @S150). 🧊 Lineage owner-choice/flip-chain FROZEN tới flip-8 (flip-9 S119 Opus-4.8 owner-choice + các lượt /model sau = per-session không enumerate, anti-churn S106):** em main Fable 5 (1M) Max (✅ **Fable RESTORED S98 2026-07-02** — lead self-report `claude-fable-5` + settings `claude-fable-5[1m]`; fallback-Opus H5 S62→S97 kết thúc, H5.6 hoàn tất) ⚠️ **S101 2026-07-03: runtime lead = Opus 4.8** (lead + 2 monitor + WF2 reviewer inherit đều self-report `claude-opus-4-8`; settings vẫn pin `claude-fable-5[1m]` → **Fable unavailable phiên này → H5-fallback tự-kích, revert-free, KHÔNG sửa frontmatter**; "Fable RESTORED S98" = point-in-time KHÔNG phải steady-state — inherit-chain resolve theo availability runtime; ✅ **S102 2026-07-06: Fable VỀ LẠI runtime** — lead + 2 monitor inherit self-report `claude-fable-5` → H5-fallback S101 kết thúc, pattern availability per-session xác nhận [S98 Fable → S101 Opus → S102 Fable → **S103 Opus** → **S104 Opus** (2026-07-06 Fable outage tiếp — S104 lead + 2 monitor spawn self-report `claude-opus-4-8` ×3, H5-fallback revert-free) → ✅ **S105 Fable** (2026-07-07 Fable VỀ lần 3 — lead + 2 monitor self-report `claude-fable-5` ×3, runtime-verified) → ⚠️ **S106 Opus** (2026-07-07 Fable outage lại — lead runtime self-report `claude-opus-4-8`, H5-fallback revert-free; flip-7) → ✅ **S107 Fable** (2026-07-10 Fable VỀ lần 4 — lead + 2 monitor self-report `claude-fable-5` ×3, runtime-verified; flip-8)], BƯỚC 0.6 probe mỗi phiên; per-session KHÔNG steady-state. 🔴 **[§Sub-agents = CANONICAL single-owner flip-chain — S106 gộp per anh-confirm; derived `agents/README §Architecture` · `session-start BƯỚC 0.6` · `session-end §commit-format` trỏ về đây [🔄 vá @S153 FLAG-1: 3 cite số-dòng cũ `:3`/`:37`/`:113` đo lại SAI cả 3 (đúng là `:5`/`:48`/`:315`) — vá bằng BỎ số theo luật đã áp @S151, không ĐỔI số], KHÔNG tự enumerate mỗi flip → chống churn 4-file/flip]**) · **TOÀN roster `model: opus` + `effort: max`** (worker-tier-pin S124; **A2 đo S126:** lane no-tier resolve `claude-opus-4-8` DÙ lead=Fable ⇒ pin ăn runtime, hết inherit-lead; số vai = cột giữa của chính row này — KHÔNG chép lại vào narrative, đó là cách row-14 và narrative-12 lệch nhau từ S121 tới S122; lineage: 7 demoted flip S66 → all-inherit S66–S123 [office-document S107 inherit-born] → pin S124) · effort Max. 10 product/quality + monitor INFORM-only (H1 · H2 · 2×H24 S121 · 3×trio-memory S141 · 3×round-KIỂM `ring1-audit`/`ring2-audit`/`ring4-audit` S145) — **liệt-kê NHÓM, số vai = cột giữa của chính row này**. Nấc H8 = **runtime-verified S98 (2026-07-02)** — spawn-test inherit-chain ×2 monitor self-report `claude-fable-5` (cả đội tự lên Fable khi lead restore, 0 sửa frontmatter — đúng thiết kế all-inherit). Prev two-tier H4 runtime-verified S57bis (spawn-test 2 chiều). | | RAG chunks | 🟢 **service UP** · 🔴 **SE index STALE** | 🔴 **TÁCH 2 TRỤC @S159 — 1 nhãn nhị-phân DOWN/alive che mất trục thứ hai.** ① **service-liveness = UP**: đo LIVE 2026-07-29 `list_projects` → **7/7 project chunk > 0** (`solution_erp` **2449** · vipix_multisite 7090 · dh_y_duoc 15440 · namgroup 6106 · ashico 4742 · vipix_ai_infra 4176 · benhvien_aau 3024; chỉ `shared_global` = 0); **query THẬT** `search_code` → 1 hit **có ruột** score 7.156 ⇒ collection đọc được, **không phải vỏ rỗng** (metadata một mình KHÔNG đủ — có thể là registry-cache). ② **SE index-freshness = KÉM**: `last_indexed_at` = **2026-05-29** trong khi **5 sibling re-index 2026-07-29 08:21** cùng một lượt. **Lật thẳng DOWN→alive sẽ CHÔN trục ②.** 🧊 **Nhãn "DOWN từ S153" ĐÚNG LÚC GHI** (`33e7f68`, 07-28 20:50, 3 phép đo khớp, `chunk_count=0` cả 7 project) — service **hồi phục sau ~12h** ⇒ class `view-stale-status`, **KHÔNG phải lead ghi ẩu**; đừng quy lỗi cho lượt viết vốn có bằng chứng đúng. 🔸 **Caveat giữ (H1 F-4 → ring1 T-2):** H1 tuyên `last_indexed_at` "không đáng tin" (2447→2449 nhúc nhích), `ring1` **BÁC** bằng nội-dung — coi là **đáng tin**; muốn chắc tuyệt đối thì re-index rồi xem field có nhảy không. Re-index = AI_INFRA op (cần VOYAGE_API_KEY). *(FLAG-2 `view-stale-status` HIGH — `lead-stale-auditor` @S159, `ring2` tái-dựng 8/8 số. Lead trước đó chỉ vá `:6`, sót đúng ô canonical này = **canonical-poison**, cùng lớp khác site.)* |