Giao diện
OKR — Objective và Key Result
Compass từng đo năng lực bằng một danh sách KPI phẳng. KPI trả lời "con số này đang thế nào"; nó không bao giờ trả lời "chúng ta đang muốn điều gì xảy ra, và làm sao biết nó đã xảy ra".
Từ 0015_okr.sql và 0016_okr_seed.sql, toàn bộ 235 KPI đã trở thành Key Result, và mỗi Key Result nằm dưới một Objective.
Mục tiêu chiến lược strategic_objectives — số ít mục tiêu cấp doanh nghiệp
└── Objective objectives — một cho mỗi năng lực, một cho mỗi hành trình
└── Key Result key_results — thước đo, chuyển từ KPI sang
└── kpi_id kpis — bản ghi gốc, giữ lại làm nguồn gốcBa luật của mô-đun
- OKR không định nghĩa lại năng lực. Nó trỏ vào
capabilitiesvàvalue_stream_stagesbằng id, đúng nhưkpistrước đây. - Key Result giữ nguyên điểm neo của KPI nó chuyển từ đó, nên mọi màn hình từng hiện KPI đều hiện Key Result ở đúng chỗ cũ. Objective là cách nhóm lại, không phải điểm neo.
kpi_idlà nguồn gốc, không phải bản sao. Sau0016, Key Result là nơi thước đo sinh sống;kpisở lại như hồ sơ ghi thước đo đó đến từ đâu.
Dữ liệu hiện có
| Loại | Số lượng | Nội dung |
|---|---|---|
| Objective theo năng lực | 75 | 74 năng lực đánh giá được (level > 1) mỗi năng lực một Objective ba Key Result, cộng một Objective ở cấp lĩnh vực — CAP-08 · Giáo viên & Nhân sự — chỉ có hai (nó chỉ có hai KPI) |
| Objective theo hành trình | 3 | Người học · Phụ huynh · Giáo viên — Key Result là chỉ số giá trị neo vào chặng |
| Key Result | 235 | Chuyển 1–1 từ KPI, giữ tên, đơn vị, người chịu trách nhiệm, kỳ đo |
| Nối lên chiến lược | 27 | strategic_objective_id suy ra từ objective_capabilities |
direction — nửa còn thiếu của một KPI
45 trong số 235 thước đo là loại càng thấp càng tốt: số ngày tới khi trả lời, chi phí mỗi lượt liên hệ, tỷ lệ người học rời đi trong tháng đầu. Một thanh tiến độ mặc định "càng cao càng tốt" sẽ đọc ngược chúng, và một thước đo đang hỏng sẽ hiện ra như đang thành công.
direction (up · down) nói rõ chiều nào là thắng. Phép tính tiến độ thì không cần biết điều đó:
progress = (current − baseline) / (target − baseline)Với thước đo đi xuống, target < baseline, nên cùng một phép trừ vẫn cho ra phần quãng đường đã đi. direction phục vụ người đọc (mũi tên, cách diễn giải), không phục vụ phép tính.
scripts/checks.sql chặn trường hợp hai thứ mâu thuẫn: direction = 'down' mà target > baseline là lỗi build, không phải điều phát hiện sau trên giao diện.
Luật về con số
Mục tiêu là cam kết. Baseline và giá trị hiện tại là phép đo.
Vì vậy scripts/okr.mjs nêu target cho cả 235 Key Result, còn baseline và current chỉ được mang sang từ KPI. KPI nào chưa từng được đo thì Key Result nói thẳng là chưa đo (status = 'not_measured') thay vì hiện một con số bịa.
Hiện tại: 22/235 Key Result đã có phép đo. Khoảng trống đó là một sự thật về hệ thống đo lường của Conan, và màn hình /okr hiện nó ngay trên đầu.
status của Key Result
Tính một lần lúc migration, từ chính con số trong kpis:
| Trạng thái | Điều kiện |
|---|---|
not_measured | Chưa có current hoặc baseline |
achieved | Đã đi ≥ 100% quãng đường |
on_track | ≥ 70% |
at_risk | ≥ 40% |
off_track | Dưới 40% |
Ngưỡng đọc theo phần quãng đường đã đi, không theo thời gian còn lại của kỳ.
Cột status trong D1 là ảnh chụp lúc chuyển đổi — cơ sở dữ liệu không tính lại khi có người nhập current mới. Nên giao diện tự suy ra trạng thái từ con số (src/lib/okr.ts · statusOf) bằng đúng bảng ngưỡng trên, để thanh tiến độ và cái nhãn bên cạnh nó không bao giờ nói hai điều khác nhau.
Quyền ghi
objectives và key-results theo phạm vi Brand, nhưng có hai luật riêng:
- Đặt
objectives.strategic_objective_idcầnarchitecthoặcexecutive— nó quyết định màn hình Chiến lược cấp doanh nghiệp hiện gì, đúng luật của các bảng nốiobjective_capabilities/objective_priorities. key-resultscố tình không lấy brand từ Objective cha: một Key Result là con số của một Brand nằm dưới một Objective cấp doanh nghiệp (15/235 Key Result như vậy). Đổi lại, Worker đòi quyền ghi trên cả hai — Brand của bản ghi và Brand của Objective cha — ởPOST,PATCHvàDELETE.kpiskhông còn là tài nguyên CRUD: hai bảng cùng ghi được thì con số sẽ lệch.
Giao diện
| Màn hình | Vai trò |
|---|---|
/okr | Toàn bộ Objective, nhóm theo miền năng lực; bốn ô số liệu; lọc "Cần chú ý" |
/okr/:code | Một Objective: Key Result, mục tiêu chiến lược nó phục vụ, năng lực hoặc hành trình nó đo |
/model/:code | Thẻ OKR thay cho bảng KPI cũ; năng lực cấp miền gộp OKR của các năng lực con |
/strategy/:code | Mục tiêu chiến lược hiện các Objective vận hành nối lên nó |
/value-streams/:stream/:stage | Chỉ số giá trị của chặng, nay mở sang Objective hành trình |
Sửa dữ liệu
Nguồn là api.conan1.com/scripts/okr.mjs — sửa ở đó rồi chạy:
bash
node scripts/okrSeed.mjs # sinh lại migrations/0016_okr_seed.sql
npm run verify # áp toàn bộ migration lên D1 local và kiểm tra bất biếnTrình sinh thất bại nếu còn một KPI nào không có Key Result, nếu hai Objective cùng nhận một KPI, hoặc nếu một Key Result trỏ vào KPI không tồn tại. "Chuyển toàn bộ KPI" là một bất biến của build, không phải một lời hứa.
0016 được viết dưới dạng INSERT ... SELECT FROM kpis, không phải hàng chữ cứng: tên, đơn vị, người chịu trách nhiệm và — quan trọng nhất — baseline và current được đọc từ KPI tại thời điểm áp migration, nên không đè lên bất kỳ phép đo nào đã nhập sau khi seed. Cả hai file đều cộng dồn và chạy lại được.