code wiki / _hdl_build / nx_hr_team.nx
nx_hr_team.nx source
↩ module page · 87 lines · 4576 B
1// nx_hr_team.nx -- NISHI HR, team-org module (S-class HR rung 2): OWN the RACI + detect STAFFING gaps + flag
2// TRAINING/competency gaps on the Nishi team. Composes nx_hr's record helpers. Registries (TSV, append-friendly):
3// RACI: area <TAB> role <TAB> letter (letter in R|A|C|I) -- who is Responsible/Accountable/Consulted/Informed
4// role-reqs: role <TAB> competency -- competencies a role REQUIRES (the training bar)
5// member-skill:member <TAB> competency -- competencies a member has ATTESTED
6// The RACI invariant (the thing HR keeps GREEN): every active area has EXACTLY ONE Accountable role AND >=1
7// Responsible role. A violation = a STAFFING GAP HR flags. A member missing a competency their role requires =
8// a TRAINING GAP HR flags. Deny/flag-by-default: an area with no A, or a member with no attestation, flags.
9// license_tier: ORIGINAL
10import "nx_hr.nx" // hr_read / hr_line_end / hr_field_end / hr_eqrange (reused; DRY)
11import "nx_syscalls.nx"
12
13const HRT_A: i64 = 65 // 'A' Accountable
14const HRT_R: i64 = 82 // 'R' Responsible
15
16// count RACI rows for `area` whose letter (field2, first char) == letter_char.
17func hrt_count_letter(raci_path: *u8, area: *u8, arealen: i64, letter_char: i64) -> i64 {
18 let buf: *u8 = sys_mmap(262144); let n: i64 = hr_read(raci_path, buf, 262144)
19 var c: i64 = 0; var i: i64 = 0
20 while i < n {
21 let le: i64 = hr_line_end(buf, i, n)
22 let f0e: i64 = hr_field_end(buf, i, le)
23 if hr_eqrange(buf, i, f0e, area, arealen) == 1 {
24 let f1e: i64 = hr_field_end(buf, f0e+1, le) // role
25 let f2s: i64 = f1e+1 // letter field start
26 if f2s < le { if (buf[f2s] as i64) == letter_char { c = c + 1 } }
27 }
28 i = le + 1
29 }
30 return c
31}
32// RACI complete for an area = EXACTLY ONE Accountable AND >=1 Responsible (the invariant HR keeps GREEN).
33func hrt_raci_complete(raci_path: *u8, area: *u8, arealen: i64) -> i64 {
34 if hrt_count_letter(raci_path, area, arealen, HRT_A) != 1 { return 0 }
35 if hrt_count_letter(raci_path, area, arealen, HRT_R) < 1 { return 0 }
36 return 1
37}
38// STAFFING GAP on an area = the RACI invariant is violated (no/duplicate Accountable, or no Responsible). 1=gap.
39func hrt_staffing_gap(raci_path: *u8, area: *u8, arealen: i64) -> i64 {
40 if hrt_raci_complete(raci_path, area, arealen) == 1 { return 0 }
41 return 1
42}
43
44// is there a line in `path` with field0==key AND field1==val? (role-req or member-skill lookup)
45func hrt_pair_exists(path: *u8, key: *u8, keylen: i64, val: *u8, vallen: i64) -> i64 {
46 let buf: *u8 = sys_mmap(262144); let n: i64 = hr_read(path, buf, 262144)
47 var i: i64 = 0
48 while i < n {
49 let le: i64 = hr_line_end(buf, i, n)
50 let f0e: i64 = hr_field_end(buf, i, le)
51 if hr_eqrange(buf, i, f0e, key, keylen) == 1 {
52 let f1s: i64 = f0e+1; let f1e: i64 = hr_field_end(buf, f1s, le)
53 if hr_eqrange(buf, f1s, f1e, val, vallen) == 1 { return 1 }
54 }
55 i = le + 1
56 }
57 return 0
58}
59// TRAINING GAP for (member in role) = the member is MISSING any competency the role REQUIRES. 1=undertrained.
60// Reads role-reqs (role<TAB>competency); for each required competency, checks member-skill (member<TAB>competency).
61func hrt_training_gap(req_path: *u8, skill_path: *u8, role: *u8, rolelen: i64, member: *u8, memberlen: i64) -> i64 {
62 let buf: *u8 = sys_mmap(262144); let n: i64 = hr_read(req_path, buf, 262144)
63 var i: i64 = 0
64 while i < n {
65 let le: i64 = hr_line_end(buf, i, n)
66 let f0e: i64 = hr_field_end(buf, i, le)
67 if hr_eqrange(buf, i, f0e, role, rolelen) == 1 {
68 let f1s: i64 = f0e+1; let f1e: i64 = hr_field_end(buf, f1s, le)
69 let comp: *u8 = ((buf as i64) + f1s) as *u8
70 if hrt_pair_exists(skill_path, member, memberlen, comp, f1e - f1s) == 0 { return 1 } // a required competency is missing
71 }
72 i = le + 1
73 }
74 return 0
75}
76// how many DISTINCT competencies does `role` require? (the training bar size; 0 = role has no defined bar = itself a gap to flag)
77func hrt_role_req_count(req_path: *u8, role: *u8, rolelen: i64) -> i64 {
78 let buf: *u8 = sys_mmap(262144); let n: i64 = hr_read(req_path, buf, 262144)
79 var c: i64 = 0; var i: i64 = 0
80 while i < n {
81 let le: i64 = hr_line_end(buf, i, n)
82 let f0e: i64 = hr_field_end(buf, i, le)
83 if hr_eqrange(buf, i, f0e, role, rolelen) == 1 { c = c + 1 }
84 i = le + 1
85 }
86 return c
87}