# Data contract — questions.json `questions.json` là **nguồn duy nhất của ngân hàng câu hỏi**, không phải nơi lưu câu trả lời participant. HTML dùng `fetch('./questions.json')`; Markdown là view sinh bởi `build.py`. Không copy câu hỏi vào script HTML. ## Quy tắc cho người và agent sửa tiếp 1. Đọc README, clarification và guide trước; hiểu đây là draft US/English. 2. Sửa `questions.json`. Giữ ID khi sửa cách diễn đạt cùng một mục đích; tạo ID mới nếu tách câu hoặc đổi ý nghĩa đáng kể. Không đánh lại số toàn bank chỉ để xếp đẹp. 3. Nếu bỏ câu đã dùng trong nghiên cứu, đổi `status` thành `retired`, giữ lịch sử trong bản archive nghiên cứu. Phiên hiện tại chỉ hiển thị các câu khác retired. 4. Mọi câu phải có condition, phương thức, nhóm đối tượng, mục tiêu và nguồn. Ghi rõ `BRIEF` cho câu đóng không dựa trên tài liệu sản phẩm; không bịa source. 5. Chạy `python3 build.py` để validate và sinh hai file Markdown. Reload HTML đọc JSON mới; không cần build frontend. 6. Nếu đổi ID/flow, sửa `06-session-guides.md` và `study_flows` trong JSON cùng lúc. Không đổi ID câu đã thu thập trong một cohort; version instrument trước thay đổi. ## Root structure | Key | Kiểu | Ý nghĩa | |---|---|---| | `schema_version` | string | `1.0.0`; tăng version khi đổi contract | | `metadata` | object | Title, owner, updated_at, market, languages, summary và stimuli | | `groups` | array | `{id, label_vi}`; ID ổn định G01… | | `decisions` | array | `{id, label_vi}`; D1–D6 | | `original_prompts` | array | `{id, text_vi}`; mapping các thắc mắc Huy | | `study_flows` | object | Tập Q-ID cho preset Survey core; wording lưu ở questions | | `questions` | array | Ngân hàng theo schema bên dưới | ## Mỗi question | Field | Kiểu / allowed | Ý nghĩa | |---|---|---| | `id` | string, `Q` + digits; unique | Khóa ổn định | | `group_id` | string, có trong groups | Nhóm thông tin | | `question_en` | non-empty string | Câu dùng với phụ huynh/trẻ, English | | `audience_vi` | non-empty string | Nhóm đủ điều kiện trả lời, tiếng Việt | | `precondition_vi` | non-empty string | Điều kiện trải nghiệm trước khi hỏi: đã xem nội dung nào, ai đã thực hiện bước nào, thời lượng tối thiểu nếu có; không đòi hoàn thành thành công nếu cần khảo sát thất bại | | `answer_format_vi` | non-empty string | Text/scale/options/rank/observation/optional media | | `methods` | array, Survey / Interview | Đúng một phương thức ưu tiên; diary/quan sát nằm trong Interview | | `decision_id` | có trong decisions | Quyết định được hỗ trợ | | `priority` | P0 / P1 / P2 | Cần khi đúng nhánh / đào sâu / tùy chọn | | `stage` | Baseline / Concept / Post-use / Pre/Post-use | Tag để tìm nhanh; precondition vẫn là điều kiện chính xác | | `source_ids` | array | E01–E14, W01/W02 hoặc BRIEF; evidence register | | `facilitator_note_vi` | non-empty string | Probe, giới hạn, cách tránh bias; không đọc như câu hỏi | | `origin_ids` | integer array | Truy ngược thắc mắc; có thể trống với closing question | | `status` | draft / ready / retired | Trạng thái instrument, không phải kết quả validation | ## Mở trang Từ folder này chạy: ```sh python3 -m http.server 8766 --bind 127.0.0.1 ``` Mở [http://127.0.0.1:8766/](http://127.0.0.1:8766/). Không cần Node/npm/internet/CDN. Chỉ serve folder này; không serve toàn workspace có tài liệu riêng tư. Mở `file://` sẽ hiện hướng dẫn local server thay vì bảng trống. CSV theo bộ lọc, sort và cột đang hiển thị; không ghi trở lại JSON. ## Assumptions & Confidence Data hiện là planning draft; không chứa PII. HTML có thể dùng `fetch` khi chạy bằng local server. Confidence cao về contract; khi sửa schema cần cập nhật validator và renderer đồng thời. ## Nghĩa của pre-condition — Huy xác nhận `precondition_vi` trả lời: participant phải đã xem hoặc trải qua điều gì để có cơ sở trả lời? Ví dụ: đã xem video/landing page concept; đã tự thử pairing/onboarding; đã tạo một mission; trẻ đã thử mission EF và parent biết diễn biến. Không dùng field này để chứa randomization, cách probe hoặc lưu ý phân tích; những nội dung đó nằm ở `facilitator_note_vi`. Phân biệt “đã thử” với “đã làm thành công”. Câu tìm khó khăn onboarding cần giữ người setup thất bại. Câu hỏi lý do không mở dashboard không yêu cầu đã mở dashboard. Với tác vụ quan sát trực tiếp, pre-condition là trạng thái sẵn sàng trước tác vụ, không yêu cầu đã làm tác vụ đó. ## Presentation và tag trải nghiệm - `preconditions`: danh mục `{id, label_vi}`; `questions[].precondition_ids`: danh sách ID tag dùng cho chip và lọc. Giữ `precondition_vi` làm điều kiện chi tiết. Tags là chỉ mục tìm kiếm, không phải biểu thức eligibility: Q60 có hai nhánh dashboard thật HOẶC mẫu; Q55 setup HOẶC review. Chế độ AND/OR của bộ lọc chỉ xét membership của tag. - `presentation.uncertainties`: các điều chưa chắc → thông tin cần thu → quyết định, liên kết nhóm câu hỏi. - `presentation.criteria` và `presentation.screeners`: dữ liệu hiển thị trong tab nghiên cứu, được đối chiếu từ 04-recruitment-screener.md. Khi sửa tuyển mẫu, cập nhật cả JSON và tài liệu này để nội dung presentation không lệch. - `study_flows.interview_concept` / `interview_trial`: thứ tự menu guide cho hai nhánh, không phải mọi câu đều bắt buộc. Survey core vẫn theo thứ tự `survey_core.question_ids`. - Tab phương thức dùng câu chung có gán phương thức tương ứng, không chỉ các câu exclusive. Mở rộng “Toàn bộ” là ngân hàng theo ID, không phải flow đã chốt. ## Câu hỏi song ngữ và màu chữ chip `questions[].question_vi` là bản dịch tiếng Việt cho review/thuyết trình, giữ cùng ID và nghĩa với `question_en`. HTML hiển thị EN và VI trong cùng ô; tìm kiếm và CSV gồm cả hai ngôn ngữ. Markdown sinh hai cột tương ứng. Nghiên cứu tại Mỹ vẫn dùng instrument tiếng Anh. `preconditions[].text_color` là màu chữ chip (hex), ổn định theo tag; nền và viền chip giữ chung. Khi chọn chip lọc, dấu ✓ và vòng chọn báo trạng thái, màu chữ vẫn giữ nguyên. ## Nhóm parent khác pre-condition `parent_segments` là danh mục `{id,label_vi,description_vi}`; mỗi question có `parent_segment_ids`. Familiarity là kinh nghiệm trước nghiên cứu; Big feelings / Routine / Focus là nhu cầu gia đình có thể chồng lấp. Mapping nhu cầu là đề xuất để phân tích/hỏi sâu, không phải chỉ tuyển người có pain. “Mọi parent” giữ cohort đối chứng không có khó khăn. Riêng Q13 yêu cầu F2 từng chơi care loop. `audience_vi` giữ mô tả người trả lời; `respondent_role` phân biệt parent với child_with_guardian cho Q45/Q47. HTML hiển thị nhóm parent bằng chip và lọc theo segment ID. Không đặt “đã dùng thử”, “chỉ xem demo”, “đã setup” trong danh mục parent; các trạng thái đó thuộc `precondition_ids` và `precondition_vi`. ## Screener setup có cấu trúc `presentation.screeners` hiện lưu id, page, question_en, question_vi, type (Pick One / Short answer), required, randomize, add_other, key_question, applies_to, display_condition và answers[{label_en,label_vi,qualification,note}]. qualification chỉ Accept/Reject; review thủ công ở note. Đây là nguồn bản setup hiện hành, 11-screener-setup.md là bản đọc; 04 giữ tổng quan tuyển mẫu. `parent_segments[].axis` phân biệt scope, familiarity và nowa_lens. Năm lens được xác minh tại 10-parent-persona-source.md. Mapping câu hỏi tới lens là phạm vi phân tích đề xuất, không suy ra persona KYC của người tham gia. ## Dạng câu hỏi và tag không trùng lặp `google_form_types` là danh mục loại Google Forms; `form_type_ids` là một hoặc nhiều loại để triển khai item; `form_setup_vi` hướng dẫn tách field, nhánh, upload hoặc ghi nhận interview. `answer_format_vi` giữ nội dung/thang/đơn vị cần thu, khác với loại control. Nguồn: https://support.google.com/docs/answer/7322334?hl=en (đối chiếu 08/10/2026). Ranking không phải loại native; Q73/Q74 dùng giải pháp chọn tối đa 3 rồi ghi thứ tự, cần kiểm tra nhất quán. Quan sát thực tế không thể thay bằng một form. Nếu `parent_segment_ids` có all thì danh sách chỉ chứa all. Câu chung không gắn thêm 5 lens. Lọc nhóm bao gồm câu gắn nhóm đó và câu all. Màu chữ tag theo axis: scope xám, familiarity xanh, nowa_lens tím. Không gán lens riêng chỉ vì câu hỏi nói về một feature. ## Đáp án và ví dụ trả lời `answer_blocks` trong mỗi câu gồm title_vi, mode (single/multiple), options[{en,vi}], note_vi. HTML hiển thị toàn bộ đáp án dưới câu hỏi; CSV/tìm kiếm gồm cả đáp án. Các danh sách động (ngày diary, feature đã dùng) được ghi rõ cần điền/chọn theo participant, không giả là danh sách đã chốt. `example_answer_vi` là ví dụ giả định cho nội bộ; không phải dữ liệu participant, không đưa làm gợi ý trước khi participant trả lời. HTML dùng cột này thay Chi tiết câu trả lời. `answer_format_vi` và `form_setup_vi` vẫn giữ làm metadata nội bộ nhưng không hiển thị trong các cột này; cột Dạng câu hỏi chỉ có nhãn loại control. ## Phương thức = phân bổ tối ưu `methods` hiện bắt buộc có đúng một giá trị Survey hoặc Interview, là phương thức ưu tiên theo mục tiêu bằng chứng, chất lượng và chi phí triển khai. `method_reason_vi` giải thích từng lựa chọn. `compatible_methods` lưu khả năng sử dụng trước đây chỉ để tham khảo nội bộ; không dùng để lọc hoặc phân bổ nghiên cứu. Flow và tab theo methods ưu tiên. Survey core giữ 17 câu; các nhánh interview bỏ những item đã phân bổ Survey, giữ probe/quan sát sâu. Diary là touchpoint trong project Interview. Đây là đề xuất phân bổ cần pilot, không có nghĩa phương thức khác không thể đặt câu này. ## Journey & interview context `presentation.journey` gồm id/title/actor/action/uncertainty/evidence/preparation/question_ids; bao phủ bank, một câu có thể nhiều bước. Nút từng bước highlight theo Q-ID; dropdown journey lọc độc lập, không tự suy participant đủ pre-condition. `presentation.decision_examples` là tình huống giả định → quyết định → vai trò đề xuất, không phải findings. `presentation.interview_context` là hướng dẫn điều phối ngoài data table, bảo đảm baseline/stimulus dù methods ưu tiên Survey. Q93–Q98 là probe Interview bổ sung đã được Huy yêu cầu, source BRIEF, chưa có dữ liệu thực. ## Warm-up `presentation.warmups`: survey/interview_concept/interview_trial, mỗi phần title/note/rows[{id,type_vi,question_en,question_vi,note_vi}]. Bảng mở đầu tách khỏi ngân hàng bằng chứng; tham chiếu Q01/Q05 để không hỏi lặp. Không cộng warm-up vào số câu bank, không thêm câu bắt buộc cho survey. ## Điều hướng journey trong HTML Canvas ngang gồm chín node nối liên tiếp. Kéo vùng trống bằng chuột, vuốt ngang hoặc dùng thanh cuộn phía đáy để xem tiếp. Click node mở side panel bên phải trong canvas và highlight câu liên quan; click lại bước đang chọn để bỏ highlight và đóng panel. Panel giữ nguyên khi kéo canvas; nút đóng chỉ đóng panel. Nút journey trong câu hỏi có cùng hành vi. Highlight và bộ lọc là hai trạng thái độc lập: click sơ đồ không đổi giá trị bộ lọc hay số dòng hiển thị. Dropdown “Lọc theo user flow” lọc giao với phạm vi study và các bộ lọc khác; chọn “Tất cả bước” để bỏ riêng bộ lọc này. “Bỏ highlight” chỉ xóa highlight; “Đặt lại” xóa cả hai. Dữ liệu liên kết lấy từ `presentation.journey[].question_ids`, không lưu bản sao trên mỗi câu. Journey là khung nghiên cứu; điều kiện thực tế của từng câu vẫn nằm ở precondition. ## Familiarity: ba mức loại trừ nhau F0 (`unfamiliar`): Chưa biết concept. F1 (`aware_not_played`): Biết concept, chưa từng chơi. F2 (`experienced`): Đã từng chơi. Không dùng familiar làm nhóm cha đồng thời với experienced. Câu áp dụng mọi mức không lặp tag familiarity; nếu không giới hạn bất kỳ dimension nào thì dùng `all` (Mọi parent). Q13 chỉ dành cho F2. Bộ lọc parent kiểm tra giới hạn trên đúng dimension được chọn; thiếu tag ở dimension đó nghĩa là không giới hạn dimension đó. ## Topic & Journey trên bảng Cột `group_id` hiển thị chủ đề và chip journey với đầy đủ mã + tên bước. Journey không còn nằm trong ô câu hỏi. Mã D1–D6 và cột mục tiêu được bỏ khỏi giao diện bảng; mục tiêu đầu trang chỉ hiện tên. `decision_id` vẫn lưu trong JSON để truy vết nội bộ. ## Điều chỉnh sau audit09/10 `presentation.survey_offer_protocol` chứa title và steps[{when,text}] để hiển thị bước xác nhận offer giữa Q31 và Q32/Q33. Screener thêm S07a về affiliation, tách khỏi exposure S07. Dropdown parent ẩn lens chưa có câu giới hạn riêng, danh mục vẫn có trong chú giải. CSV/search Topic & Journey chứa cả topic và id/title journey. Desktop cố định3 cột; viewport≤700px chỉ cố định cột đầu.