Chúng tôi dùng cookies thiết yếu để website hoạt động, và một số cookies tùy chọn cho mục đích phân tích nhằm hiểu cách website được sử dụng. Bạn có thể chấp nhận tất cả, hoặc chỉ giữ phần thiết yếu. Đọc chính sách bảo mật để biết chi tiết.
Business model, product system và decision inventory | Học viện The Data Way
Bài 1/96 · Measurement Strategy, Product Metrics và Decision Architecture
Bài học xem thử miễn phí
Business model, product system và decision inventory
Câu hỏi trung tâm
Trước khi cài bất kỳ tracker, dashboard hay data pipeline nào: hệ thống sản phẩm đang tạo giá trị như thế nào, ai đang đưa ra quyết định gì, và bằng chứng nào thực sự làm thay đổi quyết định đó?
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Flashcards: thẻ ghi nhớ
Flashcards: thẻ ghi nhớ
Recap và handoff
Recap và handoff
Bạn sẽ làm được gì
Mô hình hóa sản phẩm như một hệ thống tạo giá trị thay vì tập hợp màn hình
Liệt kê các quyết định định kỳ của Product, Marketing, Risk, Operations và Engineering
Phân biệt câu hỏi mô tả, chẩn đoán, dự đoán và nhân quả
Xác định decision latency và phân loại quyết định cần realtime vs batch
Viết Measurement Charter chốt phạm vi đo lường cho capstone
Nội dung cốt lõi
Product as a system
Sản phẩm số là hệ thống trao đổi giá trị gồm actors, entities, states và transitions, không phải tập hợp màn hình. Với thẻ tín dụng số: khách hàng (actor) đẩy application (entity) qua chuỗi trạng thái submitted → approved → card_issued → activated; mỗi transition là một điểm đo tiềm năng. Vẽ system map trước khi bàn tracking giúp lộ ra queue, delay và failure point mà UI không thể hiện, ví dụ hồ sơ kẹt ở bước thẩm định thủ công 3 ngày.
Decision inventory
Danh mục quyết định định kỳ của tổ chức, mỗi dòng có owner, cadence, trigger, inputs, available actions, cost of delay, cost of error, reversibility và required data latency. Ví dụ: "có nới cutoff điểm tín dụng cho segment người đi làm trẻ không?", owner là Head of Credit Risk, cadence quý, cost of error rất cao vì credit loss chỉ lộ sau 6-12 tháng. Đo lường tồn tại để phục vụ các quyết định này, không phục vụ sự tò mò.
Chuỗi ngược: decision → evidence → metric → event
Anti-pattern phổ biến: cài tool → thu hàng nghìn event → xây hàng chục dashboard → vẫn không biết nên làm gì. Tuần 1 đảo chiều: quyết định nào cần cải thiện → quyết định cần bằng chứng gì → bằng chứng đòi hỏi metric nào → metric cần event và nguồn dữ liệu nào. Toàn bộ 11 tháng sau của khóa chạy trên chuỗi này: application_submitted được track vì nó nuôi metric phục vụ quyết định, không phải vì "track được thì track".
Question taxonomy
Câu hỏi analytics chia 5 loại: descriptive (chuyện gì đã xảy ra), diagnostic (vì sao), predictive (sắp tới thế nào), causal (nếu can thiệp thì sao) và prescriptive (nên làm gì theo rule). "Approval rate tuần này bao nhiêu?" là descriptive; "vì sao conversion giảm sau khi đổi form eKYC?" là diagnostic; nhưng muốn khẳng định "form mới LÀM GIẢM conversion" phải có bằng chứng causal (experiment). Nhầm loại câu hỏi → nhầm phương pháp → nhầm hạ tầng.
Leading/lagging signals và decision latency
Mỗi quyết định có yêu cầu độ trễ dữ liệu riêng: chặn giao dịch gian lận cần signal trong giây (realtime); điều chỉnh ngân sách kênh acquisition cần D+1 (batch); đánh giá chính sách tín dụng cần vintage 6-12 tháng (lagging). DoD tuần này yêu cầu ít nhất 5 quyết định realtime và 5 quyết định batch, chính là spec đầu vào cho kiến trúc pipeline ở Tháng 4. Xây realtime cho quyết định tháng là lãng phí; batch cho fraud là vô dụng.
Cost of wrong decision và reversibility
Quyết định one-way door (khó đảo ngược, chi phí sai lớn, ví dụ đổi chính sách hạn mức tín dụng) xứng đáng đầu tư bằng chứng chuẩn causal; quyết định two-way door (rollback dễ, ví dụ đổi thứ tự banner trong app) chỉ cần đo nhanh rồi thử. Mức đầu tư đo lường tỷ lệ thuận với cost of error, không tỷ lệ với độ ồn ào của stakeholder.
Measurement Charter
Văn bản chốt scope: 10 quyết định giá trị nhất của capstone, câu hỏi tương ứng, evidence cần có, và những gì nằm ngoài phạm vi. Đây là "hợp đồng" giúp bảo vệ phạm vi đo lường trước Product, Marketing, Risk, Operations và Compliance, đồng thời là đầu vào trực tiếp cho metric tree ở Tuần 2.
Lab thực hành
Vẽ system map cho quy trình mở thẻ tín dụng số
Liệt kê tối thiểu 30 quyết định mà các team cần đưa ra
Gắn mỗi quyết định với owner, cadence, input, output, rủi ro và hành động
Chọn 10 quyết định có giá trị cao nhất làm phạm vi capstone
Artifacts cần nộp
docs/measurement/decision-inventory.md
docs/measurement/product-system-map.drawio
Bảng phân loại 30 câu hỏi analytics
Definition of Done
Mỗi quyết định có người chịu trách nhiệm và hành động sau khi nhận dữ liệu
Không dùng mục tiêu mơ hồ như "tăng engagement" mà thiếu định nghĩa
Có ít nhất 5 quyết định cần realtime và 5 quyết định phù hợp batch
Lỗi thường gặp
Bắt đầu bằng tool ("chúng ta dùng GA4/PostHog nên xem tool track gì") thay vì bắt đầu từ quyết định cần cải thiện
Gom mọi thứ, activity metric, diagnostic, alert, guardrail, outcome, thành một danh sách "KPI" không phân vai trò
Decision inventory thiếu owner cụ thể hoặc thiếu hành động sau khi có dữ liệu, biến thành wishlist
Mục tiêu mơ hồ kiểu "tăng engagement" không định nghĩa hành vi nên không đo và không phản biện được
Câu hỏi ôn tập
Một dashboard không dẫn tới hành động có giá trị gì?
Gần như bằng 0, thậm chí âm: nó tốn chi phí xây và maintain, đồng thời tạo ảo giác "đã có đo lường". Dashboard chỉ có giá trị khi mỗi chart gắn với một quyết định có owner và hành động định trước ("nếu X dưới ngưỡng thì làm Y"). Bài kiểm tra nhanh: nếu con số này thay đổi 20%, ai sẽ làm gì khác đi trong tuần tới? Nếu câu trả lời là "không ai", chart đó là giấy dán tường.
Diagnostic (cắt theo segment, bước funnel, kênh) là đủ khi chỉ cần khoanh vùng vấn đề. Cần causal khi định quy kết nguyên nhân cho một thay đổi cụ thể và ra quyết định đắt, ví dụ rollback form eKYC mới hay đổi chính sách duyệt. Dữ liệu observational dễ bị confounding: mùa vụ, mix kênh, chiến dịch marketing chạy song song. Quyết định one-way door với chi phí sai lớn thì cần experiment hoặc quasi-experiment thay vì suy diễn từ correlation.
Decision latency ảnh hưởng kiến trúc dữ liệu như thế nào?
Latency yêu cầu của quyết định là spec cho pipeline: fraud blocking cần streaming trong giây; điều chỉnh ngân sách kênh cần batch D+1; đánh giá chính sách tín dụng cần dữ liệu vintage theo tháng. Vì vậy decision inventory phải ghi rõ required data latency cho từng quyết định, nó quyết định chỗ nào cần Kafka/Flink, chỗ nào chỉ cần warehouse chạy đêm, tránh cả hai kiểu lãng phí: over-engineering realtime cho quyết định tháng và under-engineering batch cho quyết định giây.
Repo walkthrough
Repo W01 biến decision inventory từ 'tài liệu' thành 'artifact có contract': một linter CSV kiểm 14 cột bắt buộc, enum impact và luật 'decision_question phải kết thúc bằng dấu ?'. Đây là hiện thân code của chuỗi ngược decision → evidence → metric → event mà cả 48 tuần chạy trên đó. Kèm theo là script tổng hợp portfolio quyết định và script sinh funnel data thẻ tín dụng có bias cài sẵn theo channel/device.
Cấu trúc thư mục
week-01-product-system-decision-architecture/
├── scripts/
│ ├── validate_decision_inventory.py # linter cho decision inventory
│ ├── summarize_decisions.py # phân tích portfolio quyết định
│ └── generate_sample_data.py # sinh 5.000 application có funnel bias
├── data/
│ ├── decision_inventory_example.csv # 30+ quyết định mẫu
│ ├── question_taxonomy_example.csv
│ ├── sample_applications.csv # output của generate_sample_data
│ └── sample_funnel_daily.csv
├── docs/ (product-system-map.mmd, value-flow-map.md, measurement-charter-example.md)
├── templates/ (decision-inventory-template.csv, measurement-charter-template.md)
├── tests/test_validate_decision_inventory.py
└── notebooks/01_decision_inventory_analysis.ipynb
Các file chính
scripts/validate_decision_inventory.py (core): Linter: kiểm schema 14 cột + business rule (impact enum, câu hỏi phải có dấu ?). Exit 1 nếu lỗi, đây là giao diện với CI.
scripts/summarize_decisions.py (core): Trả lời 'portfolio quyết định của tôi lệch về đâu', groupby function / impact / analysis_type + bảng chi tiết quyết định Critical & High.
scripts/generate_sample_data.py (core): Sinh 5.000 application với funnel started → otp → kyc → submitted → approved → activated → purchase, cài sẵn bias paid_social kém và android bị phạt.
data/decision_inventory_example.csv (data): Bộ 30+ quyết định mẫu, đầu vào chuẩn của cả validator lẫn summarize.
data/question_taxonomy_example.csv (data): Phân loại câu hỏi descriptive / diagnostic / predictive / causal.
templates/decision-inventory-template.csv (doc): Bản trắng để bạn điền decision inventory cho capstone của mình.
docs/measurement-charter-example.md (doc): Artifact cuối tuần: chốt phạm vi đo lường, 10 quyết định giá trị nhất.
tests/test_validate_decision_inventory.py (support): Test cho linter, mẫu để bạn viết thêm rule mới.
scripts/validate_decision_inventory.py
48 dòng này là trái tim của tuần 1: nó biến decision inventory thành artifact có thể fail CI. Mọi validator sau (metric tree T2, dictionary T4, event schema T5-T8) đều là biến thể phức tạp hơn của khung xương này.
Làm gì: Khai báo schema của decision inventory bằng Python set, 14 cột bắt buộc và enum cho impact.
Vì sao: Mỗi cột là một câu hỏi buộc phải trả lời. reversibility ép phân biệt one-way / two-way door; max_data_latency ép nói rõ realtime hay batch, đây chính là spec đầu vào cho kiến trúc pipeline Tháng 4. Dùng set để phép trừ tập hợp REQUIRED_COLUMNS - fields tìm cột thiếu.
Bẫy: Xoá bớt cột cho 'gọn' (thường là key_caveat, reversibility) → inventory quay lại thành wishlist. Thấy một cột 'vô dụng' thường nghĩa là bạn chưa hiểu quyết định đó đủ sâu.
def validate(path: Path) -> list[str]:
errors: list[str] = []
with path.open(newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
fields = set(reader.fieldnames or [])
missing = REQUIRED_COLUMNS - fields
if missing:
return [f"Missing columns: {sorted(missing)}"]
Làm gì: Đọc header, so với schema; thiếu cột thì return ngay, không kiểm row nào.
Vì sao: Fail-fast trên lỗi cấu trúc. Thiếu cột owner mà in 30 lỗi 'Row N: empty owner' là nhiễu, nguyên nhân gốc chỉ có một. newline="" là bắt buộc theo docs module csv: bỏ đi thì field chứa xuống dòng (key_caveat nhiều dòng) parse sai trên Windows.
Bẫy:set(reader.fieldnames or []), file rỗng làm fieldnames là None, không có or [] thì set(None) ném TypeError thay vì báo lỗi tử tế.
ids: set[str] = set()
for row_num, row in enumerate(reader, start=2):
did = (row.get("decision_id") or "").strip()
if not did:
errors.append(f"Row {row_num}: missing decision_id")
elif did in ids:
errors.append(f"Row {row_num}: duplicate decision_id {did}")
ids.add(did)
Làm gì: Duyệt từng dòng, phát hiện decision_id rỗng và trùng lặp.
Vì sao:start=2 là chi tiết UX quan trọng, Excel có header ở dòng 1, nên dòng dữ liệu đầu tiên là dòng 2. Báo 'Row 5' mà Excel hiện dòng 4 là cách chắc chắn làm người dùng ghét tool. Tích luỹ lỗi vào list (thay vì raise ngay) cho phép thấy toàn bộ lỗi trong một lần chạy.
Bẫy:ids.add(did) nằm NGOÀI elif, nên chuỗi rỗng cũng vào set → dòng thứ hai thiếu id sẽ báo cả 'missing' lẫn 'duplicate'. Đây là bug thật trong repo (bài tập 1).
for col in ["decision_name", "decision_question", "owner", "desired_outcome"]:
if not (row.get(col) or "").strip():
errors.append(f"Row {row_num}: empty {col}")
if row.get("impact") not in VALID_IMPACT:
errors.append(f"Row {row_num}: invalid impact {row.get('impact')!r}")
q = (row.get("decision_question") or "").strip()
if q and not q.endswith("?"):
errors.append(f"Row {row_num}: decision_question should end with '?'")
return errors
Làm gì: Ba lớp rule, 4 trường không rỗng, impact thuộc enum, và decision_question phải kết thúc bằng ?.
Vì sao: Rule dấu ? trông ngớ ngẩn nhưng có giá trị sư phạm cao nhất file: nó ép bạn phát biểu quyết định dưới dạng câu hỏi trả lời được ('Có nên nới cutoff điểm tín dụng cho segment người đi làm trẻ không?') thay vì cụm danh từ mơ hồ ('Tối ưu hoá chính sách tín dụng'). Cụm danh từ không trả lời được bằng dữ liệu. Đây là linting cho tư duy. !r in ra 'high' để bạn thấy ngay mình viết thường trong khi enum cần High.
Bẫy: Bỏ q and đi thì mỗi ô rỗng sinh 2 lỗi trùng ý.
if __name__ == "__main__":
if len(sys.argv) != 2:
raise SystemExit("Usage: python scripts/validate_decision_inventory.py <csv>")
target = Path(sys.argv[1])
issues = validate(target)
if issues:
print("\n".join(issues))
raise SystemExit(1)
print(f"VALID: {target}")
Làm gì: In toàn bộ lỗi rồi exit 1; sạch thì in VALID và exit 0.
Vì sao:Exit code chính là API với CI, GitHub Actions không đọc chữ 'FAIL' trong stdout, nó đọc exit code. Tách hàm validate() thuần (chỉ trả list, không print, không exit) khỏi phần CLI là điều kiện để test gọi được nó mà không phải bắt SystemExit.
Bẫy: Trộn print() vào trong validate() → test phải capture stdout, và không tái sử dụng được trong notebook.
scripts/summarize_decisions.py
20 dòng hiện thực khái niệm decision portfolio: tổ chức không chỉ có 'các quyết định' mà có một PHÂN BỐ quyết định, và phân bố đó lệch về đâu quyết định bạn cần hạ tầng gì.
def main(path: Path) -> None:
df = pd.read_csv(path)
print("\nDecisions by function")
print(df.groupby("function").size().sort_values(ascending=False).to_string())
print("\nDecisions by impact")
print(df.groupby("impact").size().reindex(["Critical","High","Medium","Low"]).fillna(0).astype(int).to_string())
Làm gì: Hai lát cắt portfolio: ai ra quyết định (function) và mức độ quan trọng (impact).
Vì sao:reindex(["Critical","High","Medium","Low"]) là điểm tinh tế, groupby mặc định sort theo alphabet cho ra 'Critical, High, Low, Medium', sai thứ tự nghiêm trọng và người đọc dễ hiểu nhầm Low quan trọng hơn Medium. reindex ép thứ tự ngữ nghĩa. fillna(0).astype(int) vì nếu không có metric Critical nào thì reindex sinh NaN (float) → bảng in ra '0.0'.
Bẫy: Nếu Critical + High chiếm > 50%, bạn đang lạm phát mức độ nghiêm trọng (mọi thứ quan trọng = không gì quan trọng).
Làm gì: Phân bố loại phân tích, và bảng chi tiết các quyết định Critical/High với 5 cột.
Vì sao: Bảng này là bản thiết kế pipeline của bạn. Đọc cột max_data_latency: nếu có quyết định Critical 'chặn giao dịch gian lận' với latency < 1s → bạn bắt buộc cần streaming (Kafka/Flink, Tháng 5-6). Nếu mọi Critical đều là D+1 → xây realtime là lãng phí thuần tuý. DoD tuần 1 yêu cầu tối thiểu 5 realtime + 5 batch.
Bẫy:.isin(["Critical","High"]) giả định impact đã sạch. Ai viết 'critical' chữ thường sẽ biến mất khỏi báo cáo trong im lặng, đây chính là lý do phải chạy validator TRƯỚC summarize.
if __name__ == "__main__":
if len(sys.argv) != 2:
raise SystemExit("Usage: python scripts/summarize_decisions.py <csv>")
main(Path(sys.argv[1]))
Làm gì: CLI guard tối giản, chỉ nhận một tham số.
Vì sao: Script này không có exit code lỗi, nó là công cụ đọc hiểu, không phải công cụ gác cổng. Phân biệt vai trò rõ ràng: validator gác cổng CI (exit 1), summarize chỉ báo cáo cho người đọc. Trộn hai vai trò làm cả hai đều tệ.
Bẫy: Nhìn bảng 'Analysis types' thấy 80% là descriptive và nghĩ 'tốt, đơn giản'. Thực ra đó là tín hiệu tổ chức chỉ quan sát chứ chưa can thiệp, không có quyết định causal nào tức là chưa ai dám chạy experiment.
scripts/generate_sample_data.py
File này mã hoá GIẢ THUYẾT SẢN PHẨM vào dữ liệu: paid_social có intent thấp hơn organic ở mọi bước funnel, và android bị phạt ở OTP/KYC/purchase. Đây là 'ground truth' để các tuần sau tìm ra bằng phân tích.
Làm gì: Cố định seed, định nghĩa phân bố channel và device.
Vì sao:Path(__file__).resolve().parents[1] khiến script chạy đúng bất kể bạn đứng ở thư mục nào, pattern lặp lại ở mọi repo sau. np.random.default_rng(seed) (Generator API mới) thay vì np.random.seed() (legacy global state): Generator là object cục bộ nên hai script chạy song song không giẫm chân nhau. Seed cố định ⇒ mọi học viên thấy cùng con số ⇒ so được đáp án.
Bẫy: Dùng np.random.seed() rồi gọi thư viện bên thứ ba cũng dùng random global → kết quả không tái lập được.
otp = rng.random() < ({"paid_social":.81,"paid_search":.86,"organic":.89,"referral":.91,"crm":.90}[channel] - (.04 if device=="android" else 0))
kyc = otp and rng.random() < ({"paid_social":.68,"paid_search":.75,"organic":.80,"referral":.84,"crm":.82}[channel] - (.05 if device=="android" else 0))
submitted = kyc and rng.random() < .93
approved = submitted and rng.random() < {"paid_social":.54,"paid_search":.60,"organic":.67,"referral":.71,"crm":.69}[channel]
activated = approved and rng.random() < (.73 if channel=="paid_social" else .80)
purchase = activated and rng.random() < (.71 if device=="android" else .77)
Làm gì: Mỗi bước funnel là một phép thử Bernoulli có điều kiện vào bước trước (kyc = otp and ...).
Vì sao: Chuỗi and mã hoá ràng buộc funnel: không thể KYC nếu chưa verify OTP. Nhờ short-circuit, khi otp=False thì rng.random() vế phải không được gọi. Quan trọng hơn: hai bias được cài có chủ đích, paid_social kém nhất ở mọi bước (0.81 OTP, 0.54 approval, 0.73 activation) và android bị phạt ở OTP (-4%), KYC (-5%), purchase (0.71 vs 0.77).
Bẫy: Cách khác là dùng ma trận chuyển trạng thái hay scipy.stats, nhưng khi đó bias bị giấu trong tham số. Ở đây bias nằm trần trụi trong literal dict: đọc code là thấy ngay ý đồ.
Làm gì: Mỗi application là một dòng, mỗi bước funnel là một cột 0/1.
Vì sao: Đây là wide format (một dòng / một entity), không phải event log. Với wide format, conversion rate chỉ là df["approved"].sum() / df["submitted"].sum(), cắt theo channel chỉ là một groupby, hoàn hảo cho tuần 1 khi chưa cần biết gì về event stream. f"APP{i+1:06d}" sinh id có padding, khớp chính xác pattern ^APP[0-9]{6,20}$ trong JSON Schema tuần 5!
Bẫy: Wide format không lưu timestamp của từng bước, nên không tính được 'thời gian từ submitted đến approved'. Tuần 3 chuyển sang event-log format chính vì lý do đó.
if __name__ == "__main__":
df = generate()
df.to_csv(OUTPUT / "sample_applications.csv", index=False)
print(f"Wrote {len(df):,} rows to {OUTPUT / 'sample_applications.csv'}")
Làm gì: Sinh dữ liệu, ghi CSV, in số dòng.
Vì sao:{len(df):,} in ra '5,000' có dấu phẩy, chi tiết nhỏ nhưng khi số lên hàng triệu thì nó là khác biệt giữa đọc được và không. In đường dẫn tuyệt đối của file output để người dùng không phải đoán file vừa ghi ở đâu.
Bẫy: Script này ghi đè data/sample_applications.csv mỗi lần chạy, không hỏi. Với seed cố định thì kết quả giống hệt nên vô hại, nhưng nếu bạn đổi seed để thí nghiệm, hãy nhớ bạn vừa mất bộ dữ liệu cũ.
Chạy thử
cd Repo/W01/week-01-product-system-decision-architecture && pip install -e ".[dev]"
python scripts/generate_sample_data.py
# → Wrote 5,000 rows to .../data/sample_applications.csv
python scripts/validate_decision_inventory.py data/decision_inventory_example.csv
# → VALID: data/... (exit 0). Sửa một ô impact thành 'high' → 'Row 4: invalid impact' + exit 1
python scripts/summarize_decisions.py data/decision_inventory_example.csv
# → 4 bảng: by function / by impact / analysis types / bảng Critical-High (đọc cột max_data_latency = spec pipeline)
pytest -q
Bài tập
DỄ, Sửa bug báo trùng lặp giả: khi decision_id rỗng, chuỗi "" vẫn bị ids.add() nên dòng thiếu id thứ hai bị báo thêm 'duplicate'. Đưa ids.add(did) vào nhánh else. Đạt khi: test mới với CSV có 2 dòng thiếu decision_id chỉ sinh 2 lỗi 'missing', không có chữ 'duplicate'.
TRUNG BÌNH, Thêm VALID_LATENCY = {realtime, near_realtime, hourly, daily, weekly, monthly, quarterly} và rule: quyết định Critical mà latency là monthly/quarterly → cảnh báo. Cuối báo cáo in tổng realtime vs batch, fail nếu < 5 mỗi loại (đúng DoD tuần 1). Đạt khi: file mẫu vẫn PASS; CSV chỉ có 3 quyết định realtime → exit 1 với thông báo về DoD.
KHÓ, Viết scripts/decision_coverage.py: đọc decision_inventory + sample_applications, parse cột required_inputs (phân tách bằng ;), kiểm mỗi input có tồn tại thành cột trong CSV dữ liệu không. In coverage matrix: quyết định nào đã có dữ liệu, quyết định nào đang 'mù'. Đạt khi: chỉ ra được ít nhất một quyết định Critical chưa có dữ liệu hỗ trợ + đề xuất event cần track. Đây là bản nháp đầu tiên của decision-to-data matrix (artifact Tuần 4).
Tài liệu chi tiết: Modules/repo-walkthrough/tuan-01-repo.md
Kiểm tra nhanh
Bài này có 3 câu hỏi kiểm tra nhanh. Tạo tài khoản miễn phí để làm quiz và lưu tiến độ.