[CLAUDE] Docs: S68 session-end closeout — Hồ sơ NS header fix tên đen→trắng (gotcha #66 Tailwind v4 unlayered rule) + STATUS/HANDOFF/session log + harvest cicd MEMORY (Run #303-304)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-06-16 22:27:35 +07:00
parent 37752eb914
commit 764fe7024b
5 changed files with 133 additions and 7 deletions

View File

@ -50,7 +50,7 @@ Read-only CI/CD + post-deploy verifier SOLUTION_ERP. Polls Gitea Actions API, ve
- **Tests baseline:** **263 PASS** (S62 Run #286 sha 7926c21 spec; 45 Domain + 218 Infra em-main supplied; supersedes prev 228/240/256). CI gate runs both test projects BEFORE build/deploy status=success test gate passed (`tasks` endpoint reports terminal as `status:success`, `conclusion` field NOT populated). Local grep undercounts (Theory/InlineData) trust CI conclusion. Phase 9 UAT mode skip per chunk OK.
- **Mig latest repo:** **Mig 52 `20260616035929_AddHoSoLinkToPurchaseEvaluation`** (S65; PE +HoSoLink hyperlink-NAS, AddColumn-only no new table). Prev Mig 51 `AddDepartmentParentId` (S65 Department.ParentId loose-Guid org-tree, AddColumn-only) + Mig 50 `ReplaceBudgetModuleWithPeWorkItemBudgets` (S61 BudgetPeWorkItemBudgets net-reduce). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/` (52 mig .cs non-designer total). Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC TOP 5`. Table-count: `sys.tables` (is_ms_shipped=0, excl mighist) = **88** (S62 Run #286 verified S61 Budget-replace DROPPED tables 9388). Narrative-93 is STALE pre-S61 when commit touches no schema, 88 is correct, don't FAIL on 8893. Always cross-ref COMMIT scope vs ambient count.
- **Bearer:** admin `admin@solutions.com.vn/Admin@123456` (full) · UAT `nv.test@solutions.com.vn/TestUser@123456` (Drafter CCM, gotcha #44 check)
- **Bundle hash live S72:** admin `xkSz9BfE` (Run #298 sha 292d64d ROTATED from `BDwV5d0X`, broke S68S71 frozen-streak; FE-admin mirror EmployeesListPage + index.css accent 2 files) · user `BumgrwCJ` (Run #297 sha ab4e681 S71 FROZEN through S72 deploy-2 since fe-user untouched). ASYMMETRIC-deploy lesson (S66): FE-one-app commit that app's bundle MUST rotate + OTHER app MUST stay frozen; admin-rotate-when-only-fe-user-changed = anomaly flag. S50 mid-deploy transient lesson: pre-success snapshot can show intermediate FE copy in-flight re-confirm hash AFTER status=success ALWAYS (anti-pattern #3). FROZEN-expectation runs (BE-only or other-app): hash MUST stay = live pre-deploy value; rotate w/o relevant FE change = anomaly.
- **Bundle hash live S77:** admin `D532XZKG` (Run #303 sha 6983609 ROTATED from `CcrZqfht`; EmployeesListPage employee-detail banner text-polish) · user `CuFaBoWt` (Run #303 sha 6983609 ROTATED from `DniDFUB_`; same page both apps SHA256-identical `F013B748`). Prev live admin `CcrZqfht`/user `DniDFUB_` (Run #302 S76). ASYMMETRIC-deploy lesson (S66): FE-one-app commit that app's bundle MUST rotate + OTHER app MUST stay frozen; admin-rotate-when-only-fe-user-changed = anomaly flag. S50 mid-deploy transient lesson: pre-success snapshot can show intermediate FE copy in-flight re-confirm hash AFTER status=success ALWAYS (anti-pattern #3). FROZEN-expectation runs (BE-only or other-app): hash MUST stay = live pre-deploy value; rotate w/o relevant FE change = anomaly.
- **DB pw (S42, when `$PROD_DB_PASSWORD` empty):** `vrapp/buKL3TGBkD0wDDbYVw65QeX9` read from `C:\inetpub\solution-erp\api\appsettings.Production.json``ConnectionStrings.Default`. Skill-doc path `C:\inetpub\apps\SolutionErp\Api` is STALE real path `C:\inetpub\solution-erp\api`. sqlcmd over SSH works direct (no UTF-16 encode needed). sys-catalog string-concat queries hit collation conflict (`Latin1_General_CI_AS_KS_WS` vs `SQL_Latin1_General_CP1_CI_AS`) add `COLLATE DATABASE_DEFAULT` per concatenated column.
## 🔑 Critical config (flag commit nếu tái xuất)
@ -68,9 +68,11 @@ BE (test+build) ~90s · FE × 2 ~60s/app · deploy ~30s · **total ~3min code /
## 📅 Recent runs (FIFO — older → archive/git)
- **2026-06-16 S78 Run #304 (run_number 304, id418) sha=`37752eb` PASS ~4m (FE BOTH-APP 1-line CSS-precedence fix: "Hồ sơ NS" employee-detail banner NAME đen→trắng — `<h2>` rendered BLACK do unlayered `h1,h2,h3,h4{color:#0b1220}` index.css thắng `text-white` (Tailwind v4 @layer precedence); fix = `text-white``text-white!` important-modifier + `text-xl font-extrabold``text-lg font-bold`. 2 file `EmployeesListPage.tsx` fe-user+fe-admin SHA256-IDENTICAL `8BBAEC34…`, 1-line each, NO BE/mig/index.css; deploy 8/8 session after #297#303 all PASS):** Push `6983609..37752eb` (1 commit). Diff 2 files: both `.tsx` only → not in paths-ignore → full pipeline RAN. GITEA_TOKEN+PROD_DB_PW empty → anon Gitea API + DB pw từ prod `appsettings.Production.json``ConnectionStrings.Default` (path `C:\inetpub\solution-erp\api`, uid `vrapp` len24). Run IN-PROGRESS first 7 polls (running 19:55→19:58) — correctly did NOT verify-bundle-mid-flight (anti#3); pre-deploy baseline captured BEFORE poll-loop: admin `D532XZKG` (S77 #303 live) + user `CuFaBoWt` (S77 #303 live) — both == spec baseline (still live, deploy not yet shipped). Polled iter8 status=success (started ~19:55 → success 19:59:26 ≈4m). CI gate (both proj pre-deploy ⟹ status=success ⟹ test gate **286** baseline (45D+241I; FE-only ⟹ 0 BE call-site risk) passed; `conclusion` empty — `tasks` endpoint terminal=`status:success` doesn't populate `conclusion`, trust success; exact CI count NOT log-confirmed numerically — Gitea logs web-UI-only anon, 286 INFERRED from gate-passes-pre-build invariant). **★ BUNDLE BOTH ROTATE (the change-point — FE-BOTH-app, both EmployeesListPage changed ⟹ both bundles MUST rotate; verified AFTER status=success +re-confirm STABLE 2nd-fetch identical no transient — anti#3): admin ROTATE `D532XZKG→CNUv1jxY`** ✓ (`text-white!` name-color fix shipped) **+ user ROTATE `CuFaBoWt→CpOskeS1`** ✓ (same page shipped). BOTH required per spec → BOTH did (mirror S74/S75/S76/S77 pure-FE-both-app pattern — both same-SHA256 file ⟹ both rotate; frozen sibling here = ship-fail flag). Smoke **4×200**: api `/health/ready`+`/health/live` + admin root + eoffice root. **NO migration** — prod `__EFMigrationsHistory` top = `20260616035929_AddHoSoLinkToPurchaseEvaluation` (Mig 52) == repo HEAD GIỮ NGUYÊN ✓ (`git diff --name-only 6983609 37752eb -- '*Migrations*' '*Persistence*'` = EMPTY; FE cannot alter schema → top did NOT advance; prev-2 = `AddDepartmentParentId` Mig51 + `ReplaceBudgetModuleWithPeWorkItemBudgets` Mig50 chain intact). **sys.tables=88 verified** (sqlcmd COUNT excl mighist — unchanged, no schema touch). 0 regression. NO prod-data mutation (read-only curls + sqlcmd SELECT-only). Visual "tên NV trắng render đúng" NOT verified (anh xem mắt) — only ship+rotate+health+mig-unchanged+tables88; SHA256-identical-between-2-apps is a SOURCE-claim (git), not runtime DOM-equality; CSS-precedence-actually-fixed is render-time, NOT provable by curling bundle (the `!important` text is in dist css per spec-claim, but visual-black-vs-white is browser-render). **LESSON: pure-FE-BOTH-app 1-line CSS-fix verify (8th consecutive deploy this session, both apps same component SHA256-identical) = both bundles MUST ROTATE (≠ asymmetric one-app where sibling frozen; ≠ BE-only where both frozen). Even a 1-line `text-white`→`text-white!` change → new content-hash both apps. Migration top + sys.tables MUST stay = prev (FE-only). No BE call-site/DTO/endpoint smoke (no API surface — render-only). TOOLING (re-confirmed S77): Bash tool is POSIX bash (`Select-String`/`$var`/`$env:` unavailable inline) → write PowerShell to `.ps1` + invoke `powershell -File "ABSOLUTE/FORWARD/SLASH.ps1"` (Bash EATS backslash in `tmp\x.ps1`→`tmpx.ps1`); parse Gitea `tasks` via `Invoke-RestMethod`+native object (match `head_sha -like sha*`, `limit=N` ignored); SSH→PS nested-quote mangles → base64 `-EncodedCommand` (UTF-16LE) BOTH the appsettings-read AND the sqlcmd-query (no `$` in B64 passes bash+ssh clean); CLIXML progress-stream on stdout harmless (data rows clean below); read DB pw from prod appsettings when PROD_DB_PW empty. NEVER fixed code (READ-only).** Tag `[s78, run304, pass, fe-both-app-hoso-name-color-fix-text-white-important, fe-both-2files-sha256-identical-8BBAEC34, bundle-BOTH-rotate-CNUv1jxY-CpOskeS1, css-precedence-tailwind-v4-layer, no-mig-top-stays-mig52, tables88-verified, deploy8of8, ssh-encodedcommand-base64, no-regression, test286-inferred]`.
- **2026-06-16 S77 Run #303 (run_number 303, id417) sha=`6983609` PASS ~5m (FE BOTH-APP additive: "Hồ sơ NS" employee-detail BANNER text-polish — name `text-xl font-extrabold`+drop-shadow, meta `text-[13px] font-medium text-white`, status badge → solid status-colored pill emerald/amber/slate. 2 file `EmployeesListPage.tsx` fe-user+fe-admin SHA256-IDENTICAL `F013B748…`, NO BE/mig/index.css; +docs 2 files `{dep-audit SKILL.md gotcha 64→65, root CLAUDE.md test 263→286}` no-build-impact; deploy 7/7 session after #297#302 all PASS):** Push range `231a7b0..6983609` (2 commits). Diff 4 files: 2 `.tsx` + `CLAUDE.md` + `dependency-audit-erp/SKILL.md`. `.tsx` → not in paths-ignore → full pipeline RAN (docs alone would SKIP, but tsx present ⟹ build per Discovery#3 push-range any-non-ignored ⟹ whole build). GITEA_TOKEN+PROD_DB_PW empty → anon Gitea API + DB pw từ prod `appsettings.Production.json``ConnectionStrings.Default` (path `C:\inetpub\solution-erp\api`). Run IN-PROGRESS first 6 polls (running 19:36→19:39) — correctly did NOT verify-bundle-mid-flight (anti#3); pre-deploy baseline captured BEFORE poll-loop: admin `CcrZqfht` (S76 #302 live) + user `DniDFUB_` (S76 #302 live) — both == spec baseline (still live, deploy not yet shipped). Polled iter6 status=success (started ~19:35 → success 19:40 ≈5m). CI gate (both proj pre-deploy ⟹ status=success ⟹ test gate **286** baseline (45D+241I; FE-only ⟹ 0 BE call-site risk) passed; `conclusion` empty — `tasks` endpoint terminal=`status:success` doesn't populate `conclusion`, trust success; could NOT extract exact CI count — Gitea logs web-UI-only anon, 286 INFERRED from gate-passes-pre-build invariant NOT log-confirmed numerically). **★ BUNDLE BOTH ROTATE (the change-point — FE-BOTH-app, both EmployeesListPage changed ⟹ both bundles MUST rotate; verified AFTER status=success +re-confirm STABLE 2nd-fetch identical no transient — anti#3): admin ROTATE `CcrZqfht→D532XZKG`** ✓ (banner polish shipped) **+ user ROTATE `DniDFUB_→CuFaBoWt`** ✓ (same page shipped). BOTH required per spec → BOTH did (mirror S74/S75/S76 pure-FE-both-app pattern — both same-SHA256 file ⟹ both rotate; frozen sibling here = ship-fail flag). ⚠️ Local-build hashes (fe-user `SuT9mDAQ`, fe-admin `7ICczYiQ` per spec) ≠ deployed CI hashes — EXPECTED (CI rebuilds; only matters NEW≠baseline, confirmed). Smoke **4×200**: api `/health/ready`+`/health/live` + admin root + eoffice root. **NO migration** — prod `__EFMigrationsHistory` top = `20260616035929_AddHoSoLinkToPurchaseEvaluation` (Mig 52) == repo HEAD GIỮ NGUYÊN ✓ (`git diff --name-only 231a7b0 6983609 -- '*Migrations*' '*Persistence*'` = EMPTY; FE+docs cannot alter schema → top did NOT advance; prev-2 = `AddDepartmentParentId` Mig51 + `ReplaceBudgetModuleWithPeWorkItemBudgets` Mig50 chain intact). **sys.tables=88 verified** (sqlcmd COUNT excl mighist — unchanged, no schema touch). 0 regression. NO prod-data mutation (read-only curls + sqlcmd SELECT-only). Visual "banner text-xl/drop-shadow/status-pill render đúng" NOT verified (anh xem mắt) — only ship+rotate+health+mig-unchanged+tables88; SHA256-identical-between-2-apps is a SOURCE-claim (git), not runtime DOM-equality. **LESSON: pure-FE-BOTH-app additive verify (7th consecutive deploy this session, both apps same component SHA256-identical) = both bundles MUST ROTATE (≠ asymmetric one-app where sibling frozen; ≠ BE-only where both frozen). Docs-files in same range as tsx do NOT suppress build (range any-non-ignored ⟹ build). Migration top + sys.tables MUST stay = prev (FE-only). No BE call-site/DTO/endpoint smoke (no API surface — render-only). TOOLING (re-confirmed S76): Bash tool EATS inline `$var`/`$env:`/`@{}` in PS strings → write PowerShell to `.ps1` + run `-File`; parse Gitea `tasks` via `Invoke-RestMethod`+native object (match `head_sha -like sha*`, `limit=N` ignored); SSH→sqlcmd base64 `EncodedCommand` (UTF-16LE via iconv, no `$` in B64 passes bash clean), CLIXML progress-stream stdout harmless grep-filter out; ⚠️ this `sqlcmd` build does NOT support `-ConnectionString` flag → parse `User Id`/`Password` from conn-string via regex → `-U/-P`; read DB pw from prod appsettings when PROD_DB_PW empty. NEVER fixed code (READ-only).** Tag `[s77, run303, pass, fe-both-app-hoso-banner-textpolish, fe-both-2files-sha256-identical-F013B748, bundle-BOTH-rotate-D532XZKG-CuFaBoWt, docs-in-range-no-suppress-build, no-mig-top-stays-mig52, tables88-verified, deploy7of7, sqlcmd-no-connstring-flag-use-U-P, no-regression, test286-inferred]`.
- **2026-06-16 S76 Run #302 (run_number 302, id416) sha=`536dd6b` PASS ~4m (FE BOTH-APP additive: PE "Link hồ sơ ổ mạng" render upgrade — đường-dẫn-ổ-mạng từ chữ+Copy → `<a href=file://…>` bấm-thử mở Explorer + GIỮ nút Copy dự phòng. 2 file `PeDetailTabs.tsx` fe-user+fe-admin SHA256-IDENTICAL `b415023b…`, +46/14 mỗi file, NO BE/mig/index.css/Employee-page; deploy 6/6 session after #297/#298/#299/#300/#301 all PASS):** Push 2 files `{fe-admin,fe-user}/src/components/pe/PeDetailTabs.tsx`. `.tsx` → not in paths-ignore → full pipeline RAN. GITEA_TOKEN+PROD_DB_PW empty → anon Gitea API + DB pw từ prod `appsettings.Production.json``ConnectionStrings.Default`. Run IN-PROGRESS first 6 polls (running 14:54:20→14:56:57) — correctly did NOT verify-bundle-mid-flight (anti#3); pre-deploy baseline captured BEFORE poll-loop: admin `I1fpLeYw` (S75 #301 live) + user `DrQYkzh0` (S75 #301 live) — both == spec baseline. Polled iter7 status=success (started ~14:53 → success 14:57:13 ≈4m). CI gate (both proj pre-deploy ⟹ status=success ⟹ test gate **286** baseline (45D+241I; FE-only ⟹ 0 BE call-site risk) passed; `conclusion` empty — `tasks` endpoint terminal=`status:success` doesn't populate `conclusion`, trust success). **★ BUNDLE BOTH ROTATE (the change-point — FE-BOTH-app, both PeDetailTabs changed ⟹ both bundles MUST rotate; verified AFTER status=success +re-confirm STABLE 2nd-fetch identical no transient — anti#3): admin ROTATE `I1fpLeYw→CcrZqfht`** ✓ (file:// link shipped) **+ user ROTATE `DrQYkzh0→DniDFUB_`** ✓ (same component shipped). BOTH required per spec → BOTH did (mirror S74/S75 pure-FE-both-app pattern — both same-SHA256 file ⟹ both rotate; frozen sibling here = ship-fail flag). Smoke **4×200**: api `/health/ready`+`/health/live` + admin root + eoffice root. **NO migration** — prod `__EFMigrationsHistory` top = `20260616035929_AddHoSoLinkToPurchaseEvaluation` (Mig 52) == repo HEAD GIỮ NGUYÊN ✓ (`git diff --name-only 536dd6b~1 536dd6b -- '*Migrations*'` = EMPTY; FE cannot alter schema → top did NOT advance; prev-2 = `AddDepartmentParentId` Mig51 + `ReplaceBudgetModuleWithPeWorkItemBudgets` Mig50 chain intact). **sys.tables=88 verified** (sqlcmd COUNT excl mighist — unchanged, no schema touch). 0 regression. NO prod-data mutation (read-only curls + sqlcmd SELECT-only). Visual "link file:// bấm mở Explorer / nút Copy" NOT verified (anh xem mắt) — only ship+rotate+health+mig-unchanged+tables88; SHA256-identical-between-2-apps is a SOURCE-claim (git), not runtime DOM-equality (file:// scheme browsers thường block từ https-origin → click có thể no-op tùy browser, đó là lý do GIỮ Copy dự phòng — không kiểm chứng được qua curl). **LESSON: pure-FE-BOTH-app additive verify (6th consecutive deploy this session, both apps same component SHA256-identical) = both bundles MUST ROTATE (≠ asymmetric one-app where sibling frozen; ≠ BE-only where both frozen). Migration top + sys.tables MUST stay = prev (FE-only). No BE call-site/DTO/endpoint smoke (no API surface — render-only). TOOLING (re-confirmed S75): Bash tool EATS inline `$var`/`$env:` in `powershell -Command` → write PowerShell to `.ps1` + run `-File`; `certutil -hashfile … SHA256` for SHA256 (NOT findstr-pipe — quoting breaks); parse Gitea `tasks` via `Invoke-RestMethod`+native object (match `head_sha -eq sha`, `limit=N` ignored); SSH→sqlcmd base64 `EncodedCommand` (UTF-16LE, no `$` in B64 passes bash clean), CLIXML progress-stream stdout harmless; read DB pw from prod appsettings when PROD_DB_PW empty (path `C:\inetpub\solution-erp\api`, key `ConnectionStrings.Default`). NEVER fixed code (READ-only).** Tag `[s76, run302, pass, fe-both-app-pe-link-hoso-file-scheme, fe-both-2files-sha256-identical-b415023b, bundle-BOTH-rotate-CcrZqfht-DniDFUB_, no-mig-top-stays-mig52, tables88-verified, deploy6of6, no-regression, test286]`.
- **2026-06-16 S75 Run #301 (run_number 301, id415) sha=`6df1b2d` PASS ~2.5m (FE BOTH-APP additive: PE "Link hồ sơ" auto-detect render — `http(s)`→hyperlink bấm-mở (giữ nguyên) / đường dẫn ổ mạng `O:\...`→chữ+nút Copy. 2 file `PeDetailTabs.tsx` fe-user+fe-admin SHA256-IDENTICAL `da0884a5…`, NO BE/mig/index.css/Employee-page; deploy 5/5 session after #297/#298/#299/#300 all PASS):** Push 2 files `{fe-admin,fe-user}/src/components/pe/PeDetailTabs.tsx`. `.tsx` → not in paths-ignore → full pipeline RAN. GITEA_TOKEN+PROD_DB_PW empty → anon Gitea API + DB pw từ prod `appsettings.Production.json``ConnectionStrings.Default`. Run IN-PROGRESS first poll (running 14:31) — correctly did NOT verify-bundle-mid-flight (anti#3); pre-deploy baseline captured BEFORE poll-loop: admin `PxiZQkaw` (S74 #300 live) + user `B36hGoKd` (S74 #300 live) — both == spec baseline. Polled iter4 status=success (started ~14:31 → success 14:33:21 ≈2.5m — fastest streak, FE-only no big BE build). CI gate (both proj pre-deploy ⟹ status=success ⟹ test gate **286** baseline (45D+241I; FE-only ⟹ 0 BE call-site risk) passed; `conclusion` empty — `tasks` endpoint terminal=`status:success` doesn't populate `conclusion`, trust success). **★ BUNDLE BOTH ROTATE (the change-point — FE-BOTH-app, both PeDetailTabs changed ⟹ both bundles MUST rotate; verified AFTER status=success +re-confirm STABLE 2nd-fetch identical no transient — anti#3): admin ROTATE `PxiZQkaw→I1fpLeYw`** ✓ (Link-hồ-sơ auto-detect shipped) **+ user ROTATE `B36hGoKd→DrQYkzh0`** ✓ (same component shipped). BOTH required per spec → BOTH did (mirror S74 pure-FE-both-app pattern — both same-SHA256 file ⟹ both rotate; frozen sibling here = ship-fail flag). Smoke **3×200**: api `/health/ready` + admin root + eoffice root. **NO migration** — prod `__EFMigrationsHistory` top = `20260616035929_AddHoSoLinkToPurchaseEvaluation` (Mig 52) == repo HEAD GIỮ NGUYÊN ✓ (`git diff --name-only 6df1b2d~1 6df1b2d -- '*Migrations*'` = EMPTY; FE cannot alter schema → top did NOT advance; prev-2 = `AddDepartmentParentId` Mig51 + `ReplaceBudgetModuleWithPeWorkItemBudgets` Mig50 chain intact). **sys.tables=88 verified** (sqlcmd COUNT excl mighist — unchanged, no schema touch). 0 regression. NO prod-data mutation (read-only curls + sqlcmd SELECT-only). Visual "hyperlink bấm-mở / nút Copy hiện đúng" NOT verified (anh xem mắt) — only ship+rotate+health+mig-unchanged+tables88; SHA256-identical-between-2-apps is a SOURCE-claim (git), not runtime DOM-equality (auto-detect http-vs-O:\ branching is component logic, not provable by curling bundle). **LESSON: pure-FE-BOTH-app additive verify (5th consecutive deploy this session, both apps same component SHA256-identical) = both bundles MUST ROTATE (≠ asymmetric one-app where sibling frozen; ≠ BE-only where both frozen). Migration top + sys.tables MUST stay = prev (FE-only). No BE call-site/DTO/endpoint smoke (no API surface — render-only change). TOOLING (re-confirmed S74): Bash tool EATS inline `$var`/`$env:` in `powershell -Command` → write PowerShell to `.ps1` + run `-File`; parse Gitea `tasks` via `Invoke-RestMethod`+native object (match `head_sha -eq sha`, `limit=N` ignored); SSH→sqlcmd base64 `EncodedCommand` (UTF-16LE, no `$` in B64 passes bash clean), CLIXML progress-stream stdout harmless; read DB pw from prod appsettings when PROD_DB_PW empty (path `C:\inetpub\solution-erp\api`). NEVER fixed code (READ-only).** Tag `[s75, run301, pass, fe-both-app-pe-link-hoso-autodetect, fe-both-2files-sha256-identical, bundle-BOTH-rotate-I1fpLeYw-DrQYkzh0, no-mig-top-stays-mig52, tables88-verified, deploy5of5, fastest-2.5m, ps1-file-not-inline-dollar, no-regression, test286]`.
- **2026-06-16 S74 Run #300 (id414) sha=`91aaf05` PASS ~5m (FE BOTH-APP list-redesign: bảng list 3-cột → flex-row gọn hết-tràn-ngang-rail + đồng nhất cỡ chữ (header text-xl→lg, list name 13px) — 2 file `EmployeesListPage.tsx` fe-user+fe-admin SHA256-IDENTICAL `37d7cc6c…`, NO BE/mig/index.css; deploy 4/4 session after #297/#298/#299 all PASS):** Push 2 files `{fe-admin,fe-user}/src/pages/hrm/EmployeesListPage.tsx`. `.tsx` → not in paths-ignore → full pipeline RAN. GITEA_TOKEN+PROD_DB_PW empty → anon Gitea API + DB pw từ prod `appsettings.Production.json``ConnectionStrings.Default` (`buKL3...buKL3TGBkD0wDDbYVw65QeX9`). Run IN-PROGRESS first poll (running 14:22) — correctly did NOT verify-bundle-mid-flight (anti#3); pre-deploy baseline snapshot captured BEFORE poll-loop: admin `xkSz9BfE` (S72 #298 live) + user `BumgrwCJ` (S71 #297 live, FROZEN-streak through S73 BE-only) — both == spec baseline. Polled iter5 status=success (started ~14:20 → success ~14:25 ≈5m). CI gate (both proj pre-deploy ⟹ status=success ⟹ test gate **286** baseline (45D+241I; FE-only ⟹ 0 BE call-site risk) passed; `conclusion` empty — `tasks` endpoint terminal=`status:success` doesn't populate `conclusion`, trust success). **★ BUNDLE BOTH ROTATE (the change-point — FE-BOTH-app, both pages changed ⟹ both bundles MUST rotate; verified AFTER status=success +re-confirm STABLE 2nd-fetch identical no transient — anti#3): admin ROTATE `xkSz9BfE→PxiZQkaw`** ✓ (EmployeesListPage flex-row shipped) **+ user ROTATE `BumgrwCJ→B36hGoKd`** ✓ (same page shipped — user un-froze from S71-S73 frozen-streak, correct now fe-user finally changed). BOTH required per spec → BOTH did. ⚠️ Distinct from S68 (cross-stack BE+FE both-rotate) — this is PURE-FE-both-app both-rotate (no BE/mig). Smoke **3×200**: api `/health/ready` + admin root + eoffice root. **NO migration** — prod `__EFMigrationsHistory` top = `20260616035929_AddHoSoLinkToPurchaseEvaluation` (Mig 52) == repo HEAD GIỮ NGUYÊN ✓ (commit 0 mig files; FE cannot alter schema → top did NOT advance; prev-2 = `AddDepartmentParentId` Mig51 + `ReplaceBudgetModuleWithPeWorkItemBudgets` Mig50 chain intact). **sys.tables=88 verified** (sqlcmd COUNT excl mighist — unchanged, no schema touch). 0 regression. NO prod-data mutation (read-only curls + sqlcmd SELECT-only). Visual "flex-row gọn/hết-tràn-rail/đồng nhất cỡ chữ" NOT verified (anh xem mắt) — only ship+rotate+health+mig-unchanged+tables88; SHA256-identical-between-2-apps is a SOURCE-claim (git), not runtime DOM-equality. **LESSON: pure-FE-BOTH-app verify (both apps same file, SHA256-identical) = both bundles MUST ROTATE (≠ asymmetric S70/S71 one-app where sibling stays frozen; ≠ S73 BE-only where both stay frozen) — a frozen sibling here would = ship-fail flag; user un-froze from multi-session frozen-streak = EXPECTED when fe-user finally changes (streak-break normal). Migration top + sys.tables MUST stay = prev (FE-only). No BE call-site/DTO/endpoint smoke (no API surface). **TOOLING (re-confirmed S73): Bash tool wrapper EATS inline `$var`/`$matches[1]`→`[1]` in `powershell -Command` strings AND `$env:`→mangled — MUST write PowerShell to a `.ps1` file + run `-File` (no inline `$` survives bash eval); python3 broken on box. Parse Gitea `tasks` via `Invoke-RestMethod`+native object (match by `head_sha -like sha*`); `limit=N` ignored. SSH→sqlcmd: base64-encode (UTF-16LE via `[Convert]::ToBase64String([Text.Encoding]::Unicode...)`) the query `.ps1` → `ssh vps "powershell -EncodedCommand $B64"` (B64 has no `$` so passes bash clean); CLIXML progress-stream on stdout harmless, data lines clean. Read DB pw via `ssh→appsettings.Production.json ConvertFrom-Json .ConnectionStrings.Default` when PROD_DB_PW empty (path `C:\inetpub\solution-erp\api`). NEVER fixed code (READ-only).** Tag `[s74, run300, pass, fe-both-app-list-redesign-flexrow, fe-both-2files-sha256-identical, bundle-BOTH-rotate-PxiZQkaw-B36hGoKd, user-unfroze-from-s71streak, no-mig-top-stays-mig52, tables88-verified, deploy4of4, ps1-file-not-inline-dollar-eaten, no-regression, test286]`.
- _(S74 Run #300 sha=`91aaf05` PASS [FE-both-app list-redesign flex-row, bundle-BOTH-rotate PxiZQkaw/B36hGoKd, user-unfroze-from-s71-streak, no-mig-mig52, tables88, test286, TOOLING: ps1-file-not-inline-dollar + ssh-encodedcommand-base64] → FIFO-trimmed, full verbatim git + `archive/2026-06.md`)_
- **2026-06-16 S73 Run #299 (id413) sha=`bcd619d` PASS ~3m (TESTS-ONLY BE: +3 files `tests/SolutionErp.Infrastructure.Tests/Application/{DepartmentTreeTests,PeHoSoLinkTests,HrmProfilePermissionSeedTests}.cs` = +23→286 total (45D+241I). NO prod code, NO FE, NO migration; deploy 3/3 session after #297/#298 both success):** `.cs` not in paths-ignore → full pipeline RAN. Run IN-PROGRESS first poll (running 14:06) → polled iter4 status=`success` (~14:09 ≈3m); `conclusion` empty (terminal=success, trust). **CI test gate = the focus: gate runs BOTH test projects BEFORE build ⟹ status=success ⟹ 23 new tests passed on CI (not just local 286).** Could NOT extract exact CI count — Gitea `runs/413/logs`+`jobs` endpoints all **404 anon** (logs web-UI-only without auth token; GITEA_TOKEN empty). Inferred 286 from success (gate-passes-pre-build invariant) — NOT log-confirmed numerically. **★ BUNDLE BOTH-FROZEN (BE-only ⟹ neither app may rotate), verified AFTER status=success +2nd-fetch STABLE no transient (anti#3): admin `xkSz9BfE` FROZEN ✓ + user `BumgrwCJ` FROZEN ✓** (==pre-deploy baseline both; rotate-on-BE-only = anomaly→none). Smoke **4×200**: api `/health/ready`+`/health/live`+admin root+eoffice root. **NO migration** — prod `__EFMigrationsHistory` top=`AddHoSoLinkToPurchaseEvaluation`(Mig52)==repo HEAD GIỮ NGUYÊN ✓ (prev-2 Mig51 `AddDepartmentParentId`+Mig50 `ReplaceBudgetModule…` chain intact; commit 0 mig files). **sys.tables=88** ✓ (sqlcmd excl mighist, unchanged). 0 regression, NO prod-data mutation (read curls+SELECT-only). **TOOLING LESSON (supersedes S72 #298): `python3`/`py -3` on this box = BROKEN ZKBioTime embed (`AssertionError: SRE module mismatch` on `import re`/`json`) — version banner works but stdlib import dies. USE PowerShell `Invoke-RestMethod`+native object access (NOT ConvertFrom-Json on cached temp file — temp got stale snapshot once) to parse Gitea tasks; `limit=N` param IGNORED (returns full 299, match by id anyway). SSH→sqlcmd: nested bash→ssh→PS ate `$var` (S42) → use `iconv UTF-16LE|base64`→`powershell -EncodedCommand`; CLIXML progress-stream noise on stdout is harmless, data lines clean. Read DB pw from prod `appsettings.Production.json`→`ConnectionStrings.Default` when PROD_DB_PW empty (path `C:\inetpub\solution-erp\api`). NEVER fixed code (READ-only).** Tag `[s73, run299, pass, tests-only-be, +23-test-286-CI-gate-inferred-not-logcount, bundle-both-frozen-xkSz9BfE-BumgrwCJ, no-mig-top-mig52, tables88, deploy3of3, python3-broken-use-powershell-IRM, no-regression]`.
- **2026-06-16 S72 Run #298 (run_number 298, id412) sha=`292d64d` PASS ~4m20s (FE-Admin MIRROR "Hồ sơ Nhân sự" master-detail từ fe-user: overwrite EmployeesListPage.tsx cũ 1200→1602 dòng SHA256-IDENTICAL với fe-user + index.css +4 accent palette teal/amberx/violet/greenx + utility `.icon-chip`/`.app-gradient-brand`/`.card-accent`/`.stat-value` — FE-ADMIN-ONLY 2 files, NO BE, NO migration, NO fe-user; ASYMMETRIC NGƯỢC deploy-1 S71 #297 (đó fe-user-rotate/admin-frozen, đây admin-rotate/user-frozen)):** Deploy 2/2 trong session (deploy-1 = `ab4e681` #297 PASS fe-user `BumgrwCJ`; #297=success TRƯỚC push này nên KHÔNG bị cancel — confirmed in tasks list). Push 2 files `fe-admin/src/index.css`(+81) + `fe-admin/src/pages/hrm/EmployeesListPage.tsx`(1020+/537, 1476-line overwrite). `.tsx`+`.css` → not in paths-ignore → full pipeline RAN. GITEA_TOKEN+PROD_DB_PW empty → anon Gitea API + DB pw từ prod `appsettings.Production.json``ConnectionStrings.Default` (`buKL3...buKL3TGBkD0wDDbYVw65QeX9`). Run IN-PROGRESS first poll (running 13:52) — correctly did NOT verify-bundle-mid-flight (anti#3); pre-deploy baseline snapshot captured BEFORE poll: admin `BDwV5d0X` (S68 frozen-since, must rotate) + user `BumgrwCJ` (S71 deploy-1 live, must stay frozen). ⚠️ POLL-PARSER BUG: my `tr ','|grep -A4 '"id":412'` returned empty status ×10 iter (false negative — grep -A on tr-newlined JSON misanchors) → re-queried with `python3 json.load` → status=`success` (started 13:51:27 → updated 13:55:47 ≈4m20s). LESSON-tooling: parse Gitea tasks JSON via python3 NOT tr/grep -A (multi-field-per-object splits wrong); always cross-check with a clean parser before trusting empty-status. CI gate (both proj pre-deploy ⟹ status=success ⟹ test gate **263** baseline (45D+218I; FE-only ⟹ 0 BE call-site risk) passed; `conclusion` empty — trust success). **★ BUNDLE ASYMMETRIC NGƯỢC-deploy-1 (the change-point — FE-one-app verify) ALL PASS, verified AFTER status=success +re-confirm STABLE 2nd-fetch identical no transient (anti#3): admin ROTATE `BDwV5d0X→xkSz9BfE`** ✓ (EmployeesListPage mirror + accent index.css shipped — admin un-froze from S68's BDwV5d0X frozen-streak S68→S71, now rotated correctly cho fe-admin change) **+ user FROZEN `BumgrwCJ`==deploy-1-baseline** ✓ (fe-user 0 files touched deploy-2 → MUST NOT rotate = correct; rotate-when-untouched = anomaly→flag). Health api live+ready **200/200** (real endpoints `/health/ready`+`/health/live`, NOT `/health`) + admin/eoffice root 200. **NO migration** — prod `__EFMigrationsHistory` top = `20260616035929_AddHoSoLinkToPurchaseEvaluation` (Mig 52) == repo HEAD GIỮ NGUYÊN ✓ (prev-2 = `AddDepartmentParentId` Mig51 + `ReplaceBudgetModuleWithPeWorkItemBudgets` Mig50 chain intact; commit 0 mig files — FE cannot alter schema → top did NOT advance). **sys.tables=88 verified** (sqlcmd COUNT excl mighist — unchanged, no schema touch). 0 regression. NO prod-data mutation (read-only curls + sqlcmd SELECT-only). Visual "mirror identical / chữ xanh đậm brand-800 / accent đẹp" NOT verified (anh xem mắt) — only ship+rotate+health+mig-unchanged+tables88; SHA256-identical-with-fe-user is a SOURCE-claim (git diff), not runtime-verified by me (can't compare rendered DOM cross-app). **LESSON: deploy-2 of same-session asymmetric-NGƯỢC = (a) verify prior deploy (#297) NOT cancelled by this push (it was success first — confirmed in tasks); (b) status=success ⟹ deploy ran; (c) THIS-app bundle ROTATE + OTHER-app FROZEN — direction FLIPS vs deploy-1 (deploy-1 fe-user-rotate/admin-frozen → deploy-2 admin-rotate/user-frozen); admin un-froze from multi-session frozen-streak = EXPECTED when fe-admin finally changes (frozen-streak break is normal, not anomaly); (d) migration top + sys.tables MUST stay = prev (FE-only). Re-query Gitea JSON with python3 when tr/grep parse yields empty — parser bug ≠ run-stuck. No BE call-site/DTO/endpoint smoke (no API surface). SHA256-source-identical = git-level claim, runtime-mirror-equality not provable by curl. NEVER fixed code (READ-only).** Tag `[s72, run298, pass, fe-admin-mirror-hoso-from-feuser, fe-admin-only-2files, bundle-asymmetric-NGUOC-admin-rotate-user-frozen, admin-unfroze-from-s68-streak, no-mig-top-stays-mig52, tables88-verified, deploy2of2-prior297-not-cancelled, poll-parser-bug-use-python3, no-regression, test263]`.
- **2026-06-16 S71 Run #297 (run_number 297, id411) sha=`ab4e681` PASS ~4m21s (FE-User "Hồ sơ NS" cosmetic: đồng nhất font/size + chữ đen `text-slate-900/800`→xanh-đậm `text-brand-800` cho value/tên + bỏ `text-xs` nhánh mono — FE-USER-ONLY 1 file, NO BE, NO migration; 4th consecutive same-page S68→S71):** Push 1 file `fe-user/src/pages/hrm/EmployeesListPage.tsx` (className màu chữ + size, KHÔNG đụng BE/Mig/dep/fe-admin). `.tsx` → full pipeline RAN. GITEA_TOKEN+PROD_DB_PW empty → anon Gitea API + DB pw từ prod `appsettings.Production.json``ConnectionStrings.Default` (len24). Run IN-PROGRESS first poll (running 13:43) — correctly did NOT verify-bundle-mid-flight (anti#3), pre-deploy baseline snapshot captured BEFORE poll iter0: user `DbVv6rsf` (S70 baseline) + admin `BDwV5d0X`. Polled iter5 status=success (started ~13:42 → success ~13:46:48 ≈4m21s). CI gate (both proj pre-deploy ⟹ status=success ⟹ test gate **263** baseline (45D+218I; FE-only ⟹ 0 BE call-site risk) passed; `conclusion` empty — trust success). **★ BUNDLE ASYMMETRIC (the change-point — FE-one-app verify) ALL PASS, verified AFTER status=success +re-confirm STABLE 2nd-fetch identical no transient (anti#3): user ROTATE `DbVv6rsf→BumgrwCJ`** ✓ (EmployeesListPage cosmetic shipped — re-rotated from S70's DbVv6rsf, 4th consecutive same-page FE-user deploy = new content-hash each, normal) **+ admin FROZEN `BDwV5d0X`==baseline** ✓ (fe-admin 0 files touched → MUST NOT rotate = correct; rotate-when-untouched = anomaly→flag). Health api live+ready **200/200** (⚠️ `/health` spec'd → 404, real endpoint `/health/ready`+`/health/live` per iis-deploy-runbook skill — both 200, API healthy) + admin/eoffice root 200. **NO migration** — prod `__EFMigrationsHistory` top = `20260616035929_AddHoSoLinkToPurchaseEvaluation` (Mig 52) == repo HEAD GIỮ NGUYÊN ✓ (commit 0 mig files — `git diff --name-only | grep Migrations/` = NONE; FE-only cannot alter schema → top did NOT advance; prev-2 = `AddDepartmentParentId` Mig51 + `ReplaceBudgetModuleWithPeWorkItemBudgets` Mig50 chain intact). **sys.tables=88 verified** (sqlcmd COUNT excl mighist — unchanged, no schema touch). 0 regression. NO prod-data mutation (read-only curls + sqlcmd SELECT-only). Visual "chữ xanh đậm/đồng nhất size" NOT verified (anh xem mắt) — only ship+rotate+health+mig-unchanged+tables88. **LESSON: pure-FE-one-app cosmetic verify (4th consecutive same-page) = (a) status=success ⟹ deploy ran; (b) target-app bundle ROTATE + sibling-app FROZEN (re-rotate of same page across sessions = NORMAL, each deploy=new hash; rotate-sibling-when-untouched = anomaly); (c) migration top + sys.tables MUST stay = prev (FE cannot alter schema — advancing = bug); (d) health 200×2 (/ready+/live, NOT /health). ⚠️ `/health` 404 ≠ unhealthy — SOL uses `/health/ready`+`/health/live` (skill-doc), spec literal `/health` is wrong-path; cross-check skill before flagging. No BE call-site/DTO/endpoint smoke needed (no API surface). Tokens empty: anon Gitea + prod-appsettings DB pw works. NEVER fixed code (READ-only).** Tag `[s71, run297, pass, fe-user-hoso-cosmetic-brand800, fe-only-1file, bundle-asymmetric-user-rotate-admin-frozen, no-mig-top-stays-mig52, tables88-verified, health-ready-not-health, no-regression, test263]`.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,85 @@
# S68 (2026-06-16) — Hồ sơ NS header chi tiết NV: làm nổi bật + fix tên render đen→trắng
> em main solo · 3 commit (2 FE + 1 docs) · 2 deploy prod-verified Run #303-304 · HMW-mode ON · anh UAT realtime trên eoffice.
## Bối cảnh
Anh đang UAT trang **Hồ sơ Nhân sự** (master-detail, S65/S67) trên `eoffice.solutions.com.vn`. Yêu cầu xoay quanh **header banner chi tiết NV** (vùng gradient xanh chứa avatar + tên + dòng meta + badge trạng thái).
**Luồng:** `/session-start` → screenshot eoffice header NV *"sửa lại màu sắc/font các text trong khung đỏ cho nổi bật, màu đen + chữ in mảnh nhìn xấu"* → deploy #303 → screenshot *"cho chữ nhỏ lại, màu đen trên nền xanh ko nổi bật"* → fix #304`/session-end`.
## Bootstrap (`/session-start`)
2 monitor RE-REPORT (background, parallel) — đều **CLEAN**:
- 🟫 **H1 tooling-auditor:** roster **11/11 `model: inherit`** confirmed trên disk (Harness-8 runtime-landed, hết "executed-file pending-restart" ở mặt frontmatter) · ef-core skill FRESH (Mig 52, flush S66 giữ vững) · plugin 18/15/3 y nguyên. **Flag:** (1) stale `dependency-audit-erp/SKILL.md:153` "64 bẫy"→65; (2) **drift-correction**: curate-debt thực ra = **4 agent over-cap** (cicd 38.9 · inv-codebase 38.5 · **reviewer 35.4** · **impl-backend 30.7**), S67 chỉ flag 2.
-**H2 harvest-curator:** **0 orphan · 0 corruption · 5-trục PASS 5/5**. Harvest S67 landed trọn (4 file, test-specialist proxy-record đúng). 0 wave-folder residual · 0 stray cwd-path · 0 zero-byte.
→ em main patch 2 doc-drift (`11bc96d`): dep-audit 64→65 + root `CLAUDE.md:66` module-Tests row 263→286 (45D+241I).
**RAG:** collection alive, `last_indexed 05-29` stale; chunk-stats cold-read 0 (artifact MCP vừa connect — không phải mất index; các project khác cũng 0).
## Done
### #303 `6983609` — header polish ×2 app SHA256 (`F013B748`)
File: `fe-{user,admin}/src/pages/hrm/EmployeesListPage.tsx` (block header dòng 643-676).
- **Tên NV** `<h2>`: `text-lg font-bold``text-xl font-extrabold` + `drop-shadow-sm`.
- **Dòng meta** (mã • phòng • vị trí): `text-xs text-white/85``text-[13px] font-medium text-white` (to + đục 100% + nét dày); mã NV `font-mono font-semibold`; separator `text-white/55`.
- **Badge trạng thái**: pill trắng-mờ `bg-white/20 text-[11px]` chìm → **pill đặc màu theo status** dùng `EmployeeStatusColor` (1 emerald / 2 amber / 3 slate) + chấm `bg-current opacity-70` + `shadow-sm`. Reuse token sẵn có, no new import (`cn` + `EmployeeStatusColor` đã import).
- Build ×2 PASS · SHA256 mirror khớp · cicd **Run #303 PASS** · bundle admin `D532XZKG` / user `CuFaBoWt`.
### #304 `37752eb` — fix tên render ĐEN→TRẮNG (gotcha #66)
Anh báo *"tên màu đen nền xanh ko nổi bật"* — screenshot cho thấy `<h2 text-white>` (tên) render **đen `#0b1220`** trong khi `<div text-white>` (meta cùng banner) trắng đúng.
**Diagnose:** `fe-user/src/index.css:79` có rule `h1,h2,h3,h4 { color:#0b1220 }` viết **NGOÀI mọi `@layer`** (thêm S65 #290). Tailwind v4: CSS unlayered có priority **cao hơn tất cả `@layer`** (kể cả utilities) → `text-white` THUA. `<div>` không bị rule element nhắm nên trắng đúng → nghịch lý meta-trắng/heading-đen.
**Quyết định fix:** đo blast-radius `grep '<h[1-4][^>]*text-'`**~30+ heading toàn app** gắn `text-slate-700/900/brand-800` đang bị rule ép về `#0b1220`. Rule = **load-bearing** → KHÔNG được move vào `@layer base` (sẽ đổi màu loạt toàn app giữa UAT). → fix **ĐIỂM**: ép `text-white``text-white!` (important modifier Tailwind v4, trailing-bang). Verify bằng grep dist CSS: `.text-white\!{color:var(--color-white)!important}` ✓ → guaranteed thắng. Kèm thu nhỏ `text-xl → text-lg` + `font-extrabold → font-bold` (per "nhỏ lại").
- 1 dòng/file × 2 app · build ×2 PASS · SHA256 `8BBAEC34` · cicd **Run #304 PASS** · bundle admin `CNUv1jxY` / user `CpOskeS1`.
**gotcha #66 NEW** (Tailwind v4 unlayered element rule thắng utility — fix điểm `!`, không move @layer khi load-bearing).
## §L AUTO-MAINTAIN
- **§L.a AS-scan:** **0 production-bug RCA.** Iter-1 (#303 tên to+đen) KHÔNG phải defect mới — màu đen là **pre-existing** (rule heading ép mọi tên đen từ trước; anh báo "đen" ngay từ đầu = chính xác), iter-1 chỉ làm to nên lộ rõ; iter-2 fix root. Đây là UI iterate bình thường trên live UAT (authed page không screenshot dev-rig được — gotcha #3, visual gate = anh mắt thường qua prod). Guard mới = **gotcha #66**.
- **§L.b(a) summary-index:** STATUS Recently Done += S68. **(b) Active-Guards:** không guard mới ngoài gotcha #66. **(c) chore-flag:** 🔴 4 agent-memory > 30KB cap — cicd-monitor **44.1KB** (worst, +#303/#304), inv-codebase 38.5, reviewer 35.4, impl-backend 30.7 → curate next (P1). 0 zero-byte (AS-8 PASS).
- **§L.d flush + spawn-record (4-field):**
| agent | task | nấc | evidence |
|---|---|---|---|
| 🟫 tooling-auditor (H1) | bootstrap RE-REPORT 4-mặt + diff S67 | verified-self | roster 11/11 inherit disk + 2 flag actioned (dep-audit 64→65, curate-debt 2→4) |
| ⬜ harvest-curator (H2) | bootstrap RE-REPORT harvest 5-trục | verified-self | 0-orphan/0-corruption/0-zero-byte PASS (S67 landed trọn) |
| 🟩 cicd-monitor | verify Run #303 + #304 deploy | verified-self | self-record ×2 (FIFO-trim S74→pointer); bundle rotate confirm both runs |
- cicd self-recorded (agent-memory). H1/H2 spawn-record ghi **tại session log này** = canonical (em main single-writer) — per-agent diary append SKIP có chủ đích: bootstrap re-report CLEAN, 0 learning-at-risk (khác gotcha #53 case nơi work sub có thể MẤT → bắt buộc proxy). Coverage vẫn ✓ (traceable đủ 3 sub).
- **§L.e pending-request audit:** anh-pending = (1) xác nhận mắt tên trắng+gọn ưng chưa; (2) Ops S58/S59 giữ nguyên (tzutil · email anh Chương · 5 staff password · gán CNTT). Đã log SPECIFICS ở HANDOFF NEXT.
- **§L.f harvest GATE:** Coverage ✓ (3 sub đều có spawn-record) · Completeness ✓ (4-field) · Placement ✓ (agent-memory đúng role, 0 stray) · Corruption ✓ (0 zero-byte, no mojibake) · Fidelity ✓ no-flag. **No wave-folder** (dùng Agent-tool spawn lẻ, KHÔNG Workflow fan-out — task focused → solo+spawn đúng, không cần HMW dù mode ON). GATE PASS.
- **§L.g tooling CHỐT:** roster KHÔNG đổi (11 all-inherit). Skill: dep-audit 64→65 đã patch (H1 flag resolved). Plugin: 0 new-alloc. Doc-drift còn defer-monthly: `docs/CLAUDE.md` full count + schema-diagram §16+.
## State (verified)
| Metric | Value |
|---|---|
| Migrations | 52 (unchanged — FE-only) |
| SQL tables | 88 (unchanged) |
| Tests | 286 (45D + 241I — unchanged, no test này session; UAT mode skip per-chunk, build ×2 giữ) |
| Gotchas | **66** (+#66 Tailwind v4 unlayered heading rule) |
| Menu keys | 53 |
| Bundle prod | admin **`CNUv1jxY`** · user **`CpOskeS1`** (Run #304) |
| RAG | last_indexed 05-29 (stale); chunk cold-read 0 (MCP connect artifact) |
## Commit
| SHA | Scope | Note |
|---|---|---|
| `11bc96d` | Docs | bootstrap drift-fix — dep-audit 64→65 + root CLAUDE test 263→286 (H1) |
| `6983609` | FE | header polish (tên to/đậm + meta đậm + badge màu) ×2 SHA256, Run #303 |
| `37752eb` | FE | fix tên đen→trắng (`text-white!` thắng rule unlayered) + thu nhỏ ×2 SHA256, Run #304 |
| (this) | Docs | session-end closeout — gotcha #66 + STATUS/HANDOFF/session log + harvest |
## NEXT
- **anh:** xác nhận mắt tên NV trắng + gọn — ưng chưa (nhỏ hơn → `text-base`; màu nhấn nếu cần).
- **🔴 em main P1:** curate L1 — cicd-monitor 44.1KB + inv-codebase 38.5 + reviewer 35.4 + impl-backend 30.7 (4 agent over-cap, defer nhiều session).
- **defer-monthly (07-01):** docs/CLAUDE.md full count-flush + schema-diagram §16+ Mig 32-52 ERD + STATUS/HANDOFF re-tier (header bloat).
- **Ops của anh:** tzutil VPS · anh Chương email typo · 5 real staff password · gán CNTT → lock nv.cao/nv.truong.
## INFRA-ADOPTION
N/A (no infra adoption this session — 2 monitor bootstrap re-report là vận hành thường, không adopt broadcast mới).

View File

@ -1162,6 +1162,20 @@ for h in resp.points: # ← .points không phải iterable trực tiếp
---
### 66. Tailwind v4 — rule element thô `h1-h4{color}` viết NGOÀI `@layer` thắng MỌI utility `text-white` → heading không đổi màu; fix ĐIỂM bằng important `text-white!`, KHÔNG move `@layer` (load-bearing) (Session 68)
**Triệu chứng:** Header chi tiết NV (`app-gradient-brand` nền gradient xanh) `<h2 className="text-white">` render **ĐEN `#0b1220`**, trong khi `<div className="text-white">` (dòng meta cùng banner) render trắng đúng. Anh UAT báo "màu đen nhìn không nổi bật" chính xác, code ghi `text-white`.
**Cơ chế:** `fe-user/src/index.css:79` `h1,h2,h3,h4 { color:#0b1220 }` viết **thô, NGOÀI mọi `@layer`** (thêm S65 #290 "darker ink"). Tailwind v4: CSS unlayered priority **CAO HƠN tất cả `@layer`** (kể cả `utilities`) `text-white` (trong layer utilities) THUA. `<div>` không bị rule element này nhắm nên `text-white` thắng nghịch meta-trắng / heading-đen cùng 1 banner.
**Guard:** (1) **User báo màu render ≠ class trong code ⟹ NGHI ngay rule CSS priority cao hơn** (unlayered element / `!important` / global) grep `index.css` rule element TRƯỚC khi tin utility. (2) Ép utility thắng = **important modifier Tailwind v4 trailing-bang** `text-white!` compile `.text-white\!{color:…!important}` (**verify bằng grep dist CSS** đừng tin suông). (3) **KHÔNG move rule unlayered vào `@layer base` nếu load-bearing** đo blast-radius `grep '<h[1-4][^>]*text-'`: rule này đang ép ~30+ heading toàn app về `#0b1220` (chúng gắn `text-slate-700/900/brand-800` nhưng bị override) move = đổi màu loạt giữa UAT. (4) Authed page không screenshot dev-rig (gotcha #3) visual gate = anh mắt thường qua deploy prod.
**Credit:** em main solo S68 anh UAT realtime ("chữ đen nền xanh ko nổi bật") diagnose unlayered heading rule `text-white!` + thu nhỏ `text-lg` grep dist confirm `!important` Run #304 PASS, x2 app SHA256.
**References:** `fe-user/src/index.css:79-83` (h1-h4 unlayered) · `fe-{user,admin}/src/pages/hrm/EmployeesListPage.tsx:653` (h2 name `text-white!`) · Tailwind v4 layer precedence · gotcha #3 (authed screenshot).
---
## Checklist debug bug mới
1. Build pass không? fail check using + package version compat