Files
solution-erp/.claude/auto-memory/feedback_cardinality_change_grep_consumers.md
pqhuy1987 23bbe97f39
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m26s
[CLAUDE] Docs: S124 adap-wave AI_INFRA + owner worker-tier-pin (14 agent opus+effort:max) + user-memory relocate R6 + H24 dogfood
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:17:45 +07:00

4.1 KiB

name, description, metadata
name description metadata
feedback_cardinality_change_grep_consumers Đổi field single→multi (cardinality) = grep MỌI consumer của field cũ — impl agent sửa write-site nhưng sót dependent read-site (vỡ chính feature vừa thêm)
node_type type originSessionId
memory feedback 1f21f760-be7e-4f90-8c3d-337edd5a4a9b

Khi đổi 1 field từ single→multi (cardinality), implementer agent sửa đúng chỗ HIỂN NHIÊN (picker/setter/write-site) nhưng SÓT các read-site phụ-thuộc field cũ — và đó là nơi feature MỚI vỡ.

Ca thật (S87 Mig 58 PE multi-winner): winner đổi từ scalar PurchaseEvaluation.SelectedSupplierId → tập PurchaseEvaluationSupplier.IsWinner per-row. implementer-frontend làm xong picker (tick nhiều ô + tổng) nhưng SÓT 8 chỗ FE vẫn keyed selectedSupplierId: missingForApproval (submit-guard), checklist, computeGiaChaoThau, canCreateContract, 2 display, winnerSupplierRowId. Vì SelectedSupplierId = null khi liên-danh ≥2 → multi-winner phiếu bị chặn submit (FE nói "chưa chọn NCC" dù đã tick 3 ông) = vỡ ĐÚNG feature vừa thêm. em-main self-review grep -rn selectedSupplierId mới bắt → đổi hết sang ev.suppliers.some(s => s.isWinner).

Why: cardinality change đổi SEMANTIC field cũ (single→có-thể-null/đổi-nghĩa khi multi). Mọi nơi đọc field cũ với giả-định "luôn có đúng 1 giá trị" sẽ sai. Implementer thấy write-path (1 chỗ), không thấy read-path rải-rác khắp codebase. Reviewer/build cũng PASS (TS compile + tests xanh) vì lỗi là LOGIC-runtime cho case multi, không phải type/compile.

How to apply: sau khi đổi cardinality 1 field → grep -rn "<oldField>" TOÀN BỘ FE+BE, kiểm TỪNG site: site này giả-định single? → đổi sang nguồn-sự-thật mới. Self-gate BẮT BUỘC dù impl + reviewer + build PASS — đây là blind-spot điển hình. Mở rộng cho mọi "1→N": single→list, optional→required, enum-thêm-value (feedback_root_cause_over_symptom họ gotcha #71 proxy-predicate). Trục thứ 2 — thêm ATTRIBUTE/FLAG mới rendered nhiều surface (S89): thêm 1 per-level flag AllowApproverFinalize (Mig 58) vào Workflow Designer nhưng SÓT surface song-song WorkflowMatrixViewPage (build S24 hard-code 7 <FlagRow>) → anh báo "matrix chưa hiển thị chính xác". Quy tắc: thêm field vào flag-set/attribute-set của 1 entity → grep MỌI nơi render set đó (Designer + matrix + flow-panel + chip + DTO projection), không chỉ surface đang sửa. BE thường đã gửi sẵn field; FE-các-surface mới là chỗ sót. Liên quan feedback_agent_kill_recovery (#53 recover-disk + self-gate) + feedback_workflow_fanout_reliability (workflow review-lane verify disk độc-lập, trust PASS dù impl-lane return NULL).

Trục thứ 3 — DERIVED-INVARIANT ở MUTATION-PATH, enumeration-writer KHÔNG đáng tin (S114 gotcha #81): đổi winner single→multi per-hạng-mục, Supplier.IsWinner thành DERIVED (== Any(Quote.IsSelected)). Spec (invest+review) liệt kê writer maintain-invariant "SelectWinner + UpsertQuote(ins+upd) + seed + backfill" NHƯNG SÓT DeleteQuote + DeleteDetail (cascade) → xóa quote-selected CUỐI của 1 NCC để IsWinner kẹt stale (Any=false) → CreateContract Where(IsWinner) gom NCC phantom → sinh HĐ giaTri=0. invest/review/implement ĐỀU sót vì cùng theo enumeration; chỉ verify adversarial-refute (lane "thử tìm bug, grep độc-lập MỌI .Remove(") bắt. Quy tắc mở rộng: cardinality/derived-flag change → grep KHÔNG chỉ read-site + write/select mà MỌI mutation đổi tập-nguồn: thêm (.Add) / sửa (= field) / XÓA (.Remove) / cascade-delete. Field-nguồn (Quote.IsSelected) → mọi path chạm TẬP quote phải re-establish flag phái-sinh. Read-site-miss ≡ writer-miss ≡ delete-writer-miss — cùng 1 class "consumer/producer bị bỏ sót khỏi enumeration". Enumeration của người KHÔNG đáng tin → grep máy-móc + adversarial-verify.