Skip to content

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ốc

Ba luật của mô-đun ​

  1. OKR không định nghĩa lại năng lực. Nó trỏ vào capabilities và value_stream_stages bằng id, đúng như kpis trước đây.
  2. 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.
  3. kpi_id là nguồn gốc, không phải bản sao. Sau 0016, 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ạiSố lượngNội dung
Objective theo năng lực7574 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ình3Người học · Phụ huynh · Giáo viên — Key Result là chỉ số giá trị neo vào chặng
Key Result235Chuyể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ược27strategic_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_measuredChưa có current hoặc baseline
achievedĐã đi ≥ 100% quãng đường
on_track≥ 70%
at_risk≥ 40%
off_trackDướ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_id cần architect hoặc executive — 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ối objective_capabilities / objective_priorities.
  • key-results cố 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, PATCH và DELETE.
  • kpis khô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ìnhVai trò
/okrToàn bộ Objective, nhóm theo miền năng lực; bốn ô số liệu; lọc "Cần chú ý"
/okr/:codeMộ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/:codeThẻ 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/:codeMục tiêu chiến lược hiện các Objective vận hành nối lên nó
/value-streams/:stream/:stageChỉ 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ến

Trì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.